PHP无法直接提取字幕轨道,必须通过shell_exec调用ffmpeg执行命令,解析ffprobe输出获取字幕流索引后,用-map和-c:s:srt提取为SRT文件。

确认 ffmpeg 已安装并支持字幕解复用
在终端运行:
ffmpeg -version
确保输出包含 libass、libsubtitles 等字样,且能识别常见字幕格式(如 mov_text、webvtt、ass、srt)。再检查视频文件的轨道信息:
ffprobe -v quiet -show_entries stream=index:stream_tags=language:stream=codec_type -of csv=p=0 "video.mp4"
你会看到类似:
2,subtitle,eng 3,subtitle,zho
其中 index=2 表示第 3 条流(从 0 开始计数)是英文字幕轨道。
立即学习“PHP免费学习笔记(深入)”;
用 PHP 调用 ffmpeg 提取指定字幕轨道为 SRT 文件
PHP 不解析容器或字幕内容,只执行命令。例如,提取 index=2 的字幕流并转为 SRT:
- 如果原始字幕是
mov_text(常见于 MP4)、webvtt(常见于 MKV/MP4),ffmpeg 可直接复制或转换:
$videoPath = '/path/to/video.mp4';
$subtitlePath = '/path/to/output.srt';
$streamIndex = 2;
// 构建命令:将第 2 号流(字幕)提取为 SRT 格式(自动转码)
$cmd = sprintf(
'ffmpeg -i %s -map 0:%d -c:s:srt -f srt -y %s 2>&1',
escapeshellarg($videoPath),
(int)$streamIndex,
escapeshellarg($subtitlePath)
);
$output = shell_exec($cmd);
if (file_exists($subtitlePath) && filesize($subtitlePath) > 0) {
echo "字幕已成功提取到:{$subtitlePath}";
} else {
echo "提取失败,输出:" . htmlspecialchars($output);
}
注意:-c:s:srt 表示“将所有字幕流用 srt 编码器处理”,-map 0:2 精确指定轨道;-f srt 强制封装格式。
批量检测并提取所有字幕轨道
先用 ffprobe 获取所有字幕流索引和语言,再循环提取:
$streams = json_decode(shell_exec('ffprobe -v quiet -print_format json -show_entries stream=index,codec_type,tags=language "video.mp4"'), true);
$subtitleStreams = array_filter($streams['streams'] ?? [], function($s) {
return $s['codec_type'] === 'subtitle' && isset($s['tags']['language']);
});
foreach ($subtitleStreams as $stream) {
$idx = $stream['index'];
$lang = $stream['tags']['language'] ?? 'unk';
$outFile = "sub_{$lang}_{$idx}.srt";
$cmd = sprintf('ffmpeg -i %s -map 0:%d -c:s:srt -f srt -y %s 2>&1',
escapeshellarg($videoPath),
$idx,
escapeshellarg($outFile)
);
shell_exec($cmd);
}
这样可自动导出 sub_eng_2.srt、sub_zho_3.srt 等文件。
注意事项与常见问题
- PHP 进程需有执行 shell 命令权限(
shell_exec未被禁用,disable_functions中未包含它) - Web 服务器用户(如 www-data)必须对输入视频和输出目录有读写权限
- 某些内嵌字幕(如图形字幕/VOBSUB)无法转成纯文本 SRT,ffmpeg 会报错或输出空文件;此时需 OCR(如使用
ccextractor)或跳过 - 若需保留 ASS/SSA 样式,把
-c:s:srt换成-c:s copy并改后缀为.ass(前提是源格式就是 ASS)



















