FFmpegKit.executeAsync is slower than FFmpegKit.execute
jcsena opened this issue · comments
The issue reported suggests that using the executeAsync
method in the FFmpegKit
library is slower than using the execute
method. This may be unexpected, as one would typically expect the asynchronous method to be faster than the synchronous method.
Device: Readmi Note 3
Mode: Debug | Release
Video using executeAsync
_controller.exportVideo(
...
preset: VideoExportPreset.ultrafast,
isFiltersEnabled: false,
customInstruction: '-c:a aac -b:a 64k'
);
video__3.mp4
Video using execute
final command =
'-i $videoPath -ss $startValue -to $endValue -preset ultrafast -c:a aac -b:a 64k -c copy $outputPath';
await FFmpegKit.execute(command);
video__4.mp4
To address this issue, we propose adding a new parameter to the exportVideo
method that allows the user to choose between synchronous and asynchronous processing. This parameter could be a boolean value that defaults to true (async processing) but can be set to false for synchronous processing.
Thank you for your feedback and continued support.
thank you for the report i will check it!
I tried but did not see any difference between FFmpegKit.executeAsync
and FFmpegKit.execute
:(
Here is the adapted version of exportVideo()
using FFmpegKit.execute
:
Future<void> exportVideo({
required void Function(File file) onCompleted,
void Function(Object, StackTrace)? onError,
String? name,
String? outDir,
VideoExportFormat format = VideoExportFormat.mp4,
double scale = 1.0,
String? customInstruction,
void Function(Statistics, double)? onProgress,
VideoExportPreset preset = VideoExportPreset.none,
bool isFiltersEnabled = true,
}) async {
final String videoPath = file.path;
final String outputPath = await _getOutputPath(
filePath: videoPath,
name: name,
outputDirectory: outDir,
format: format,
);
final String filter = _getExportFilters(
videoFormat: format,
scale: scale,
isFiltersEnabled: isFiltersEnabled,
);
final String execute =
// ignore: unnecessary_string_escapes
" -i \'$videoPath\' ${customInstruction ?? ""} $filter ${_getPreset(preset)} $_trimCmd -y \"$outputPath\"";
debugPrint('VideoEditor - run export video command : [$execute]');
// PROGRESS CALLBACKS
if (onProgress != null) {
FFmpegKitConfig.enableStatisticsCallback((stats) {
// Progress value of encoded video
double progressValue = stats.getTime() / trimmedDuration.inMilliseconds;
onProgress(stats, progressValue.clamp(0.0, 1.0));
});
}
FFmpegKit.execute(execute).then((session) async {
final state =
FFmpegKitConfig.sessionStateToString(await session.getState());
final code = await session.getReturnCode();
if (ReturnCode.isSuccess(code)) {
onCompleted(File(outputPath));
} else {
if (onError != null) {
onError(
Exception(
'FFmpeg process exited with state $state and return code $code.\n${await session.getOutput()}'),
StackTrace.current,
);
}
return;
}
});
I think that is because I am using that command:
-ss 00:00:10 -i input.mp4 -t 30 -c copy output.mp4
-
In terms of speed, using the
-t
option is generally faster than using the-to
option because FFmpeg can stop decoding the input file once it reaches the end of the specified duration. -
When using the
-to
option, FFmpeg needs to decode the entire input file up to the specified end time, even if the trimmed portion of the video is shorter than the input file. This can be slower, especially for very large files. -
Use the
-ss
option before the -i option. This will tell FFmpeg to seek to the start time before even opening the input file, which can save time. -
-c copy
tells FFmpeg to copy the video and audio streams without re-encoding them. This is a fast and lossless way to trim a video.
that's why I think the command is faster, but -c copy
does not allow or is not compatible with other customizable commands.
The -c copy
flag is now enabled if there is no filters in the last 3.0.0.
It also introduces a new commandBuilder
function where you can customize the command exactly like you want