拿到转写 SRT 后,用 FFmpeg 导出中文字幕视频
想让视频发出去就自带字幕,可以把已有 SRT 绘进视频画面。这样播放器不需要再加载字幕文件,但文字也不能单独关闭,改字要重新导出。
下面是本地六秒样片在 2.0 秒处的实际抽帧,两行中文都已经成为画面的一部分:
背景由 FFmpeg 色块生成,字幕是手写教学内容,没有做模型转写。这里验证的是“已有字幕怎样导出”,不是 AI 识别准确率;不同转录模型支持的输出格式也有区别,不能把普通文本改个扩展名就当成 SRT。
包里有三份 Bash 脚本、UTF-8 的 captions.srt 和 README。视频由脚本在本地生成,不需要你复制保存长命令,也不需要 API key。
先跑这六秒
面向 Linux 和 Bash,需要 FFmpeg 带 subtitles(libass)滤镜、libx264 编码器,以及中文字体。本地实际使用 FFmpeg 7.1.5、Noto Sans CJK SC Regular。验证脚本还用到 ffprobe、Fontconfig 和 Python 3 标准库。
可以先看滤镜和字体:
ffmpeg -hide_banner -h filter=subtitles
fc-match -f '%{family}\n' 'Noto Sans CJK SC' fc-match 可能给出替代字体,要读返回的家族名。没有指定字体或滤镜时,先补齐环境;不要只看命令退出就认定中文字形正常。
解压后在目录里执行:
bash build_demo.sh
bash burn.sh
bash verify.sh 前两条生成 clip.mp4 和 subtitled.mp4;验证脚本在临时目录重跑另一份样片,将证据保存到 evidence/。样片是 960×540、25 fps、6 秒、H.264、无声。包已经实际解压重跑,验证通过后也逐张查看了关键帧。
换行写在 SRT 里
这就是随包的完整字幕:
1
00:00:01,000 --> 00:00:03,000
先检查字幕格式
再看中文和换行
2
00:00:04,000 --> 00:00:05,500
这段从第四秒开始 同一条字幕里的换行会保留,条目之间用空行分开。本例用了显式两行,不靠自动折行碰运气。长句、竖屏或更大的字号仍要重新看画面。
对应的关键时刻是:
| 视频时间 | 本地样片预期画面 |
|---|---|
| 0.5 秒 | 无字幕 |
| 2.0 秒 | 第一条,两行中文 |
| 3.5 秒 | 无字幕 |
| 4.5 秒 | 第二条,一行中文 |
验证脚本检查了这些时刻的亮色文字行带、导出规格、缺 SRT 时报错,以及已有源文件和目标文件不被覆盖,共 5 组检查。像素检查不会认字,中文是不是方框、有没有缺字或裁切,还得打开实际 PNG 看;上图就是其中一张。
真正处理自己的视频
另解压一份干净目录,把自己的视频命名为 clip.mp4,与保存为 UTF-8 的 captions.srt 放在一起,只运行 bash burn.sh。这次不要运行生成色块的 build_demo.sh。
burn.sh 里实际使用的导出命令如下,在这两个文件所在目录也能直接运行:
ffmpeg -hide_banner -loglevel warning -nostdin -n -i clip.mp4 \
-vf "subtitles=filename=captions.srt:charenc=UTF-8:force_style='FontName=Noto Sans CJK SC,FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H00202020,BorderStyle=1,Outline=2,Shadow=0,Alignment=2,MarginV=24'" \
-c:v libx264 -crf 18 -pix_fmt yuv420p \
-c:a copy -movflags +faststart subtitled.mp4 FontName 填字体家族名。这里用系统已安装字体;如果另加 fontsdir,它只是补充字体目录,不会保证只用那个目录里的字体。-vf subtitles 会重新编码视频,不能把视频编码改成 -c:v copy 来省这一步。
脚本固定简单文件名,避免把复杂路径直接塞进字幕滤镜;Bash 脚本本身可以从其他目录调用。若 subtitled.mp4 已存在,会明确失败并保留旧文件,不会自动替换。导出中途失败仍可能留下不完整文件,先查错误和文件状态,不能把“文件在”当成成功;验证证据目录也请使用空目录,重复验证的做法见 README。
SRT 的时间必须已经对应输入视频。这份样片和字幕都以 0 为起点;若你把原片剪掉前十秒、变速或拼接过,不能期待滤镜自动把旧时间轴对齐。
命令中的 -c:a copy 只尝试复制默认选中、且兼容 MP4 的音轨;这里没有指定 -map,不会保留全部音轨。音轨不兼容时要另选音频编码。样片无声,没有验证音轨处理或语音同步;真实素材导出后仍需完整播放检查。
资料:FFmpeg《Filters: subtitles》及官方源码、OpenAI 转录接口文档、Noto CJK README,2026-10-22 核对当前资料。