PPCDN ERTSP 协议与嵌入式设备接入指南¶
本文写给需要接入嵌入式/受限设备(IP 摄像机、硬件编码器、机顶盒等跑不动浏览器级 WebRTC 协议栈的终端) 的团队。它说明 PPCDN 的 ERTSP 能力到底是什么、怎么鉴权、有哪些限制,以及和 WHIP/WHEP 路径的关系。 本文是这个能力目前唯一的设计说明文档;此前只有代码注释和版本更新记录,没有独立文档。
0. 一句话结论¶
ERTSP(Enhanced RTSP)让只会说标准 RTSP、跑不动 WebRTC 协议栈的设备,也能直接接入 PPCDN:
推流端用 ANNOUNCE/RECORD 推流,播放端用 DESCRIBE/SETUP/PLAY 拉流——协议本身是标准 RTSP,
PPCDN 只是在这条已有路径上加了一层与 WHIP/WHEP 同源的签名鉴权,没有另起一套协议或一套密钥体系。
1. 为什么需要 ERTSP:嵌入式设备的现实约束¶
PPCDN 的主路径是 WHIP 推流 + WHEP 播放,这对浏览器、现代 App 很合适——但一台 IP 摄像机或硬件编码器, 通常只有 RTSP 输出/输入能力,不会、也没有资源去实现一套完整的 WebRTC/ICE/DTLS 协议栈。这类设备要接入 低延迟直播平台,过去常见的做法是业务自己搭一个 RTSP→WHIP 的转码网关——多一跳转码,就多一份延迟和一份 运维成本。
ERTSP 的思路是反过来:不逼设备学 WebRTC,而是让 PPCDN 的媒体节点直接支持标准 RTSP 收流/发流, 设备侧几乎零改造,只需要把推流/拉流地址换成 PPCDN 签发的带签名的 RTSP URL。
2. ERTSP 推流:地址怎么拿、怎么鉴权¶
设备侧调用 POST /v1/publish/requests,protocol 传 "ertsp",拿到一条类似这样的地址:
rtsp://{txTime}:{txSecret}@{host}:8554/{appId}/{streamName}
{host}是 ppcenter 为这次推流选中的 Origin 地址(选节点逻辑复用已有的池过滤 + 剩余容量优先排序, 只是多了一个 ERTSP 专用的候选筛选函数,没有另起一套调度规则)。- 鉴权信息直接编码在 RTSP URL 的"用户名:密码"里(标准 RTSP Basic Auth 的位置),设备侧不需要任何 额外的签名计算:
txTime是过期时间戳(十六进制);txSecret是HMAC-SHA256(authKey, "{appId}/{streamName}:{txTime}")的十六进制摘要。
媒体节点收到 ANNOUNCE 时用同一个密钥重新计算 txSecret 校验,鉴权失败会带上标准的
WWW-Authenticate 挑战头返回 401,而不是一个裸的错误——这样符合标准 RTSP 客户端的重试预期。
工程教训(真实踩过的坑):ERTSP 最早用的是和 WHIP 推流一致的长 token(AES-GCM 加密,约 168 字符)。真实联调时发现:很多 RTSP 客户端的底层库(包括 ffmpeg 所用的 libavformat)会把 RTSP Basic Auth 的
user:pass静默截断到约 127 字符——长 token 从未完整送达服务端,推流鉴权必然失败,而且 现象上毫无提示。改成上面这套短得多的txTime + HMAC方案后,长度和播放端签名(txTime:txSecret) 是同一量级,彻底绕开了这个截断上限。这是一次真实端到端联调发现并修复的问题,不是纸面设计。
3. ERTSP 拉流:地址怎么拿、怎么鉴权¶
播放端调用 POST /v1/play/requests,capability 传 "ertsp",拿到:
rtsp://{txTime}:{txSecret}@{host}:8554/{appId}/{streamName}/{codec}
签名用的是和 WHEP 播放完全相同的一套 HMAC 校验(同一个密钥派生、同一段验证代码),不是为 ERTSP
专门写的第二套。媒体节点在标准 RTSP 的 SETUP 阶段校验这个签名,通过后才允许 PLAY。{codec} 对应
推流时实际发布的轨道(h264 或 hevc)。
4. 编码限制:单轨 H264/HEVC + Opus/AAC,不支持多轨同播¶
AAC 只有 RTSP / ERTSP 推流才被接受:ppmmx 对 SRT、Enhanced RTMP、WHIP、MoQ 推流只接受 Opus。ERTSP 的 AAC 音频会被接受,但转发给其它节点和 WebRTC(WHEP)播放时会被丢弃(WebRTC 不承载 AAC、服务端不转码),需要观众听到声音时请用 Opus。
ERTSP 面向的是"嵌入式设备读回一路固定清晰度"的场景,不是浏览器那种按网络状况动态切档的播放,所以 媒体节点对 ERTSP 推流做了明确限制:
| 维度 | ERTSP 允许 | 不允许 |
|---|---|---|
| 视频编码 | H264、HEVC(二选一) | AV1 等其他编码 |
| 音频编码 | Opus、AAC(二选一) | G711 等其他编码 |
| 轨道数量 | 恰好 1 路视频 + 1 路音频 | 0 路或多路视频、Simulcast、多轨同播 |
这组限制在 RECORD(推流确认)阶段强制校验,不满足会直接拒绝——这是刻意的简化:嵌入式设备通常本身
就只有一路固定编码输出,不需要、也无法消费 PPCDN 面向浏览器端的 Simulcast/多轨能力。
5. 安全:复用已有的签名体系,不是另起一套¶
- 推流和播放的签名密钥与 WHIP/WHEP 走的是同一套基础设施(
txTime/txSecretHMAC 方案), ERTSP 没有引入新的密钥管理或加密算法。 - 鉴权是否生效由节点配置的独立开关控制(
rtsp总开关 +rtspErtspAuthEnable签名校验开关), 两者都关闭时该节点不接受 RTSP 连接;都打开后,ERTSP 的推流/播放签名校验在标准 RTSP 鉴权逻辑之外 强制生效,不能被绕过。 - RTSP 本身不是加密传输协议——和 WHIP/WHEP 的 TLS/DTLS-SRTP 不同,ERTSP 的媒体数据走明文 RTP。 这是标准 RTSP 生态的现实限制,不是 PPCDN 刻意弱化;需要加密传输的场景应继续走 WHIP/WHEP。
6. 落地方式:设备侧几乎零改造¶
对已经在用标准 RTSP 协议栈的设备(摄像机厂商 SDK、硬件编码器固件),接入 PPCDN 不需要重新适配协议, 只需要:
- 业务侧按设备身份调用
POST /v1/publish/requests(protocol=ertsp)/POST /v1/play/requests(capability=ertsp),拿到带签名的 RTSP URL; - 把这条 URL 填进设备或播放端已有的 RTSP 推流/拉流配置里——大多数摄像机固件和
ffmpeg/VLC这类 通用 RTSP 客户端本身就支持 URL 内嵌的用户名:密码认证,不需要为 PPCDN 单独写一段鉴权代码。
7. 嵌入式设备接入指南¶
本节讲真实接入:一台只会 RTSP 的嵌入式设备(IP 摄像机、硬件编码器、机顶盒等),怎么拿到推流地址、 怎么选播放地址、怎么把流播出来。
客户端支持范围(重要):这条能力面向标准 RTSP 客户端——设备自带协议栈、
ffmpeg、VLC等。 PPCDN 自带的ppobs客户端不支持 ERTSP 推流,pplayer播放器不支持 RTSP 拉流; 推流用标准 RTSP 客户端(走ANNOUNCE/RECORD),播放用标准 RTSP 客户端(走DESCRIBE/SETUP/PLAY)。
7.1 获取 RTSP 推流地址¶
业务后端按设备身份调用 POST /v1/publish/requests,protocol 传 "ertsp":
curl -sS https://api.pp-cdn.org/v1/publish/requests \
-H 'Content-Type: application/json' \
-d '{"appId":"app_xxx","appSecret":"<appSecret>","streamName":"B01-frontView","protocol":"ertsp"}'
返回里 ppcdnPublishEndpoint 就是一条完整的、带签名的 RTSP 推流地址(不是 SRT/RTMP 那种裸 host:port 模板):
{
"originNodeId": 12,
"ppcdnPublishEndpoint": "rtsp://<txTime>:<txSecret>@<origin-host>:8554/app_xxx/B01-frontView",
"expiresAt": "2026-10-16T12:00:00Z"
}
streamName必须是{tableId}-{view}两段式(和 WHIP/SRT 推流一致)。- 鉴权信息已内嵌在 URL 的
txTime:txSecret里,设备侧不需要再做任何签名计算。 - 这条凭证默认 1 小时有效(见
expiresAt),过期后重新调一次本接口即可。 - 把整条地址填进设备的 RTSP 推流配置(
ANNOUNCE/RECORD)即可开推。
7.2 选择播放地址:WebRTC(WHEP)或 RTSP(ERTSP)¶
播放端调用 POST /v1/play/requests,capabilities 二选一:
| 走哪条路 | capabilities |
返回的地址 |
|---|---|---|
| WebRTC 低延迟播放(浏览器 / 能跑 WebRTC 的终端) | ["whep"] |
edgeStreamURL = WHEP 地址 |
| 标准 RTSP 播放(嵌入式设备) | ["ertsp"] |
edgeStreamURL = 带签名的 rtsp://... |
播放请求需要 viewer token(Authorization: Bearer <appId>:<txTime>:<txSecret>,txSecret 用该 app 的
appSecret 对 {appId}/{streamName} 做 HMAC,见推流/播放 API 文档)。以 RTSP 为例:
curl -sS https://api.pp-cdn.org/v1/play/requests \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer app_xxx:<txTime>:<txSecret>' \
-d '{"streamName":"B01-frontView","clientId":"cam-01","requestRegion":"","capabilities":["ertsp"]}'
返回:
{
"mode": "edge-ertsp",
"edgeStreamURL": "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264",
"expiresAt": "2026-10-16T12:00:00Z"
}
ERTSP 播放不参与 P2P,也不动态切档,固定返回一路 H264;需要 P2P 直连 / 多档 ABR 的场景请选
whep。
7.3 如何播放 WHEP 流(WebRTC)¶
capabilities:["whep"] 返回的 edgeStreamURL 是一个 WHEP 端点:
- 播放端向该地址
POST一个 SDP offer(Content-Type: application/sdp),服务端返回 SDP answer; - 按标准 WebRTC 建立连接后即可播放。
- 浏览器可直接用标准 WHEP 客户端(如 PPCDN 的
pplayer)播放。 - 命令行 / 嵌入式环境通常没有 WebRTC 协议栈,这种情况请改走 7.2 的
ertsp(见 7.4)。
7.4 如何播放 RTSP 流¶
capabilities:["ertsp"] 返回的 edgeStreamURL 就是一条标准 RTSP 拉流地址,用户名/密码已内嵌,
直接交给设备的 RTSP 客户端即可:
- ffmpeg / ffplay:
ffplay "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264"
# 拉一路存文件(-rtsp_transport tcp 在弱网下更稳):
ffmpeg -rtsp_transport tcp -i "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264" -c copy out.mp4
- VLC:
vlc "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264" - 设备自带 RTSP 协议栈:把整条 URL(含
user:pass@)填进播放配置即可,无需额外鉴权代码。
地址里的 token 有有效期(
expiresAt),到期前重新调用 7.2 的接口换取新地址。
8. 自查清单¶
- [ ] 你要接入的设备,是否本身就只支持 RTSP、无法实现 WebRTC/ICE/DTLS 协议栈?
- [ ] 这路流是否天然只有一路固定编码(而不需要 Simulcast 多档位)?
- [ ] 你的场景能接受 RTSP 明文传输,还是必须要 TLS/DTLS-SRTP 级别的加密(后者请走 WHIP/WHEP)?
- [ ] 是否需要和浏览器端观众共享同一路流(ERTSP 播放端和 WHEP 播放端可以同时拉同一路 Origin 的流)?
如果前两项都符合、第三项可以接受明文传输,ERTSP 大概率比自建一个 RTSP→WHIP 转码网关更省事。
9. 免责声明¶
- 本文记录的是 ERTSP 当前的实现与生产配置状态(推流/播放 URL 格式、签名方案、编码限制),截至本文 写作时,这是该能力唯一的文档说明——此前只有代码注释和内部版本更新记录。
- URL 格式、端口、签名细节随产品迭代可能调整,以实际 API 返回值为准,不要在业务代码里硬编码本文 给出的字符串格式。
- 本文不涉及具体设备型号的兼容性承诺;不同厂商的 RTSP 实现在认证头处理上可能存在差异(见第 2 节的 工程教训),接入前建议先用目标设备或其 SDK 做一次真实联调。