PPCDN开发复盘。
一、行业困扰:我们到底被什么卡住了
做互动视频游戏,最怕的不是"延迟高一点",而是**延迟不可控、时间不可对齐、播放不够稳**。
过去几年,Agora、腾讯云、华为云、Dolby 等大厂 CDN 我们先后都用过。它们各有优势,直播、RTC、媒体处理的能力都很强。但在我们这种"游戏结果要和视频画面严格同步"的场景里,有三个问题始终没有被真正解决。
1. 时延压不到 500ms 以内
互动游戏不是看直播,玩家操作、游戏判定、视频画面必须在同一个时间窗口里发生。
我们对端到端延迟的要求很明确:**最好稳定在 500ms 以内**。
但实际使用中,延迟经常在 800ms、1s 甚至更高,而且会随网络、区域、节点、协议变化。更麻烦的是,厂商通常只能给一个"平均延迟"或"P90/P99"指标,很难承诺某一条具体链路的实时延迟。
对于普通直播,1 秒和 2 秒可能只是"体验差一点";对于互动游戏,这意味着玩家看到的结果和实际判定对不上。
2. 播放器拿不到视频帧的绝对时间戳
这是最致命、也最容易被忽略的问题。
互动游戏的结果需要和视频流对齐。比如:
-
游戏在第 12.340 秒判定胜负;
-
视频画面需要精确显示第 12.340 秒发生了什么;
-
播放器必须知道"当前这一帧"对应的绝对采集时间。
但大多数标准播放器 API 只给你 `currentTime`、`buffered`、`videoWidth` 这类信息,**拿不到每一帧在采集端的绝对时间戳**。
没有这个时间戳,服务端和播放器只能靠估算:
-
用 RTT 猜延迟;
-
用 PTS 推算墙钟;
-
用 NTP 校时后再做二次拟合。
这些方法在普通直播里够用,在互动游戏里就会变成"看起来差不多,实际上对不上"。游戏结果和视频画面一旦出现几百毫秒的偏差,公平性就没了。
3. 播放流畅性始终不如 YouTube、TikTok
YouTube、TikTok 的播放体验为什么好?
因为它们有极其成熟的 ABR、缓冲策略、预加载、CDN 调度和客户端播放器优化。用户可以接受 1~2 秒的起播,但播放过程必须丝滑。
而很多直播 CDN 的优化重点是"低延迟",不是"低延迟下的流畅性"。弱网时:
-
该降档的时候降不下来;
-
降档时黑屏或卡顿;
-
网络恢复后升档很慢;
-
不同协议、不同编码、不同终端的表现不一致。
结果就是:延迟看起来不高,但观看体验不稳定。
二、原因分析:不是厂商不行,是这件事不划算
一开始我们也会问:大厂这么多工程师,为什么连这三个问题都解决不了?
后来想明白了:**不是技术做不到,而是这件事对视频 CDN 厂商来说不划算。**
1. 互动游戏是一个相对小众的市场
视频 CDN 的主战场是直播电商、在线教育、泛娱乐、赛事、会议。互动游戏只是其中很小的一块。
大厂的产品要服务尽可能多的客户,接口和策略必须标准化:
-
播放器要通用;
-
协议要标准;
-
调度要平台化;
-
SLA 要可复制。
而互动游戏要的恰恰是"非标准"的东西:帧级时间戳、游戏事件对齐、极低延迟、定制播放器、甚至定制推流端。
2. 端到端改造的成本太高
要真正解决这三个问题,不能只改 CDN 边缘节点,必须同时改:
-
推流端:采集、编码、时间戳、P2P 发布;
-
播放端:解码、ABR、时间戳读取、P2P 订阅;
-
媒体服务器:转发、调度、弱网策略;
-
控制面:鉴权、NAT 探测、容量分配、计费。
这是一条完整的端到端链路。任何一个环节不改,最终效果都会被打折。
对厂商来说,为一个细分市场重做推流端和播放器,投入产出比不高;对客户来说,等厂商排期也不现实。
**所以问题不是"没人会做",而是"没人愿意为这个小市场做端到端改造"。**
三、转机出现:Vibe Coding 把开发成本打下来了
真正的转机,是 AI 编程助手的成熟。
过去做一个定制推流端、定制播放器、定制媒体服务器,光是把代码写出来、调通、联调、压测,就需要一个不小的团队和很长的周期。
现在,Vibe Coding 让"写代码"和"调代码"的成本大幅下降:
-
不熟悉的代码库,可以让 AI 先梳理调用链;
-
重复的协议处理、SDP 解析、状态机,可以让 AI 快速生成;
-
日志、抓包、压测脚本,可以让 AI 帮忙写;
-
一个故障,可以从日志、数据库、浏览器 `getStats()` 多路并行分析。
于是我决定:**既然大厂不愿意为互动游戏做端到端优化,那我就自己手搓一套。**
这套东西就是 **PPCDN**(`pp-cdn.org`)------一个 **WebRTC CDN Platform**,也是一套面向互动直播的 **UltraLow Latency Video API**。
为什么叫 pp
"pp" 有两层含义,正好对应我们最在意的两件事:
-
**P2P connection**:观众和推流端能直连就直连,绕开中心节点,延迟最低、边缘带宽最省;
-
**Precise P2P latency**:不仅能直连,还要能**准确测量并读取 P2P 时延**,让延迟从"感觉"变成可验证的数字。
这两点,是 PPCDN 和普通直播 CDN 最不一样的地方。
四、技术框架:定制推流端 + 定制播放器才是关键
我们很快确认了一件事:
> **上面三个问题,靠单个服务器或单个边缘节点是解决不了的,必须做端到端优化。**
所以 PPCDN 从第一天起就不是"买一个媒体服务器,再套一个播放器"的方案,而是推流端、播放端、媒体节点和控制面一起设计:
```text
┌──────────────────────────────┐
│ ppcenter │
│ 调度 / 鉴权 / P2P 信令 │
└───────┬──────────────┬───────┘
│ │
│ 信令 │ 信令
▼ ▼
┌──────────┐ WHIP/SRT/ERTMP ┌──────────┐ Forward ┌──────────┐ WHEP ┌──────────┐
│ ppobs │ ───────────────▶ │ Origin │ ────────▶ │ Edge │ ─────▶ │ pplayer │
│ 推流端 │ │ (ppmmx) │ │ (ppmmx) │ │ 播放器 │
└────┬─────┘ └──────────┘ └──────────┘ └────┬─────┘
│ │
└──────────────── P2P 直连(H264,媒体不经过 Origin/Edge)─────────────────┘
```
这里要特别强调:
-
**ppobs ⇄ pplayer 是 P2P 直连**,媒体包不经过 Origin/Edge;
-
**ppcenter 只负责协调**:调度、鉴权,以及转发 SDP/ICE 信令,**不转发媒体**;
-
只有 P2P 不可用时,pplayer 才回落到 `Edge → WHEP` 的媒体路径。
1. ppobs:基于 OBS Studio 的定制推流端
ppobs 不是简单套壳 OBS,而是在 OBS 的采集、编码、输出链路上做了深度定制:
-
支持 **WHIP(WebRTC)** 和 **SRT** 推流;
-
支持基于 TCP/UDP 的 **Simulcast** 多档同播;
-
支持 **HEVC + H264 多轨**;
-
推流端同时作为 **P2P 发布者**,直接服务观众;
-
在码流里注入 **SEI 绝对时间戳**,供播放器精确计算端到端延迟;
-
本地完成多档编码,服务端只转发,不做转码。
为什么一定要改推流端?
因为时间戳、编码参数、Simulcast 层数、P2P 发布能力,都必须在采集和编码阶段就确定。只在服务端做文章,永远拿不到"这一帧是什么时候采集的"。
2. pplayer:基于浏览器 WebRTC 的定制播放器
pplayer 也不是普通 `<video>` 播放器,而是直接使用浏览器内置的 WebRTC 引擎:
-
标准 **WHEP** 拉流;
-
**ABR** 自适应码率,支持手动切换质量;
-
支持 **HEVC / H264**,按浏览器解码能力选流;
-
作为 **P2P 订阅者**,优先尝试直连推流端;
-
解析码流里的 **SEI 绝对时间戳**,显示真实的 Edge / P2P 时延;
-
P2P 失败或名额耗尽时,干净回落到 Edge。
为什么一定要改播放器?
因为标准播放器 API 不暴露帧级绝对时间戳,也不负责 P2P 准入和 ABR 策略。只有在播放器内部同时掌握"解码、时间、网络、P2P 信令",才能把延迟测准、把画面放稳。
3. 媒体服务器与控制面:用 Go 重写
流媒体服务器和管理服务器,我们选择了 Go。
Go 被称为"网络时代的 C++":并发模型简单、部署轻量、性能足够,非常适合做长连接、信令、调度和边缘转发。
媒体面基于成熟的 **MediaMTX** 做定制:
-
Origin 负责稳定收流;
-
Edge 被动接收 Origin 的转发,就近服务观众;
-
Forward 负责跨区域桥接;
-
控制面 ppcenter 不碰媒体包,只做鉴权、调度、P2P 信令、计费和报表。
> 砖头已经成熟,房子没理由盖不起来。
> 前提是,你愿意自己画图纸、自己砌墙,而不是指望别人给你一套刚好合适的房子。
五、落地开发:顺利的部分,和真正费时的部分
真正开始写之后,有些地方比想象中顺利。
1. P2P 穿透率其实很高
我们原本担心 NAT 穿透会是最大的坑。
实际测试下来,在普通家庭宽带、办公网络、移动网络里,P2P 直连的成功率比预期高很多。只要双方不是对称 NAT / CGNAT,STUN 打洞通常都能建立连接。
当然,PPCDN 不做 TURN 中继。打不通就老老实实回 Edge,不假装"穿透成功"。对互动游戏来说,**稳定的失败回退**比"偶尔成功、偶尔卡住"更重要。
2. SEI 时间戳编码/解码并不费事
把绝对时间戳写进 H264/HEVC 的 SEI,再在播放器里读出来,技术上并不复杂。
真正难的是:
-
时间戳要在采集/编码链路里打,而不是在服务端补;
-
不同 sender 的时间轴单位要统一;
-
播放器要能区分"帧时间戳"和"估算延迟";
-
弱网、重连、切档时,时间戳不能断。
我们最后放弃了"用 RTP 时间轴外推墙钟"的做法,直接在编码帧经过 transform 时使用当前墙钟。这样虽然不追求理论上的绝对精确,但能保证**测出来的就是当前这一帧的真实发送时间**,不会再出现 45 秒、12 秒这种明显错误。
3. ABR 切换非常丝滑
因为编码在推流端完成,码率档位在推流时就固定好了;播放器切档时只是切换不同的 Simulcast 层,不需要服务端转码,也不需要重新建立整条链路。
实际体验里,ABR 切换基本无感,弱网降档、恢复升档都很平滑。
4. 真正费时的是"横向扩容"
功能跑通只是开始。要做成商业化服务,最难的是容量和成本:
-
单节点能扛多少路并发?
-
新节点上线后,流量怎么分?
-
Origin 和 Edge 的带宽预算怎么分配?
-
某个区域突然爆量,怎么自动扩容?
-
P2P 省下来的带宽,怎么反馈到调度和计费?
-
节点故障时,观众怎么无感切走?
这些问题没有标准答案,只能靠压测、监控和不断调参。
也正是在这个阶段,AI 编程助手的价值变得非常明显:它不能替你做容量决策,但可以帮你快速写压测脚本、分析指标、对比不同调度策略,把"试错"的成本降下来。
六、压测数据
下面是我们在 AWS 上的一组实测数据,用于说明当前实现的量级,不构成商业 SLA。
单节点并发
测试机型:**AWS 2 vCPU / 4GB**
| 单节点并发 | **300 路** |
单 Region 容量
测试规格:**64 vCPU**
| 单 AWS Region 并发 | **5000 路** |
这里的"并发"指同时在线播放连接数,实际可承载量会受码率、码流复杂度、网络出口、P2P 命中率等因素影响。
七、P2P 时延 Benchmark
测试环境:
-
节点机:**AWS Singapore**
-
推流地点:**Manila**
-
拉流地点:**Manila,但与推流不在同一地点/同一网络**
-
路径:P2P 直连
| 推流协议 | P2P 端到端时延 |
| --- | --- |
| WHIP | **150ms** |
| ERTMP | **160ms** |
| SRT | **440ms** |
几个观察:
-
**WHIP 最低**。WebRTC 原生链路,少一层封装,时间戳和 P2P 信令都在同一条技术栈里。
-
**ERTMP 接近 WHIP**。Enhanced RTMP 在多轨和低延迟上比传统 RTMP 好很多,但仍有 RTMP 家族的封装成本。
-
**SRT 明显更高**。SRT 的 ARQ、TS 封装和接收缓冲换来了抗丢包能力,代价是延迟更高。它适合弱网/长距离稳定传输,不是极限低延迟的首选。
这也是为什么 PPCDN 同时支持 WHIP、SRT 和 ERTMP:**不同场景选不同协议,而不是用一个协议打天下。**
八、结语:不是再做一个 CDN,而是为互动视频重做一条链路
PPCDN 的目标不是取代所有通用视频 CDN。
它更像是一条为互动游戏、实时竞拍、在线课堂、1 对 1 视频这类场景专门优化的链路:
-
端到端延迟尽量压到 500ms 以内;
-
推流端和播放器都能拿到帧级绝对时间戳;
-
P2P 直连优先,失败干净回落到 Edge;
-
ABR 在低延迟下仍然保持流畅;
-
用定制推流端 + 定制播放器 + Go 媒体节点,把三个痛点一起解决。
这套东西能做出来,一方面是因为 MediaMTX、WebRTC、OBS 这些"砖头"已经足够成熟;另一方面,是因为 Vibe Coding 把开发和调试的成本降到了个人/小团队可以承受的范围。
AI 可以帮你写代码、读日志、做压测、分析故障;但下面这些仍然必须由人来做:
-
判断哪些问题值得解决;
-
选择什么协议、什么编码、什么架构;
-
在延迟、流畅性、成本之间做取舍;
-
对最终结果负责。