音视频面试--延迟优化

文章目录

Q1|流媒体服务器如何做到低延迟

低延迟不是单点优化,而是全链路对齐的结果。服务器侧能做的归纳成三句话:**只透传不转码、缓存要短、丢帧不丢延迟:

  1. 协议选型决定下限:内网实时监控用 RTSP over UDP,Web 端用 WebRTC,两者走 UDP,不会因 TCP 重传导致延迟层层累积;HTTP-FLV 约 1 秒,作为兼容备选;HLS 切片机制至少 6 秒起步,实时场景基本不用。
  2. 只透传不转码:服务器解封装后直接重封装转发,避免多余的编解码循环,一次转码至少引入一个 GOP 的延迟。
  3. 关闭大缓存和长 GOP :GOP 控制在 1--2 秒,缓冲队列限制在几十到一百毫秒级,超出即丢旧帧;编码端用 zerolatency、baseline/main profile,禁用 B 帧和 lookahead。
  4. 关键帧缓存实现秒开:服务器只缓存最近一个 I 帧(GOP cache),新观众接入立刻从 I 帧推流,不必等下一个 IDR;但缓存越大秒开越快、实时延迟也越大,所以通常只缓存 1 个 GOP。
  5. 丢帧与追帧策略:弱网下直接丢弃非关键帧而非排队等待;关键帧丢失时请求 PLI/FIR 或 NACK,重传和等待必须设固定时限(如 200ms 内不恢复就丢弃并追帧),杜绝"累计延迟"。
  6. 时间戳与抖动缓冲:统一 PTS/DTS 基准,服务器用自适应 jitter buffer(基线几十毫秒),把网络抖动吸收在服务器侧,而不是交给客户端累积。

协议选 UDP、链路透传、缓存只留一个 GOP、弱网丢帧不等待------内网可做到 100--200ms,WebRTC 公网 200--500ms。

【解析】

  • 为什么强调"全链路":延迟是各环节累加,短板决定结果。只优化服务器而不管编码端的 B 帧或播放端的缓冲,端到端照样下不去。
  • 为什么 UDP 比 TCP 关键:TCP 的重传是"必须送达",丢一个包就卡住后续所有数据,延迟单调增长;UDP 允许"放弃",这是低延迟的前提。
  • 为什么只缓存一个 GOP:GOP cache 是拿延迟换秒开。缓存 N 个 GOP 就等于叠加 N 秒延迟,监控场景宁可秒开慢一点也不能牺牲实时性。
  • "累计延迟"是最大陷阱:缓冲做大会让卡顿看起来"没发生",但延迟在持续增长且不可逆,最终必须跳帧追赶,表现为爆发式卡顿。

Q2|窄带宽下视频卡顿如何处理

【总】

先分根因 再动手,按优先级逐级降码率。贯穿原则是:宁可丢帧、降画质,也不让延迟累积。

【分】

  1. 先分四类根因(看着都是"卡",处理方式完全不同):

    根因 表现 处理
    持续带宽不足 长期糊、掉帧 降码率、降档、换 H.265
    瞬时峰值超限 平时流畅,运动时卡 改 CBR 并限制峰值
    丢包/重传 马赛克、播放器等重传 限时 NACK、丢非关键帧
    缓存堆积 越播越慢 限制缓存、主动追帧
  2. 取舍顺序:先降帧率(25→15fps 省约 25%,观感损失小)→ 再降分辨率(1080p→720p 省约 45%,细节损失明显)→ 最后才加 QP 降画质。

  3. 双码流/多档位(最有效):接入端输出主码流+子码流,服务器按客户端带宽与窗口尺寸按需分发,窄带默认走子码流、放大才切主码流;必要时做多档转码(1080p→720p/D1/CIF),由客户端 ABR 自动切换。

  4. 编码参数适配:CBR 限峰值、GOP 1--2 秒、ROI 感兴趣区域(省 20--30%)、智能编码(静态降码率)、关 B 帧与多参考帧;带宽波动剧烈时可用 SVC 分层,只收基础层平滑降档。

  5. 弱网传输策略:NACK/PLI 限时 100--200ms、优先保 I 帧、队列积压丢旧帧、落后超阈值主动追帧提速、ABR 切换设滞回区间避免反复抖、丢包率 5--15% 的无线链路用 FEC 比多次重传更划算。

  6. 执行优先级:链路占用控在 70% 以内 → CBR 限峰值 → 双码流选档 → H.265/智能编码 → 降帧率、必要时降分辨率 → 丢帧追帧消除累积 → 多档转码 + ABR 平滑切换。

【总】

一句话:先判断是"带宽不够"还是"缓存太多",再按"控链路→限峰值→双码流→换编码→降帧率"的顺序逐级降级。

