PHP不嵌入字幕到视频,仅安全拼接WebVTT路径供HTML5 通过加载;字幕嵌入由FFmpeg异步处理,渲染由浏览器和JavaScript控制,PHP只负责白名单过滤语言参数并输出正确静态路径。

PHP 本身不嵌入字幕到视频文件里,也不控制浏览器字幕渲染——它只负责安全地告诉前端该加载哪个 .vtt 文件。真正在做字幕嵌入的是 FFmpeg;真正切换和显示字幕的是 HTML5 <video></video> 和 JavaScript。
PHP 不处理视频字幕嵌入,别用它调用 exec('ffmpeg ...')
有人试图让 PHP 调用 ffmpeg 把字幕硬编码进 MP4,这在生产环境极不推荐:
- 耗 CPU、阻塞请求,一个视频转码可能卡住整个 PHP 进程
- 并发一高就崩溃,没日志、难调试
- 权限和路径问题频发:
/tmp写满、exec被禁用、SELinux 拦截 - 字幕样式(字体、位置、颜色)丢失严重,WebVTT 的 CSS 类无法映射到硬编码结果
正确做法是:用独立任务队列(如 Supervisor + Python 脚本或 Node.js worker)异步处理 FFmpeg 命令,PHP 只返回任务 ID 和状态接口。
<track></track> 标签的 src 必须是 Web 可直链的路径,不是 PHP 输出内容
常见错误是用 readfile() 或 file_get_contents() 读取 .vtt 再输出,还设 Content-Type: text/vtt ——这会让浏览器拒绝加载字幕,因为 <track></track> 只接受 CORS 安全、MIME 正确的静态资源。
立即学习“PHP免费学习笔记(深入)”;
-
src值必须形如/subtitles/movie_zh.vtt,不能是/api/subtitle.php?lang=zh - PHP 只需拼接路径:
echo '/subtitles/movie_' . $safe_lang . '.vtt';,其中$safe_lang是白名单过滤后的值(如in_array($lang, ['zh', 'en', 'ja'])) - 确保 Web 服务器配置了
.vtt的 MIME 类型:Nginx 加types { text/vtt vtt; },Apache 加AddType text/vtt .vtt - 直接访问
https://yoursite.com/subtitles/test.vtt,检查响应头中Content-Type是否为text/vtt
多语言字幕切换依赖 JavaScript 控制 textTracks
PHP 只能决定初始 default 属性,后续切换必须靠 JS。HTML 中多个 <track></track> 标签已存在,但浏览器默认只启用带 default 的那个。
- 获取所有轨道:
const tracks = video.textTracks; - 关闭全部:
for (let t of tracks) t.mode = 'disabled'; - 启用指定语言:
tracks[1].mode = 'showing';(注意索引非srclang) - 更稳妥的方式是遍历:
Array.from(tracks).find(t => t.language === 'zh')?.mode = 'showing'; - 不要依赖
label匹配,它只是 UI 文本,可能重复或含空格
PHP 的作用仅限于生成初始 HTML 中哪条 <track></track> 带 default,比如根据 $_SESSION['lang'] 或 $_GET['lang'] 动态插入属性。
字幕文件内容必须严格符合 WebVTT 格式,UTF-8 无 BOM
哪怕一个空格错位、时间戳格式不对(00:00:01.234 而非 00:00:01.23),浏览器都会静默失败,控制台可能只报 “Failed to load track”。
- 首行必须是
WEBVTT(无注释、无空行) - 每段字幕以数字序号开头,后跟时间轴(
00:00:01.000 --> 00:00:04.000),再空一行,再写文本 - 中文内容必须保存为 UTF-8 编码,且不能带 BOM(用 VS Code 或 Notepad++ 检查并另存为“UTF-8 无签名”)
- 避免使用 HTML 标签:
<b></b>在 WebVTT 中无效,应改用<c.color-green></c.color-green>等 CSS 类(需配合<style></style>定义) - 测试时用最小字幕文件验证:
WEBVTT 1 00:00:01.000 --> 00:00:03.000 Test
最容易被忽略的是:字幕文件路径可访问、MIME 正确、格式合规、编码干净——四者缺一不可,而 PHP 在其中只参与路径拼接这一环。



















