29、音视频测试与质量评估:PSNR/SSIM计算、音画同步测试、弱网模拟
做音视频开发这么多年,我踩过最大的坑,就是「自测没问题,上线就翻车」。
你想想看,本地跑得飞快的视频播放器,到了用户手里,画面卡成PPT,声音还对不上嘴型。这种问题,光靠肉眼盯是盯不出来的。必须上工具、上指标、上模拟环境。
今天这一章,我就把压箱底的三板斧掏出来:PSNR/SSIM 算画质、音画同步 测延迟、弱网模拟 找极限。说白了,就是给你的音视频App做一次全身体检。
29.1 画质评估:PSNR 与 SSIM
先聊画质。你辛辛苦苦把视频压缩了一遍,到底损失了多少?不能光靠「我觉得还行」来判断。
29.1.1 PSNR:峰值信噪比
PSNR 是最经典的客观指标。它算的是原始图像和压缩后图像之间的像素误差。数值越高,失真越小。
公式长这样:
PSNR = 10 * log10( (MAX^2) / MSE )
其中 MSE 是均方误差,MAX 是像素最大值(比如 255)。
我个人习惯,PSNR 在 40dB 以上,说明画质几乎无损;30~40dB 算良好;低于 30dB,嗯,肉眼就能看出明显瑕疵了。
29.1.2 SSIM:结构相似性
PSNR 有个毛病——它只算像素差异,不考虑人眼感知。比如稍微调亮一点,PSNR 可能掉很多,但人眼觉得没啥区别。
SSIM 就聪明多了。它从亮度、对比度、结构三个维度去比较。取值范围 0~1,越接近 1 越好。
一般 SSIM 在 0.95 以上,人眼基本分不出区别。0.9 以下,就能看出压缩痕迹了。
29.1.3 代码实现
Android 上怎么算?我一般用 OpenCV 或者直接撸像素。下面给个纯 Java 的 PSNR 计算片段:
public static double calculatePSNR(Bitmap original, Bitmap compressed) {
int width = original.getWidth();
int height = original.getHeight();
double mse = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel1 = original.getPixel(x, y);
int pixel2 = compressed.getPixel(x, y);
int r = Color.red(pixel1) - Color.red(pixel2);
int g = Color.green(pixel1) - Color.green(pixel2);
int b = Color.blue(pixel1) - Color.blue(pixel2);
mse += (r * r + g * g + b * b) / 3.0;
}
}
mse /= (width * height);
if (mse == 0) return 100; // 完全一致
return 10 * Math.log10((255 * 255) / mse);
}
29.2 音画同步测试
音画不同步,是用户骂娘最多的问题。我见过最离谱的案例——声音比画面快了 2 秒,用户以为是「预知未来」功能。
29.2.1 测试方法
测音画同步,我推荐两种方式:
- 打点法: 在视频特定帧插入一个视觉标记(比如闪白),同时在音频轨道对应位置插入一个短促的「嘀」声。播放时用示波器或者录屏软件,数一下闪白和嘀声之间的帧数差。
- 自动化工具: 用 FFmpeg 的
av_sync或者自己写脚本,逐帧比对音视频时间戳。
29.2.2 可接受范围
ITU-R BT.1359 标准建议:
| 场景 | 可接受延迟 | 可察觉延迟 |
|---|---|---|
| 影视内容 | ±40ms | ±80ms |
| 直播/通话 | ±20ms | ±40ms |
| 游戏 | ±15ms | ±30ms |
29.3 弱网模拟
弱网环境,是音视频 App 的照妖镜。你在办公室 Wi-Fi 下测出来的流畅度,到了地铁、电梯、地下室,可能直接崩掉。
29.3.1 模拟工具
Android 上做弱网模拟,我常用这几招:
- Android Emulator 自带网络限制: 模拟器设置里可以选 EDGE、3G、4G 等模式,还能自定义延迟和丢包率。
- Facebook ATC(Augmented Traffic Control): 一个强大的弱网模拟工具,可以精确控制带宽、延迟、丢包、抖动。
- Charles / Fiddler: 通过代理做限速,适合 HTTP/HTTPS 流媒体测试。
- Linux tc 命令: 如果你有 root 权限,直接在设备上用
tc qdisc模拟弱网。
29.3.2 关键指标
弱网测试,重点看这几个:
- 丢包率: 1% 以下基本无感,3% 开始卡顿,5% 以上画面马赛克严重。
- 延迟: 100ms 以内体验良好,300ms 以上交互感明显下降。
- 抖动: 延迟忽高忽低,比高延迟更致命。抖动超过 50ms,播放器缓冲区就很容易饿死。
29.3.3 实战脚本
下面是我常用的一个弱网模拟脚本(需要 root 权限):
# 模拟 3G 网络:延迟 100ms,丢包 2%,带宽 1Mbps
tc qdisc add dev wlan0 root netem delay 100ms loss 2% rate 1mbit
# 恢复网络
tc qdisc del dev wlan0 root
29.4 知识体系总览
下面这张图,把本章的核心逻辑串起来了:
29.5 总结
音视频测试,说白了就是三个字:量化。画质用 PSNR/SSIM 量化,音画同步用时间戳量化,弱网用丢包/延迟/抖动量化。
我个人的经验是:不要等到上线前才做测试。从编码器选型、网络协议设计、播放器缓冲区策略,每一步都要带着测试思维去做。否则,等用户骂上门来,就晚了。
公众号:蓝海资料掘金营,微信deep3321