【解析】

  • 为什么先降帧率:监控画面以"看得清人/物"为目标,帧率降低主要损失流畅感,分辨率降低直接损失可辨识细节,后者代价更大。
  • 为什么必须 CBR:VBR 的瞬时峰值可能超过链路带宽,瞬间打满就产生排队,用户感知就是"本来好好的突然卡"。
  • 为什么缓存堆积加带宽没用:问题在播放端/服务端队列已经积压,加带宽只让队列更快填满,必须靠"丢帧不等待"把延迟拉回基线。
  • 双码流为何优于纯调参:它把"带宽适配"变成架构问题而不是参数问题,一次投入覆盖所有窄带客户端,比反复调 GOP/QP 更稳定。

Q3|低延迟和音视频卡顿的关系

【总】

它们本质上是同一个延迟预算的两端 。缓冲是拿延迟换平稳,所以延迟压得越低,抗抖动余量越小,卡顿概率越高。

【分】

  1. 等价关系:低延迟 = 小缓冲 = 抗抖动能力弱 → 卡顿概率上升;反之缓冲过大 → 延迟累积 → 弱网下越积越多,最终被迫跳帧追赶,表现为爆发式卡顿。
  2. 延迟的理论下限由抖动决定:可做到的最低延迟 ≥ 链路抖动峰值 + 解码耗时 + 必要处理耗时。强行压到低于抖动峰值,多出来的抖动只能靠丢包/丢帧消化,就是卡顿。局域网抖动 <10ms、缓冲 50ms 够用;公网/4G 抖动 50--200ms、至少需 200--300ms 缓冲------这就是内网能 100ms、公网必须 300ms 起步的原因。
  3. 卡顿与延迟互相转化:大缓存→延迟高但少卡;小缓存→低延迟但多卡;无限等待重传→延迟持续增长后集中爆发;激进丢帧→延迟稳定但偶发跳帧。
  4. 音视频差异 :音频对卡顿极敏感,丢包直接产生爆音、断续,人耳敏感,所以音频 buffer 通常比视频大;视频相对宽容,能接受偶发跳帧但不能接受延迟增长。因此实时监控通用策略是以音频为同步基准,视频允许丢帧追赶。
  5. 工程做法:自适应 jitter buffer(按实时抖动分布动态收窄/放宽)、卡顿率与端到端延迟分开监控、按场景定 SLO、音视频分开处理(音频走更高优先级或 FEC/重传,视频走丢帧)。

Q4|如何做到音视频同步

【总】

同步只有一个本质问题:音频和视频各自的时钟不同,必须先映射到同一条时间轴,再按它对齐播放。 服务器侧归纳为:建映射、保时间戳、控漂移。

【分】

  1. 协议层建映射 :RTSP/RTP 用 RTCP SR ,其中同时携带 NTP 时间戳 与 对应 RTP 时间戳,接收端据此把音视频各自的 RTP 时间轴换算到同一条 NTP 墙钟;MPEG-TS 用 PCR 恢复系统时钟,PTS/DTS 以此为基准;WebRTC 同样走 RTCP SR。前提是时间戳必须在采集时刻打上,不能是编码或发送时刻。
  2. 转发时保关系 :无论原样转 RTP 还是转 WebRTC/FLV/TS,都要按映射重新计算 PTS/DTS ,保证音视频相对关系不变;音视频独立缓存、按时间戳对齐后再发,绝不按到达顺序发送。
  3. 播放端以音频为主时钟:按音频推进主时间轴,比较视频 PTS 与当前播放位置的偏差并分档处理------≤80--100ms 不处理(死区,避免反复抖动)→ 100--300ms 微调播放节奏 → >300ms 丢帧/补帧追平 → >1s 重新锚定时间轴。
  4. 长期漂移必须控 :晶振偏差常见 10--100ppm,100ppm 约每小时漂 0.36 秒、一天近 9 秒,7×24 场景必然音画脱节。做 clock recovery :小偏差用音频重采样 (48kHz→48.002kHz,人耳无感),大偏差才丢/插视频帧。
  5. 异常兜底 :乱序、丢包、序列号处理保证时间戳序列干净;转码与合流以音频为基准;存储回放按 PTS 建索引对齐,不能按写入顺序播放。
  6. 特殊场景 :不少监控设备不发 RTCP SR,服务器要自行补偿(统一授时或首包到达时间估算);音频外接拾音器与视频不同源时自动算法无效,只能靠固定 audio offset 配置。

【总】

一句话:服务器要保证三件事------时间轴一致、时间戳相对关系不变、长期运行不漂移。

