自动检测或拒绝与 iOS Safari 不兼容的 VP9 视频上传

我最近发现,在我自托管的 Discourse 论坛上,多个视频在 iPhone 和 iPad 上无声地无法播放。经过调查,根本原因是这些视频使用了 VP9 编码,并封装在 MP4 容器中——这种组合 iOS Safari 无法播放。

问题成因

Facebook(以及其他平台可能也存在类似情况)在用户下载其内容时,有时会提供 VP9 编码的视频。当这些文件上传到 Discourse 时,系统会正常接受——.mp4 扩展名无法反映其内部使用的编码格式。在桌面浏览器和 Android 设备上,视频可以正常播放,因此问题不易被察觉。而在 iOS Safari 上,视频会显示缩略图和播放按钮,但点击后只会显示旋转加载指示器。用户通常会认为这是网络问题,从而不再进一步报告。

为何难以察觉

  • 文件扩展名(.mp4)与正常工作的 H.264 文件完全相同
  • 桌面浏览器支持 VP9,管理员在桌面端测试时不会发现问题
  • iOS 用户通常不会单独报告媒体播放失败,尤其是当同一帖子中的其他内容仍可正常查看和播放时
  • 系统没有向管理员提供警告或错误提示

建议的解决方案

在视频上传时,Discourse 可以检查视频编码格式(Docker 容器中已内置 ffprobe),并选择以下任一方式处理:

  1. 拒绝上传,并显示明确提示,说明 VP9 在 iOS 上不受支持,要求用户重新编码为 H.264;或
  2. 自动转码 视频为 H.264(类似于某些平台对上传内容的标准化处理)

方案 1 实现复杂度较低,且已能带来显著改善。方案 2 则能为用户提供无缝体验,是更理想的选择。

环境信息

  • 自托管 Discourse,运行于 Docker 中,使用本地存储(未使用 S3)
  • Discourse 版本:2026.4.0-latest
  • Discourse 前端部署了 Apache 反向代理,其后为 nginx

临时解决方案

对于遇到此问题的管理员,修复步骤如下:

  1. 使用 ffprobe 识别 VP9 文件
  2. 使用 ffmpeg -c:v libx264 -profile:v main -level 3.1 -r 30 -movflags +faststart 将视频重新编码为 H.264
  3. 更新 uploads 表中的 sha1urlfilesize 字段
  4. 更新受影响帖子原始 Markdown 中的 upload:// 短链接令牌
  5. 重新生成受影响帖子的内容

这是一项相当繁琐的手动操作,大多数论坛管理员并不具备执行这些步骤的能力。

1 个赞

关于自动转码,您可以查看 Discourse 视频流 :movie_camera:

本地自动转码可以正常工作,但如何在大多数部署环境中安全地交付该内容才是主要问题。

2 个赞

感谢 @Falco 指向 Video Stream 插件。对于像我这样的小型爱好者论坛来说,依赖付费第三方服务似乎有些小题大做——尽管我理解这对高流量且大量使用视频的网站颇具吸引力。

您关于本地转码的说明很有意思。在修复过程中,我手动在 VPS 上对受影响的 9 个文件运行了 ffmpeg,服务器处理得很顺利。我理解在上传时同步执行转码的顾虑——CPU 峰值、超时和磁盘压力都是真实存在的风险。但如果采用异步后台任务的方式,是否能解决大部分这些问题呢?上传正常完成,转码则在之后的队列任务中执行——类似于 Discourse 处理图像缩略图的方式。视频在任务完成前无法在 iOS 上播放,这似乎是一个可以接受的权衡。

即使不进行完整的转码,一个更轻量级的方案——在上传时检测 VP9 格式,要么以清晰的错误消息拒绝,要么在管理面板中标记——对于可能缺乏技术背景来诊断 iOS 静默播放故障的自托管管理员来说,将大有裨益。

1 个赞

视频处理要复杂一些,因为用户有多种方式可以恶意上传文件以占用 CPU,尤其是在许多单核 CPU 的自托管实例中。

我可以尝试在此处探索一个插件方案,使其成为管理员在权衡利弊后可以选择的选项。

3 个赞