Skip to content

一次“有控件无画面”的视频播放问题

最近在开发一个 Next.js 项目时,需要在页面中嵌入几个 MP4 视频,用的是标准的<video controls> 标签。 结果发现一个诡异的现象:三个视频使用了完全相同的 HTML 结构,其中两个可以正常显示画面,另一个却只出现了播放控件条,画面区域一片黑/白,时间轴可以拖动,但没有图像输出。 现象

  • 页面代码完全一致,仅视频文件路径不同。
    • 不正常的视频:VLN1.mp4
    • 正常的视频:VLN2.mp4、VLA.mp4
  • 在本地文件夹中用系统播放器(如 VLC、Windows 媒体播放器)打开 VLN1.mp4 完全正常。
  • 在浏览器(Chrome/Edge)以及 VSCode 的内置预览中均无法显示画面。

排查思路

  1. 排除前端代码问题 既然三个视频的 <video> 标签一模一样,且有两个能正常工作,说明不是代码逻辑、CSS 或 JavaScript 的问题。 也不是服务器 MIME 类型问题(因为同一个目录下的其他 MP4 能正常加载)。

  2. 怀疑视频编码格式不兼容 浏览器对视频编码的支持是有限制的。目前最广泛支持的是 H.264(AVC)视频 + AAC 音频 的组合。 很多现代浏览器不默认支持 H.265(HEVC),因为专利授权复杂且硬件解码支持不统一。

  3. 使用 ffprobe 查看视频编码信息 安装 ffmpeg 后,可以用 ffprobe 命令快速查看视频流的编码格式:

ffprobe -v error -show_entries stream=codec_name,profile,level -of default=noprint_wrappers=1 VLN1.mp4

输出结果:

text
codec_name=hevc
profile=Main
level=120
codec_name=aac
profile=LC

关键信息:codec_name=hevc —— 视频编码是 H.265(HEVC),而音频是 AAC(正常)。 再查看正常播放的 VLN2.mp4:

bash
ffprobe -v error -show_entries stream=codec_name,profile,level -of default=noprint_wrappers=1 VLN2.mp4

输出:

text
codec_name=aac
profile=LC
codec_name=h264
profile=High
level=40

结论:正常视频是 H.264 + AAC,问题视频是 HEVC + AAC。 浏览器不支持 HEVC 解码,所以只能解析出音频(如果有)和元数据(控件条能出现),但无法渲染视频帧。

解决方案

将 VLN1.mp4 重新编码为 H.264 + AAC,并添加 faststart 标志(将 moov 元数据移到文件头部,优化网页渐进式播放)。

方法一:使用 ffmpeg 命令行(推荐)

bash
ffmpeg -i VLN1.mp4 \
  -c:v libx264 \
  -preset medium \
  -crf 23 \
  -c:a aac \
  -b:a 128k \
  -movflags +faststart \
  VLN1_fixed.mp4

参数说明:

  • c:v libx264:视频编码器改为 H.264
  • preset medium:编码速度与压缩率的平衡(可选:fast, medium, slow)
  • crf 23:恒定质量因子,18~28 之间,数值越小画质越好、体积越大;23 是默认值
  • c:a aac:音频编码为 AAC
  • b:a 128k:音频比特率 128kbps
  • movflags +faststart:将元数据移到文件开头,网页加载时无需下载完整文件即可开始播放

转载或 CV 自 maomao1996