AI生成SRT字幕硬烧录视频失败:FFmpegKit字体缺失问题解决
解决FFmpeg硬编码字幕时找不到字体的问题
核心问题分析
从执行日志可明确错误根源:
[Parsed_drawtext_0 @ 0xb4000077140d5380] Cannot find a valid font for the family Sans
Android环境下的FFmpeg无法直接调用系统默认字体库,必须显式指定字体文件路径才能让drawtext滤镜正常工作。此外,原代码直接将interval的时间字符串传入between(t, ...)也存在格式问题——该函数需要秒数数值,而非0:00:00.000这类时间格式。
解决方案
1. 指定系统内置字体路径
Android系统通常自带Roboto字体,固定路径为/system/fonts/Roboto-Regular.ttf,可直接在drawtext参数中指定该路径。
2. 转换时间格式为秒数
将interval中的时间字符串(如0:00:00.000)转换为秒数格式,例如:
0:00:00.000→0.00:00:04.000→4.0
3. 修正后的Dart代码
Future<void> saveSubtitle() async { emit(ExportSubtitleLoading()); String subtitleFilter = ""; // Android系统Roboto字体固定路径 const fontPath = "/system/fonts/Roboto-Regular.ttf"; for (var subtitle in subtitles!.fotmatedSubtitle!) { // 转换时间字符串为秒数 final startTimeSec = _convertTimeToSeconds(subtitle.interval![0]); final endTimeSec = _convertTimeToSeconds(subtitle.interval![1]); String text = subtitle.displayText!; // 转义文本中的单引号,避免FFmpeg命令解析错误 text = text.replaceAll("'", "\\'"); subtitleFilter += "drawtext=text='$text':enable='between(t,$startTimeSec,$endTimeSec)':x=(w-text_w)/2:y=h-30:fontsize=24:fontcolor=white:fontfile='$fontPath',"; } // 移除滤镜字符串末尾多余的逗号 if (subtitleFilter.isNotEmpty) { subtitleFilter = subtitleFilter.substring(0, subtitleFilter.length - 1); } final dir = await getTemporaryDirectory(); String outputPath = '${dir.path}/ex_vid.mp4'; final arguments = [ '-y', // 自动覆盖已存在的输出文件 '-i', inputFile, '-vf', subtitleFilter, '-c:v', 'libx264', '-c:a', 'copy', outputPath ]; await FFmpegKit.executeWithArguments(arguments).then((session) async { final returnCode = await session.getReturnCode(); if (ReturnCode.isSuccess(returnCode)) { ('The Conversion is Success').logger; emit(ExportSubtitleSuccess()); } else if (ReturnCode.isCancel(returnCode)) { ('The Conversion is Cancelled').logger; } else { emit(ExportSubtitleerror()); ('The Conversion Have an Error').logger; // 打印详细日志辅助排查 final logs = await session.getAllLogsAsString(); logs.logger; } }); } // 辅助函数:将时间字符串转换为秒数 double _convertTimeToSeconds(String timeStr) { final parts = timeStr.split(':'); final hours = double.parse(parts[0]); final minutes = double.parse(parts[1]); final seconds = double.parse(parts[2]); return hours * 3600 + minutes * 60 + seconds; }
额外说明
- 若系统中无Roboto字体,可将自定义字体文件(如.ttf格式)打包到APP的assets目录,通过
getApplicationDocumentsDirectory()获取字体路径后传入滤镜。 - 使用
executeWithArguments而非字符串拼接执行命令,可避免手动处理引号转义的风险,提升命令执行稳定性。
内容的提问来源于stack exchange,提问作者abdallah mostafa
相关产品推荐
相关产品推荐

