PHP通过FFmpeg添加字幕乱码的根源是字符编码不一致,需确保字幕文件为UTF-8无BOM编码、FFmpeg显式指定charenc=utf-8参数、PHP生成时统一转码,并注意字体路径与格式规范。

PHP本身不直接处理视频字幕渲染,但可通过调用外部工具(如 FFmpeg)给视频添加字幕。乱码本质是**字符编码不一致**,核心在于确保字幕文件(通常是 .srt 或 .ass)以 UTF-8 编码保存,且 FFmpeg 正确识别该编码。
确保字幕文件是 UTF-8 无 BOM 编码
很多编辑器(如记事本、Sublime Text、VS Code)默认保存可能带 BOM 或用 GBK/ANSI 编码,导致 FFmpeg 读取时显示乱码。
- 用 VS Code 打开 .srt 文件 → 右下角查看编码(如显示“GBK”),点击后选择“通过编码重新打开”→ 选 “UTF-8” → 再点击右下角“UTF-8”,选择“另存为 UTF-8”(勾选“不带 BOM”)
- 用 Notepad++:菜单栏“编码”→“转为 UTF-8 无 BOM 编码”→ 保存
- 可用命令行快速验证:
file -i subtitle.srt(Linux/macOS)或用 PowerShell:Get-Content subtitle.srt -Encoding UTF8测试是否可正常读取中文
FFmpeg 添加字幕时指定编码(关键步骤)
FFmpeg 从 v4.4+ 开始支持 -sub_charenc utf-8 参数,显式告诉它字幕文件是 UTF-8 编码。缺少该参数,FFmpeg 可能按系统默认编码(如 Latin-1)解析,导致中文变问号或方块。
- 正确命令示例(硬嵌字幕):
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:charenc=utf-8" -c:a copy output.mp4 - 如果字幕路径含中文,建议用绝对路径,并确保 PHP 中用
escapeshellarg()转义:
$srtPath = escapeshellarg('/var/www/sub/字幕.srt');<br> $cmd = "ffmpeg -i input.mp4 -vf \"subtitles={$srtPath}:charenc=utf-8\" -c:a copy output.mp4";<br> exec($cmd, $output, $returnCode);
PHP 生成字幕文件时主动写入 UTF-8
如果字幕内容由 PHP 动态生成(如从数据库读取台词),务必用 mb_convert_encoding() 统一转为 UTF-8,并用 file_put_contents() 指定编码:
立即学习“PHP免费学习笔记(深入)”;
$lines = ["1", "00:00:01,000 --> 00:00:04,000", "你好,世界!"];<br> $content = implode("\n", $lines);<br> // 确保整个字符串是 UTF-8<br> $content = mb_convert_encoding($content, 'UTF-8', 'auto');<br> file_put_contents('subtitle.srt', $content, LOCK_EX);- 避免直接拼接中文字符串后写入,尤其当源数据来自 MySQL(检查表字符集是否为
utf8mb4,连接是否设SET NAMES utf8mb4)
其他易忽略细节
即使编码正确,仍可能因字体缺失或样式配置不当导致显示异常:
- FFmpeg 默认使用系统字体,Linux 服务器常无中文字体 → 需指定字体路径:
-vf "subtitles=subtitle.srt:charenc=utf-8:fontsdir=/usr/share/fonts/truetype/wqy/:font='WenQuanYi Zen Hei'" - .srt 文件每段之间必须有空行;时间格式严格为
HH:MM:SS,mmm(逗号分隔毫秒),不能用英文句点 - 测试时先用小片段(如 5 秒视频)快速验证,避免长时间等待



















