createGifFromImages method

Future<Uint8List> createGifFromImages(
  1. List<XFile> rawImages, {
  2. int fps = 1,
  3. int? width,
  4. int? height,
  5. bool forceOriginalAspectRatio = true,
  6. List<GifyTextMessage>? textMessages,
})

Implementation

Future<Uint8List> createGifFromImages(
  List<XFile> rawImages, {
  int fps = 1,
  int? width,
  int? height,
  bool forceOriginalAspectRatio = true,
  List<GifyTextMessage>? textMessages,
}) async {
  final tempDir = await getTemporaryDirectory();
  // REF: https://github.dev/arthenica/ffmpeg-kit-test/blob/ce66bf7c1ab2978579405d0a5b06f38936c0893f/flutter/test-app-pub/lib/video_util.dart#L46-L48
  await FFmpegKitConfig.setFontDirectoryList(
      [tempDir.path, "/system/fonts", "/System/Library/Fonts"], {});
  const fontName = 'Roboto Bold';
  final String currentTime = DateTime.now().millisecondsSinceEpoch.toString();
  final textMessagesCommand = textMessages == null
      ? ''
      : textMessages
          .map((message) =>
              'drawtext=font=\'$fontName\':fontsize=${message.fontSize}:fontcolor=0x${message.fontColor.toHex()}:text="${message.text}":x=${message.x}:y=${message.y}')
          .join(',');
  for (int i = 0; i < rawImages.length; i++) {
    final image = rawImages[i];
    late String path;
    if (image.path.isEmpty) {
      await File('${tempDir.path}/$currentTime-$i.${image.mimeType ?? 'png'}')
          .writeAsBytes(await image.readAsBytes());
      continue;
    } else {
      path = image.path;
    }
    final String convertCommand =
        '-i $path -vf scale=w=${width ?? height ?? -1}:h=${height ?? width ?? -1}${forceOriginalAspectRatio ? ':force_original_aspect_ratio=decrease' : ''} ${tempDir.path}/$currentTime-$i.png';
    final convertSession = await FFmpegKit.execute(convertCommand);
    final convertReturnCode = await convertSession.getReturnCode();
    if (!ReturnCode.isSuccess(convertReturnCode)) {
      return Uint8List.fromList([]);
    }
  }

  final String gifCommand =
      '-f image2 -r $fps -i ${tempDir.path}/$currentTime-%d.png -vf "pad=width=\'max(${width ?? height ?? -1},iw)\':height=\'max(${height ?? width ?? -1},ih)\':x=-1:y=-1:color=black@0" -loop 0 ${tempDir.path}/gif_maker_result_$currentTime.gif';
  final gifSession = await FFmpegKit.execute(gifCommand);

  final gifReturnCode = await gifSession.getReturnCode();

  if (!ReturnCode.isSuccess(gifReturnCode)) {
    return Uint8List.fromList([]);
  }

  final String gifWithTextCommand =
      '-i ${tempDir.path}/gif_maker_result_$currentTime.gif${textMessagesCommand.isNotEmpty ? ' -vf $textMessagesCommand' : ''} ${tempDir.path}/gif_maker_result_${currentTime}_text.gif';
  final gifTextSession = await FFmpegKit.execute(gifWithTextCommand);

  final gifTextReturnCode = await gifTextSession.getReturnCode();

  if (!ReturnCode.isSuccess(gifTextReturnCode)) {
    return Uint8List.fromList([]);
  }

  final result =
      await File('${tempDir.path}/gif_maker_result_${currentTime}_text.gif')
          .readAsBytes();

  return result;
}