extractCover method

Future<void> extractCover({
  1. required void onCompleted(
    1. File file
    ),
  2. void onError(
    1. Object,
    2. StackTrace
    )?,
  3. String? name,
  4. String? outDir,
  5. String format = "jpg",
  6. double scale = 1.0,
  7. int quality = 100,
  8. void onProgress(
    1. Statistics
    )?,
  9. bool isFiltersEnabled = true,
})

Export this selected cover, or by default the first one, return an image File.

The onCompleted param must be set to return the exported File cover

The onError function provides the Exception and StackTrace that causes the exportation error.

If the name is null, then it uses this video filename.

If the outDir is null, then it uses TemporaryDirectory.

The format of the image to be exported, by default jpg.

The scale is scale=width*scale:height*scale and reduce or increase cover size.

The quality of the exported image (from 0 to 100 (more info))

The onProgress is called while the video is exporting. This argument is usually used to update the export progress percentage. This function return Statistics from FFmpeg session.

Set isFiltersEnabled to false if you do not want to apply any changes

Implementation

Future<void> extractCover({
  required void Function(File file) onCompleted,
  void Function(Object, StackTrace)? onError,
  String? name,
  String? outDir,
  String format = "jpg",
  double scale = 1.0,
  int quality = 100,
  void Function(Statistics)? onProgress,
  bool isFiltersEnabled = true,
}) async {
  final String tempPath = outDir ?? (await getTemporaryDirectory()).path;
  // file generated from the thumbnail library or video source
  final String? coverPath = await _generateCoverFile(quality: quality);
  if (coverPath == null) {
    if (onError != null) {
      onError(
        Exception('VideoThumbnail library error while exporting the cover'),
        StackTrace.current,
      );
    }
    return;
  }
  name ??= path.basenameWithoutExtension(file.path);
  final int epoch = DateTime.now().millisecondsSinceEpoch;
  final String outputPath = "$tempPath/${name}_$epoch.$format";

  // CALCULATE FILTERS
  final String crop = minCrop >= _min && maxCrop <= _max ? _getCrop() : "";
  final String rotation =
      _rotation >= 360 || _rotation <= 0 ? "" : _getRotation();
  final String scaleInstruction =
      scale == 1.0 ? "" : "scale=iw*$scale:ih*$scale";

  // VALIDATE FILTERS
  final List<String> filters = [crop, scaleInstruction, rotation];
  filters.removeWhere((item) => item.isEmpty);
  final String filter = filters.isNotEmpty && isFiltersEnabled
      ? "-filter:v ${filters.join(",")}"
      : "";
  // ignore: unnecessary_string_escapes
  final String execute = "-i \'$coverPath\' $filter -y $outputPath";

  // PROGRESS CALLBACKS
  FFmpegKit.executeAsync(
    execute,
    (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;
      }
    },
    null,
    onProgress,
  );
}