1. 卡顿现象的本质:音频卡顿与视频卡顿的区别,推流卡顿的宏观表现

做音视频这行,天天跟卡顿打交道。但说实话,很多人干了三五年,还是分不清「音频卡顿」和「视频卡顿」到底有啥本质区别。

我刚开始带项目那会儿,有一次线上事故,用户反馈直播「一卡一卡的」。团队排查了两天,最后发现是音频缓冲区配置错了。嗯,从那以后,我养成了一个习惯——先问一句:到底是声音卡,还是画面卡?

1.1 音频卡顿 vs 视频卡顿:本质差异

先看一张对比表,把核心差异说清楚。

维度 音频卡顿 视频卡顿
感知方式 听觉——断断续续、杂音、变调 视觉——画面停滞、跳帧、模糊
容忍度 极低。超过 20ms 的断续就能察觉 较高。30fps 下丢一两帧不太明显
数据特征 连续流,采样点不可丢 离散帧,丢帧可接受(但会卡)
缓冲策略 小缓冲区(几十 ms),低延迟优先 大缓冲区(几百 ms),平滑优先
修复手段 插值、PLC(丢包隐藏) 丢帧、帧重复、降分辨率

核心结论:音频卡顿是「连续性」被破坏,视频卡顿是「完整性」被破坏。音频丢一个采样点,人耳就炸了;视频丢一帧,人眼可能没反应。

我个人习惯,排查卡顿时先看音频。为什么?因为音频卡顿的容忍窗口太窄了。你想想看,视频卡顿你还能忍个半秒,音频卡顿超过 50ms,用户就开始骂娘了。

1.2 推流卡顿的宏观表现

推流卡顿,不是单一现象。它是一连串连锁反应的外在表现。我把它拆成三个层面来讲。

1.2.1 采集端卡顿

源头就卡了,后面怎么修都没用。表现是:

  • 麦克风或摄像头驱动丢数据
  • 采集回调间隔不均匀(比如本该每 10ms 回调一次,结果有时 5ms,有时 30ms)
  • 系统负载高,采集线程被调度延迟

避坑指南:我曾经在 Android 项目里遇到过,某些低端机麦克风采集回调会随机「跳 tick」。排查了三天,最后发现是 HAL 层驱动没做时钟补偿。解决方案是加一个 jitter buffer,把不均匀的采集数据先捋顺了再送编码器。

1.2.2 编码端卡顿

编码器跟不上输入速度,或者码率控制出问题。表现是:

  • 编码队列堆积,延迟越来越高
  • 编码器内部丢帧(尤其是硬件编码器,满了就扔)
  • 音频编码器因为采样率不匹配,产生「变调」或「加速」

这里有个坑:很多人以为编码卡顿就是 CPU 不够。其实大部分情况是编码器配置不对。比如 H.264 的 preset 设成了 placebo,或者音频编码的 bitrate 设得比源采样率还高——编码器自己就卡死了。

1.2.3 网络传输卡顿

这是最常见的卡顿来源。表现是:

  • 发送缓冲区满,数据包排队出不去
  • 网络抖动导致 RTT 忽高忽低
  • 丢包重传导致发送端阻塞

注意:网络卡顿和编码卡顿经常被混淆。我见过一个团队,用户反馈卡顿,他们先升级了服务器带宽,结果没用。最后发现是编码器输出码率峰值超过了网络出口带宽——不是网络不够,是编码器「吐」得太快了。

1.3 卡顿的宏观链路图

下面这张图,把推流卡顿的完整链路画出来了。每个环节都可能成为瓶颈。

推流卡顿宏观链路图 推流卡顿宏观链路图 采集端 麦克风 / 摄像头 编码端 AAC / H.264 编码器 网络传输 TCP / UDP 推流 原始数据 压缩码流 卡顿原因:每个环节都可能成为瓶颈 采集端卡顿原因 • 驱动丢数据 • 回调间隔不均匀 • 系统调度延迟 • 时钟漂移未补偿 编码端卡顿原因 • 编码队列堆积 • 硬件编码器丢帧 • 码率控制异常 • 采样率不匹配 网络传输卡顿原因 • 发送缓冲区满 • 网络抖动 (Jitter) • 丢包重传阻塞 • 带宽不足 宏观表现:用户感知为「声音断断续续」+「画面一帧一帧跳」 实际可能是采集、编码、网络中任意一个或多个环节共同导致

1.4 音频卡顿的特殊性

音频卡顿和视频卡顿最大的区别,在于「人耳感知模型」。我简单说几个关键点。

  1. 时间分辨率极高:人耳能分辨 10μs 级别的时差。视频卡顿你还能用「丢帧」糊弄过去,音频卡顿你丢一个采样点(比如 48kHz 下约 20μs),人耳就能听出「啪」的一声。
  2. 连续性要求苛刻:音频是波形,必须连续。一旦中断,波形就断了,解码器会输出噪声或静音。视频丢一帧,解码器还能用上一帧「撑一下」。
  3. 延迟敏感度不同:音频端到端延迟超过 200ms,用户就感觉「对不上口型」。视频延迟 500ms 甚至 1 秒,用户可能都没察觉。

实战经验:我在做某款直播软件时,发现音频卡顿的根因往往是「缓冲区太小」。视频缓冲区可以设到 1 秒,音频缓冲区超过 100ms 就会导致明显的延迟感。所以音频缓冲区通常设在 20-50ms,但这又导致它对网络抖动特别敏感——这就是音频卡顿「难搞」的地方。

1.5 推流卡顿的「蝴蝶效应」

最后说一个宏观现象。推流卡顿很少是单一原因导致的。往往是:

  • 网络抖动 → 发送端堆积 → 编码器背压 → 采集端被阻塞 → 音频采样点丢失 → 用户听到「咔咔咔」

你看,源头是网络,但最终用户感知到的是音频卡顿。如果你只盯着音频修,永远修不好。

所以我个人习惯,遇到卡顿问题,先拉一条完整链路:采集→编码→网络→解码→渲染。每个环节打上时间戳,看延迟在哪里堆积。这叫「端到端延迟瀑布图」,后面章节我会详细讲怎么画。

一句话总结:音频卡顿是「连续性」问题,视频卡顿是「完整性」问题。推流卡顿是整条链路的「木桶效应」——最弱的一环决定了用户体验。