如何在flutter中使用ffmpeg为视频添加字幕?

问题描述 投票:0回答:1

我正在使用 flutter_ffmpeg_kit_full 包向我的视频添加字幕。首先我循环遍历所有单词并创建一个 srt 文件并将其存储在临时文件夹中。

 Future<String> _createSrtFile() async {
    String filePath = await getSrtOutputFilePath();

    final file = File(filePath);
    final buffer = StringBuffer();

    for (int i = 0; i < widget.words.length; i++) {
      final word = widget.words[i];
      final startTime = _formatSrtTime(word['startTime'].toDouble());
      final endTime = _formatSrtTime(word['endTime'].toDouble());
      final text = word['word'];

      buffer.writeln('${i + 1}');
      buffer.writeln('$startTime --> $endTime');
      buffer.writeln('$text');
      buffer.writeln('');
    }

    await file.writeAsString(buffer.toString());
    return filePath;
  }

  String _formatSrtTime(double seconds) {
    final int hours = seconds ~/ 3600;
    final int minutes = ((seconds % 3600) ~/ 60);
    final int secs = (seconds % 60).toInt();
    final int millis = ((seconds - secs) * 1000).toInt() % 1000;

    return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${secs.toString().padLeft(2, '0')},${millis.toString().padLeft(3, '0')}';
  }

然后我创建一个 future 函数来使用 ffmpeg 命令处理导出

Future<void> _exportVideo() async {
    final hasPermission = await _requestStoragePermission();
    if (!hasPermission) {
      ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Storage permission denied')));
      return;
    }

    setState(() {
      _isProcessing = true;
      _outputFilePath = "";
    });

    try {
      final srtFilePath = await _createSrtFile();

      String videoPath = widget.videoFile!.path;

      String _outputPath = await getOutputFilePath();

      final command =
          '-i $videoPath -vf "drawtext="text=\'Stack Overflow\':fontcolor=white:fontsize=24:box=1:[email protected]:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2"" -codec:a copy $_outputPath';

      // final cmd = [
      //   '-i',
      //   videoPath,
      //   '-preset',
      //   'ultrafast',
      //   '-vf',
      //   'subtitles=$srtFilePath:force_style=\'Fontname=Roboto Bold,FontSize=30,MarginV=70,PrimaryColour=ffffff,OutlineColour=000000\'',
      //   _outputPath
      // ];
      // FFmpegKit.executeWithArguments(cmd)

      print('Executing FFmpeg command: $command');

      await FFmpegKit.execute(command).then((session) async {
        final returnCode = await session.getReturnCode();
        final output = await session.getOutput();
        final failStackTrace = await session.getFailStackTrace();

        print('FFmpeg Output: $output');
        if (failStackTrace != null) {
          print('FFmpeg Fail StackTrace: $failStackTrace');
        }

        if (ReturnCode.isSuccess(returnCode)) {
          setState(() {
            _outputFilePath = _outputPath;
          });
          ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Export successful!')));
        } else {
          final logs = await session.getLogsAsString();
          print('FFmpeg Logs: $logs');
          ScaffoldMessenger.of(context)
              .showSnackBar(const SnackBar(content: Text('Export failed!')));
        }
      });
    } catch (e) {
      print('Error: $e');
      ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Export failed with error: $e')));
    } finally {
      setState(() {
        _isProcessing = false;
      });
    }
  }

我导出时没有字幕,效果很好。但问题是当我尝试使用字幕时。我不知道我犯了什么错,但这段代码无法导出。你能帮我一下吗?这也是 srt 和视频本身的路径。

  Future<String> getOutputFilePath() async {
    final Directory? downloadsDir = await getDownloadsDirectory();
    final timestamp = DateTime.now().millisecondsSinceEpoch;
    final name = "output-$timestamp.avi";
    return '${downloadsDir!.path}/$name'; // Save in downloads folder
  }

  Future<String> getSrtOutputFilePath() async {
    final Directory? downloadsDir = await getDownloadsDirectory();
    final timestamp = DateTime.now().millisecondsSinceEpoch;
    final name = "caption-$timestamp.srt";
    return '${downloadsDir!.path}/$name'; // Save in downloads folder
  }
flutter dart ffmpeg video-processing
1个回答
0
投票

我认为文本部分正在添加叠加层。尝试下面的部分,看看这是否适合您。

Future<void> _exportVideo() async {
  final hasPermission = await _requestStoragePermission();
  if (!hasPermission) {
    ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Storage permission denied')));
    return;
  }

  setState(() {
    _isProcessing = true;
    _outputFilePath = "";
  });

  try {
    final srtFilePath = await _createSrtFile();
    String videoPath = widget.videoFile!.path;
    String _outputPath = await getOutputFilePath();

    // Use the correct FFmpeg command for adding subtitles
    final command = '-i $videoPath -vf subtitles=$srtFilePath -c:a copy $_outputPath';

    print('Executing FFmpeg command: $command');

    await FFmpegKit.execute(command).then((session) async {
      final returnCode = await session.getReturnCode();
      final output = await session.getOutput();
      final failStackTrace = await session.getFailStackTrace();

      print('FFmpeg Output: $output');
      if (failStackTrace != null) {
        print('FFmpeg Fail StackTrace: $failStackTrace');
      }

      if (ReturnCode.isSuccess(returnCode)) {
        setState(() {
          _outputFilePath = _outputPath;
        });
        ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Export successful!')));
      } else {
        final logs = await session.getLogsAsString();
        print('FFmpeg Logs: $logs');
        ScaffoldMessenger.of(context)
            .showSnackBar(const SnackBar(content: Text('Export failed!')));
      }
    });
  } catch (e) {
    print('Error: $e');
    ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Export failed with error: $e')));
  } finally {
    setState(() {
      _isProcessing = false;
    });
  }
}

命令已更改我已删除了绘图文本部分。

© www.soinside.com 2019 - 2024. All rights reserved.