跳转至

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/txSecret HMAC 方案), ERTSP 没有引入新的密钥管理或加密算法。
  • 鉴权是否生效由节点配置的独立开关控制(rtsp 总开关 + rtspErtspAuthEnable 签名校验开关), 两者都关闭时该节点不接受 RTSP 连接;都打开后,ERTSP 的推流/播放签名校验在标准 RTSP 鉴权逻辑之外 强制生效,不能被绕过。
  • RTSP 本身不是加密传输协议——和 WHIP/WHEP 的 TLS/DTLS-SRTP 不同,ERTSP 的媒体数据走明文 RTP。 这是标准 RTSP 生态的现实限制,不是 PPCDN 刻意弱化;需要加密传输的场景应继续走 WHIP/WHEP。

6. 落地方式:设备侧几乎零改造

对已经在用标准 RTSP 协议栈的设备(摄像机厂商 SDK、硬件编码器固件),接入 PPCDN 不需要重新适配协议, 只需要:

  1. 业务侧按设备身份调用 POST /v1/publish/requests(protocol=ertsp)/POST /v1/play/requests (capability=ertsp),拿到带签名的 RTSP URL;
  2. 把这条 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 端点:

  1. 播放端向该地址 POST 一个 SDP offer(Content-Type: application/sdp),服务端返回 SDP answer;
  2. 按标准 WebRTC 建立连接后即可播放。
  3. 浏览器可直接用标准 WHEP 客户端(如 PPCDN 的 pplayer)播放。
  4. 命令行 / 嵌入式环境通常没有 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 做一次真实联调。