一、问题描述

今天电脑网页(Chrome浏览器)上看飞牛视频的时候,发现画面比音频慢一拍,然后使用PotPlayer播放原视频发现音视频画面是同步的。
二、分析
播放是的原画质,播放类型是直接播放,说明飞牛Nas系统没有进行转码,而是尝试让浏览器直接解码原视频流。再从缓冲时长为92秒多的情况看,排除了网络或缓冲策略问题。剩下就二种可能了:
1. 浏览器硬解支持有限
多数浏览器(尤其是 Chrome / Edge)对 H.265(HEVC)硬解支持不完善,使用了软解或转码,导致画面卡顿而出现音画不同步。
2. 音频/视频轨道本身存在轻微偏移
少数视频文件本身音画就有微小偏移(PotPlayer 具备强大的音画同步算法,能智能调整播放节奏,自动修正轻微偏移),但网页播放器没有此功能,导致问题暴露。
三、查看详情,确认问题
在浏览器中开一个新的页签,输入chrome://media-internals,查看 Players,选择一条播放的视频数据,查看完整的Player Properties信息。

从信息来看,我们能确认以下几点:
1. 视频解码:硬解成功
说明 Intel GPU 正在硬件解码 HEVC 视频,性能不是瓶颈。
kVideoDecoderName: D3D11VideoDecoder
kIsPlatformVideoDecoder: true
2. 音频处理:软解 + 时间戳异常
kAudioDecoderName: FFmpegAudioDecoder
kIsPlatformAudioDecoder: false
音频用的是 FFmpeg 软件解码(虽然 AAC 解码很轻量,通常没问题)
但我们要注意最后面那条警告:
warning: Failed to reconcile encoded audio times with decoded output.
浏览器无法将音频帧的时间戳与视频帧对齐,导致播放时“画面慢一拍”,这就是根本原因了。
四、解决办法
使用ffmpeg重新封装视频文件并校正时间戳,来修复视频文件。
进入飞牛Nas Shell终端,安装飞牛视频后默认安装好了ffmpeg无需要重新安装。若没有可以用命令行安装
sudo apt install ffmpeg # 飞牛/Debian/Ubuntu
sudo dnf install ffmpeg # Fedora
sudo pacman -S ffmpeg # Arch
然后使用下面命令重新封装:
ffmpeg -i input.mp4 -c copy -avoid_negative_ts make_zero -movflags +faststart output.mp4
参数说明:
- -c copy:不转码,只修复封装(效率高,略逊于直接复制的速度)
- -avoid_negative_ts make_zero:强制时间戳从 0 开始,消除负偏移
- -movflags +faststart:将 moov 移到文件头,优化网页播放
- -i input.mp4:input.mp4为原视频文件
- output.mpt:为修复后的视频文件
然后进入飞牛视频重新扫描媒体库文件,播放新的文件试试,理论上音视频不同步问题应该能得到解决了。若还未解决可轻微重编码音频,消除潜在的时间戳错乱问题。
ffmpeg -i input.mp4 -c:v copy -c:a aac -b:a 192k -ar 48000 -movflags +faststart output.mp4
最后附上一个修复当前目录下的 MP4 文件的脚本
#!/bin/bash
echo "正在修复当前目录下的 MP4 文件(不包含子目录)..."
echo
# 遍历当前目录下所有 .mp4 文件
for file in *.mp4; do
# 如果没有匹配到任何 .mp4 文件,跳过
[[ ! -f "$file" ]] && continue
# 跳过已修复的文件(文件名以 _fixed.mp4 结尾)
if [[ "$file" == *_fixed.mp4 ]]; then
echo "跳过已修复文件: $file"
continue
fi
# 构造输出文件名
output="${file%.mp4}_fixed.mp4"
# 如果输出文件已存在,跳过
if [[ -e "$output" ]]; then
echo "已存在,跳过: $output"
continue
fi
echo "处理: $file"
# 执行 ffmpeg 修复命令
ffmpeg -i "$file" -c copy -avoid_negative_ts make_zero -movflags +faststart "$output"
if [[ $? -eq 0 ]]; then
echo "完成: $output"
else
echo "处理失败: $file"
fi
echo
done
echo "所有任务完成!"
五、题外话
如果遇到了浏览器硬件不支持的情况下,可以将视频转码成更兼容的H.264编码
ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 192k output.mp4
- -c:v libx264:输出 H.264 编码
- -preset medium:平衡速度与质量
- -crf 23:高质量(类似原片)
- -c:a aac:保留 AAC 音频
评论区