【解析】

  • 为什么必须"采集时刻打时间戳":编码和发送的耗时不均且不可预测,用它打戳会把处理抖动直接变成音画偏移。
  • 阈值的依据 :可引用 ITU-R BT.1359,音频超前视频 45ms 至滞后 125ms 属主观可接受;工程上一般按 ±100ms 死区、±200ms 开始明显来控制。
  • 为什么要设死区与滞回:任何校正都会带来画面节奏变化,频繁微调会被感知为"抖动",代价比初始的小偏差更大。
  • 为什么服务器不能"原样转发就完事":一旦转协议或转码,原时间戳语义就丢失,必须在出口重算;判断同步好坏看三个指标------偏差稳定值、是否随时间增长、协议转换前后偏差是否一致。
  • 无 SR 与外接音频是监控的两大坑,能主动提到说明有实际落地经验。

Q5 网关转发视频,如何减少卡顿?

  1. 内核零拷贝直通,绕开用户态

    bind_addr_port →ioctl(IOC_SET_PORTS) 把 video RTP/RTCP 的转发表直接下发到/dev/net_dev 。包在内核里改地址转发, 不进用户态、不做内存拷贝、不做协议栈解析 。用户态路径(SetRtpFwdInfo 双槽 4 个 socket,epolltype: 0=audio 1=video 2=aRTCP 3=vRTCP )每包至少多一次recv→sendto 拷贝和一次调度。

  2. 视频独立端口对,与音频隔离

    info_video_local/remote 是 独立的 4 组 local_remote_info 之一 ( RtpFwd.h ),不与音频共用 socket 或队列。视频 I 帧突发是"毫秒级几 MB"的尖峰,若与音频共队列会把语音一起拖到卡顿;物理隔离后 音频的排队延迟不受视频突发影响 。

  3. 视频独立 DSCP(这是网关侧最有效的延迟优化)

    g_nVideoCtrl 独立于g_nRtpCtrl ,可单独配置。这条值贯穿/dev/net_dev 的转发规则,决定了视频包在出口 QoS 队列里的出队优先级。 为什么这是最有效的 :弱网延迟的大头是 排队延迟 (bufferbloat),而不是传播延迟。视频 I 帧突发时若被丢进 BE(Best Effort)队列,会在路由器缓冲区里排几百毫秒------ DSCP 打标是唯一能在网关侧直接砍掉这部分延迟的手段 。

后续提问:DSCP是什么

Q6:RTP 弱网丢包有哪些抗性手段?

FEC 前向纠错:发冗余包(如 RFC 2198 RED / XOR 奇偶校验),丢 1 补 1

PLC 丢包隐藏:用前后帧波形/参数外推填补

ARQ 重传: 收到 NACK 再补发 视频/非严格实时

Q8:长时间通话"越打越卡"是什么原因?怎么修?

答 : 收发端晶振存在 ppm 级频率偏差 ,导致 RTP 时间戳与本地播放时钟不同步:

  • 发送端快 → 包持续"提前"到 → buffer 悄悄涨满 → 溢出丢包 → 延迟累积
  • 发送端慢 → buffer 持续排空 → underrun 卡顿
    修法(jitterctl.c ) :
  1. slide = slide*(1-0.03) + diff*0.03 ------ 用 EWMA 估计"长期时钟漂移量"(JC_BETA=0.03 ,允许 3% 漂移跟踪)。
  2. corrective_slide 按corrective_step = 160*8000/clock_rate 逐步 逼近 slide,每次只挪一小步------ 不能一次性对齐 ,否则会产生可闻的跳变/爆音。
  3. adapt_jitt_comp_ts = MAX(jitt_comp_ts, jitter) 做自适应补偿。

Q9:弱网下音视频不同步(lip-sync)怎么保证?为什么不能各自独立缓冲?

答 :

  • 音频 8kHz、视频 90kHz 是 两套独立时钟 ,各自 jitter buffer 延迟不同,必然漂移。
  • 解法是 RTCP SR 桥接 :SR 同时携带 NTP 墙钟时间和本媒体 RTP 时间戳,接收端由此建立"音频 RTP ts ↔ 视频 RTP ts ↔ 墙钟"的映射(项目 rtcp.c 中ntp_timestamp_msw/lsw 的写入)。
  • 以音频为主时钟 :音频不能断(人对断音极敏感),视频按差值 调整渲染时刻或丢帧追赶 。
  • 网关侧的额外保障:音视频用 同一套 NTP 基准 打时间戳,避免网关自身成为不同步源。
  • 弱网下原则: 同步优先于流畅 ,宁可丢视频帧,不可让音画错位超过 100ms(超过就"出画"了)。

Q10:给你一条弱网下的 RTP 通话,"卡顿",你的排查路径是什么?

