generateImages method

  1. @override
Future<List<NetworkToFileImage>> generateImages(
  1. {required AppModel appModel,
  2. required MediaItem item,
  3. List<Subtitle>? subtitles,
  4. SubtitleOptions? options,
  5. String? data}
)
override

If this source is non-null, this will be used as the initial function for the image field over the auto enhancement. Extra durations can be invoked and defined when initially opening the creator, to call attention to multiple durations to be used for image generation.

Implementation

@override
Future<List<NetworkToFileImage>> generateImages({
  required AppModel appModel,
  required MediaItem item,
  List<Subtitle>? subtitles,
  SubtitleOptions? options,
  String? data,
}) async {
  while (appModel.blockCreatorInitialMedia) {
    await Future.delayed(const Duration(seconds: 1), () {});
  }

  if (appModel.isProcessingEmbeddedSubtitles) {
    Fluttertoast.showToast(msg: t.processing_embedded_subtitles);
    return [];
  }

  bool useCurrentTime = false;
  if (subtitles == null && _transcriptSubtitle != null) {
    subtitles = [_transcriptSubtitle!];
  }

  if (subtitles == null && appModel.currentSubtitle.value != null) {
    subtitles ??= [appModel.currentSubtitle.value!];
    useCurrentTime = true;
  }

  List<NetworkToFileImage> imageFiles = [];
  Directory appDirDoc = await getApplicationSupportDirectory();
  String playerPreviewPath = '${appDirDoc.path}/playerImagePreview';
  Directory playerPreviewDir = Directory(playerPreviewPath);
  if (playerPreviewDir.existsSync()) {
    playerPreviewDir.deleteSync(recursive: true);
  }
  playerPreviewDir.createSync();

  String timestamp = DateFormat('yyyyMMddTkkmmss').format(DateTime.now());
  Directory imageDir = Directory('$playerPreviewPath/$timestamp');
  imageDir.createSync();

  for (int index = 0; index < subtitles!.length; index++) {
    Subtitle subtitle = subtitles[index];
    File imageFile = appModel.getPreviewImageFile(imageDir, index);

    String outputPath = imageFile.path;
    if (imageFile.existsSync()) {
      imageFile.deleteSync();
    }

    int msStart = subtitle.start.inMilliseconds;
    int msEnd = subtitle.end.inMilliseconds;
    int msMean = ((msStart + msEnd) / 2).floor();
    Duration currentTime = Duration(milliseconds: msMean);

    VlcPlayerController playerController = appModel.currentPlayerController!;
    if (useCurrentTime) {
      currentTime = Duration(
          milliseconds: playerController.value.position.inMilliseconds);
    }

    String timestamp = JidoujishoTimeFormat.getFfmpegTimestamp(currentTime);
    String inputPath = item.mediaIdentifier;
    MediaSource source = item.getMediaSource(appModel: appModel);
    if (source is PlayerYoutubeSource) {
      inputPath = await source.getDataSource(item);
    }

    String command =
        '-ss $timestamp -y -i "$inputPath" -frames:v 1 -q:v 2 "$outputPath"';

    final FlutterFFmpeg _flutterFFmpeg = FlutterFFmpeg();
    await _flutterFFmpeg.execute(command);

    String output = await FlutterFFmpegConfig().getLastCommandOutput();

    if (!output.contains('Output file is empty, nothing was encoded')) {
      while (!imageFile.existsSync()) {
        await Future.delayed(const Duration(milliseconds: 100));
      }

      NetworkToFileImage networkToFileImage =
          NetworkToFileImage(file: imageFile);

      imageFiles.add(networkToFileImage);
    }
  }

  return imageFiles;
}