LeGoffMael / video_editor

A flutter package for editing video written in pure Dart with fully customizable UI. Supports crop, trim, rotation and cover selection.

Home Page:https://pub.dev/packages/video_editor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

commented

thank you for the report i will check it!

commented

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.

commented

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