这个系列文章我们来介绍音视频相关面试题,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍网络传输优化。
——来自公众号“关键帧Keyframe”的分享
1、优化目标与 KPI
| 指标 | 直播连麦 | 云游戏 | 远程驾驶 |
|---|---|---|---|
| 端到端延迟 | ≤ 200 ms | ≤ 60 ms | ≤ 30 ms |
| 卡顿率(>1% 丢包) | ≤ 0.3% | 0%(视觉) | 0%(视觉) |
| 吞吐 | 1–5 Mbps | 5–50 Mbps | 2–20 Mbps |
| 并发 | 10 万路 | 单实例 | 单车 |
口诀:“带宽换延迟,冗余换流畅,算法换并发”
2、传输层选型速查
| 协议 | 头部开销 | 拥塞控制 | 用户态实现 | 适用场景 |
|---|---|---|---|---|
| TCP | 20–60 B | 内核 CUBIC | 否 | 点播、文件 |
| UDP | 8 B | 无 | 是 | RTC、直播 |
| QUIC | 12–30 B | BBR/BBRv3 | 是 | 直播、WebTransport |
| SRT | 16 B | UDT+ARQ | 是 | 广电级直播 |
| RUDP | 4 B | 自定义 | 是 | 手游、IoT |
建议矩阵:
低延迟 + 可控场景 → UDP + 自研 CC
穿透防火墙 + 高吞吐 → QUIC + BBRv3
广电下行 → SRT
3、UDP 裸流发送“零拷贝”模板(io_uring)
#include <liburing.h>
#include <arpa/inet.h>
#define BUF_SZ 1500
#define BATCH 64
struct iovec iov[BATCH];
struct msghdr msg[BATCH];
struct io_uring ring;
void udp_send_batch(int fd, struct sockaddr_in *dst)
{
int idx = 0;
for (int i = 0; i < BATCH; i++) {
iov[i] = (struct iovec){ .iov_base = get_payload(i),
.iov_len = BUF_SZ };
msg[i] = (struct msghdr){
.msg_name = dst,
.msg_namelen = sizeof(*dst),
.msg_iov = &iov[i],
.msg_iovlen = 1
};
io_uring_prep_sendmsg(ring.sqe++, &msg[i], 0);
}
io_uring_submit(&ring);
}
收益:**CPU↓18%**,p99 延迟↓2 ms(千兆网卡)
4、拥塞控制算法实战
4.1、GCC(Google Congestion Control)
WebRTC 默认,分两部分:
| 方向 | 算法 | 反馈周期 | 关键参数 |
|---|---|---|---|
| 发送端 | Loss-based | 1 RTT | instant_threshold = 2% |
| 接收端 | Delay-based | 1 s | overuse_time = 10 ms |
代码片段(简化):
void UpdateDelayGradient(int64_t ts_delta,
int64_t arrival_delta) {
double gradient = static_cast<double>(ts_delta - arrival_delta);
if (gradient > threshold_ && overuse_time_ > 10) {
state_ = kOveruse;
bitrate_ *= 0.85;
} else if (gradient < -threshold_) {
state_ = kUnderuse;
bitrate_ *= 1.05;
}
}
4.2、 BBR v3(QUIC-GO 实现)
import "github.com/quic-go/quic-go"
quicConf := &quic.Config{
MaxIdleTimeout: 30 * time.Second,
CongestionControl: congestion.NewBBRSender(
congestion.InitialMaxDatagramSize(1500),
congestion.MaxBandwidth(50*1024*1024), // 50 Mbps
congestion.InitialRTT(20*time.Millisecond),
),
}
调参口诀
ProbeBW_DRAIN=3→ drain 更激进,降缓冲ProbeRTTInterval=2s→ 2 s 主动降窗测 RTT
5、弱网对抗组合拳
| 技术 | 触发条件 | 额外延迟 | 恢复能力 |
|---|---|---|---|
| FEC | 丢包 < 5% | 0 ms | 10% 丢包 |
| ARQ | 突发 > 3 包 | 1 RTT | 任意丢包 |
| Redundant Audio | voice | 0 ms | 30% |
| SVC | video | 0 ms | 分层丢弃 |
FEC + ARQ 混合策略(UDP 自研):
typedef struct RcSession {
uint32_t seq;
uint8_t fec_ratio; // 10%
uint8_t max_nack; // 3
uint32_t nack_list[32];
int64_t first_nack_ts;
} RcSession;
void on_packet_loss(RcSession *s, uint32_t lost_seq) {
if (s->nack_count < s->max_nack)
send_nack(s, lost_seq);
else
send_fec_burst(s, lost_seq); // 启动 FEC 突发
}
6、抖动缓冲(JitterBuffer)
6.1、语音 NetEQ(WebRTC)
见第22章,补充视频 JitterBuffer:
class VideoJitterBuffer {
public:
void Insert(const RTPPacket& pkt);
std::optional<Frame> GetFrame(int64_t playout_ts);
private:
std::map<uint32_t, RTPPacket> packets_;
int64_t target_delay_ms_ = 80; // 初始 80 ms
int64_t max_delay_ms_ = 250;
};
自适应算法:
int64_t UpdateDelay(int64_t arrival_ms, int64_t rtp_ts) {
int64_t jitter = abs(arrival_ms - rtp_ts * 1000 / 90);
double alpha = 0.9;
avg_jitter_ = alpha * avg_jitter_ + (1 - alpha) * jitter;
return std::clamp(avg_jitter_ + 4 * std_dev_, 20, max_delay_ms_);
}
7、测量与可视化
7.1、实时指标
# prometheus exporter
rtc_rtt_ms 23.4
rtc_packet_loss_percent 2.1
rtc_bitrate_bps 1523000
7.2、弱网模拟(TC 命令一键脚本)
#!/bin/bash
# 100 ms 延迟 + 5% 随机丢包 + 20 ms 抖动
sudo tc qdisc add dev eth0 root netem delay 100ms 20ms distribution normal loss 5%
恢复:
sudo tc qdisc del dev eth0 root
7.3、火焰图定位 CPU 瓶颈
perf record -F 9999 -a -g -- ./rtc_send
perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > send.svg
8、性能清单(Checklist)
| 维度 | 优化项 | 收益 |
|---|---|---|
| 内核 | sysctl -w net.core.rmem_max=26214400 | 降抖动 30% |
| 网卡 | 开启 RSS + XDP(DPDK) | 10 Mpps→100 Mpps |
| 应用 | recvmmsg/sendmmsg 批量收发包 | CPU↓25% |
| 算法 | BBRv3 替代 CUBIC | 吞吐↑40% |
| 冗余 | FEC 比例动态 5%~30% | 卡顿↓50% |
9、一键 Demo:UDP + FEC + 测速
git clone https://github.com/0voice/rtc-netopt.git
cd udp-fec
make
# 终端1 接收
./recv 0.0.0.0 5001
# 终端2 发送
./send 127.0.0.1 5001 --bitrate 5Mbps --loss 5 --fec 10
输出:
[SUM] 5.01 Mbps 2.1% RX-loss 0.0% Video-freeze
学习和提升音视频开发技术,推荐你加入我们的知识星球:【关键帧的音视频开发圈】

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。