答 (三步定位法,面试直接背):

  1. 抓包看网络 :tcpdump -i eth0 udp port 6000 -w /tmp/6000.pcap ,Wireshark → Telephony → RTP → Streams,看Delta 列(应稳定 20ms)、Jitter 列、丢包数、乱序数。先区分"网络真丢"还是"应用丢"。
  2. 看日志看应用 :currentDepth 频繁归零 = buffer 太小(抖动打穿);discarded 持续涨 = buffer 太大/溢出;outoftime 涨 = 包到得太晚(延迟已超预算)。
  3. 对比分段 :LAN/WAN 两侧同时抓包,对比包序与时间差,判断丢包/抖动发生在网关前还是网关后(GetRtpCount 看内核转发计数是否与对端发包数一致)。
    优化动作按收益排序 :
    ① 自适应 jitter buffer + 预缓冲(治抖动)→ ② 乱序重排 + 理论 seq 跟踪(治乱序)→ ③ FEC/PLC(治丢包)→ ④ 时钟漂移修正(治长通话累积)→ ⑤ DSCP/QoS(治排队延迟)→ ⑥ 直通转发替代终结(治架构性延迟)。

11 智能监控平台,对于 推流中断 怎么定位和排查?

  • 设备层 :摄像机/编码器是否在线、是否本地有输出(设备日志、Web 页面看码率)。常见:设备断电重启、编码参数被改、SD 卡/固件异常、连接数限制(同一路被多路拉取)。
  • 网络层 :链路丢包/抖动、上下行带宽不足、NAT/防火墙会话老化(默认 30 分钟,GB28181 UDP 心跳不够就断)、4G/5G 信号切换、专线抖动、MTU/分片。
  • 接入/信令层 :GB28181 的 REGISTER/INVITE/媒体流保活(Keepalive),RTMP 的握手与 publish 鉴权;SIP 注册过期、平台 IP/端口变更、鉴权失败、流 ID 冲突(同一通道 ID 被重复推流顶掉)。
  • 流媒体/分发层 :转码节点 CPU/内存、磁盘写满、单节点流数超限、级联上级断、CDN 回源失败。
  • 应用层 :播放鉴权、token 过期、拉流地址错误、播放器超时策略过短。

排查方向:

  • 会话表 :streamId/app/通道ID、推流方 IP、开始时间、最后收包时间、累计字节、当前码率、断开原因码。
  • 心跳与超时参数 :RTP 收包超时阈值、RTMP 空闲超时、SIP 注册周期,并统一记录对应阈值。
  • 抓包 :设备侧tcpdump -i any -n host <平台IP> ;平台侧同时抓,比对"设备发了但平台没收到"这类单向丢包。
  • 码率/帧率曲线 :断流前 5 分钟的码率、丢包率、关键帧间隔,比"断没断"更有价值。
  • 链路 traceId :一次推流从 SIP 注册 → INVITE → RTP → 分发 → 播放,全链路带同一个 requestId,能一键串日志。

最高频的根因(按现场经验排序):

  • NAT/防火墙会话老化 :UDP 媒体没有保活,30 分钟后静默断。→ 加 RTP 保活包或改 TCP 被动/主动模式。
  • 同一通道重复推流 :多个客户端/多平台同时推同一 streamId,被后来的顶掉,表现为"周期性闪断"。
  • 上行带宽不足 / 码率突增 :断流前码率打满,关键帧突发导致丢包。→ 看断流前 1 分钟码率峰值。
  • 编码器关键帧间隔过大 :GOP 10s+ 时丢一个 I 帧就黑屏十几秒,被误判为断流。
相关推荐
ShineWinsu1 小时前
对于Qt:QLabel常见属性的解析
c++·qt·面试·笔试·gui·标签·qlabel
Pniubi1 小时前
力扣42接雨水(动态规划法)
算法·leetcode·职场和发展
weixin_307779131 小时前
RAG 级联失效分析——面试中的错误归因艺术
人工智能·python·面试·职场和发展
智能直播2 小时前
MEDAI-W2_Tinyalsa音频_HDMI输出_CSDN文章
音视频·实时音视频·视频编解码
Pniubi2 小时前
力扣46全排列(回溯(递归))
算法·leetcode·职场和发展
Pniubi12 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
狗凯之家源码网14 小时前
吃瓜主题 3.0 视频源码深度评测与实战指南
音视频
每天进步一点点km15 小时前
自用-牛客网-华为机试编程模拟题1-python
华为od·华为·面试
美狐美颜sdk18 小时前
视频美颜SDK中的YUV与RGBA格式有什么区别?直播APP开发解析
人工智能·计算机视觉·音视频·美颜sdk·直播美颜sdk·视频美颜sdk