Skip to content

PPCDN ERTSP protocol & embedded-device integration guide

This note is for teams that need to integrate embedded/constrained devices (IP cameras, hardware encoders, set-top boxes — anything that can't run a browser-class WebRTC stack). It explains what PPCDN's ERTSP capability is, how it authenticates, what its limits are, and how it relates to the WHIP/WHEP path. This is currently the only design note for this capability; before it there were only code comments and internal version history.

0. One-line takeaway

ERTSP (Enhanced RTSP) lets devices that only speak standard RTSP and can't run a WebRTC stack connect to PPCDN directly: publishers push with ANNOUNCE/RECORD, viewers pull with DESCRIBE/SETUP/PLAY — the protocol is standard RTSP, and PPCDN only adds a signature-auth layer drawn from the same source as WHIP/WHEP, without inventing a new protocol or a new key system.

1. Why ERTSP: the real constraints of embedded devices

PPCDN's main path is WHIP publish + WHEP playback, which suits browsers and modern apps — but an IP camera or hardware encoder usually only has RTSP in/out and won't (and can't afford to) implement a full WebRTC/ICE/DTLS stack. The old way to bring such a device onto a low-latency live platform was to build your own RTSP→WHIP transcoding gateway — one more hop, one more delay, one more thing to operate.

ERTSP flips it: instead of forcing devices to learn WebRTC, PPCDN's media nodes support standard RTSP ingest/egress directly. The device barely changes — it just swaps its publish/play address for a signed RTSP URL issued by PPCDN.

2. ERTSP publish: how to get the address, how it authenticates

The device side calls POST /v1/publish/requests with protocol set to "ertsp" and gets an address like:

rtsp://{txTime}:{txSecret}@{host}:8554/{appId}/{streamName}
  • {host} is the Origin ppcenter selected for this publish (selection reuses the existing pool filtering + least-used-capacity ordering, plus an ERTSP-specific candidate filter — no separate scheduling rules).
  • Auth is encoded directly in the RTSP URL's "user:password" (the standard RTSP Basic Auth position); the device needs no extra signing:
  • txTime is the expiry timestamp (hex);
  • txSecret is the hex digest of HMAC-SHA256(authKey, "{appId}/{streamName}:{txTime}").

On ANNOUNCE the media node recomputes txSecret with the same key; a failed check returns 401 with a standard WWW-Authenticate challenge rather than a bare error — matching standard RTSP client retry expectations.

Engineering lesson (a real pitfall): ERTSP originally used the same long token as WHIP publish (AES-GCM, ~168 chars). In a real integration, many RTSP clients' underlying libraries (including ffmpeg's libavformat) silently truncate RTSP Basic Auth user:pass to ~127 chars — the long token never arrived intact, so publish auth always failed, with no visible hint. The shorter txTime + HMAC scheme above is the same magnitude as the viewer-side signature (txTime:txSecret) and sidesteps the truncation limit entirely. This was found and fixed in a real end-to-end integration, not on paper.

3. ERTSP play: how to get the address, how it authenticates

The viewer calls POST /v1/play/requests with a capability of "ertsp" and gets:

rtsp://{txTime}:{txSecret}@{host}:8554/{appId}/{streamName}/{codec}

The signature uses exactly the same HMAC verification as WHEP playback (same key derivation, same verification code), not a second scheme written for ERTSP. The media node verifies it during standard RTSP SETUP and only allows PLAY after it passes. {codec} matches the track actually published (h264 or hevc).

4. Codec limits: single H264/HEVC + Opus/AAC, no multitrack simulcast

AAC is accepted only on RTSP / ERTSP publishes: ppmmx accepts Opus only on SRT, Enhanced RTMP, WHIP and MoQ publishes. ERTSP AAC audio is accepted, but it is dropped when forwarded to other nodes and when played over WebRTC (WHEP), because WebRTC cannot carry AAC and nothing is transcoded; use Opus if viewers must hear the audio.

ERTSP targets "an embedded device reading back one fixed rendition", not the browser's adaptive layer switching, so the media node imposes explicit limits on ERTSP publishes:

Dimension ERTSP allows Does not allow
Video codec H264 or HEVC (one) AV1, etc.
Audio codec Opus or AAC (one) G711, etc.
Track count exactly 1 video + 1 audio 0 or multiple video tracks, Simulcast, multitrack

These limits are enforced at RECORD (publish confirmation); failing them is rejected outright. It's a deliberate simplification: an embedded device usually has a single fixed encoder output and neither needs nor can consume PPCDN's browser-facing Simulcast/multitrack.

5. Security: reuse the existing signature system, not a new one

  • Publish and play signing share the same infrastructure as WHIP/WHEP (txTime/txSecret HMAC); ERTSP introduces no new key management or crypto.
  • Whether auth is active is controlled by node config switches (rtsp master switch + rtspErtspAuthEnable signature switch); with both off the node accepts no RTSP connection; with both on, ERTSP's publish/play signature check is enforced on top of standard RTSP auth and can't be bypassed.
  • RTSP itself is not an encrypted transport — unlike WHIP/WHEP's TLS/DTLS-SRTP, ERTSP media runs over plaintext RTP. That's a reality of the standard RTSP ecosystem, not a deliberate weakening; scenarios needing encrypted transport should keep using WHIP/WHEP.

6. Adoption: near-zero change on the device side

For devices already running a standard RTSP stack (camera vendor SDKs, hardware encoder firmware), PPCDN needs no protocol re-adaptation — only:

  1. the business side calls POST /v1/publish/requests (protocol=ertsp) / POST /v1/play/requests (capability=ertsp) per device identity to get the signed RTSP URL;
  2. put that URL into the device's or player's existing RTSP publish/play config — most camera firmware and generic RTSP clients like ffmpeg/VLC already support credentials embedded in the URL, so no PPCDN-specific auth code is needed.

7. Embedded-device integration guide

This section is about real integration: for an RTSP-only embedded device (IP camera, hardware encoder, set-top box, …), how to get the publish address, how to choose the play address, and how to play the stream.

Client support (important): this capability is for standard RTSP clients — the device's own stack, ffmpeg, VLC, etc. PPCDN's own ppobs client does NOT support ERTSP publishing, and pplayer does NOT support RTSP playback; publish with a standard RTSP client (ANNOUNCE/RECORD) and play with a standard RTSP client (DESCRIBE/SETUP/PLAY).

7.1 Getting the RTSP publish address

The business backend calls POST /v1/publish/requests per device identity, with protocol set to "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"}'

The response's ppcdnPublishEndpoint is a complete, signed RTSP publish URL (not the bare host:port template that SRT/RTMP return):

{
  "originNodeId": 12,
  "ppcdnPublishEndpoint": "rtsp://<txTime>:<txSecret>@<origin-host>:8554/app_xxx/B01-frontView",
  "expiresAt": "2026-10-16T12:00:00Z"
}
  • streamName must be the two-part {tableId}-{view} form (same as WHIP/SRT publishing).
  • The credentials are embedded in the URL's txTime:txSecret; the device needs no signing.
  • The credential is valid for 1 hour by default (see expiresAt); call the endpoint again after it expires.
  • Put the whole URL into the device's RTSP publish config (ANNOUNCE/RECORD) to start.

7.2 Choosing the play address: WebRTC (WHEP) or RTSP (ERTSP)

The viewer calls POST /v1/play/requests with capabilities exactly one of:

Path capabilities Returned address
WebRTC low-latency playback (browser / WebRTC-capable terminal) ["whep"] edgeStreamURL = WHEP endpoint
Standard RTSP playback (embedded device) ["ertsp"] edgeStreamURL = signed rtsp://...

The play request needs a viewer token (Authorization: Bearer <appId>:<txTime>:<txSecret>, where txSecret is an HMAC of {appId}/{streamName} with the app's appSecret; see the publish/play API docs). RTSP example:

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"]}'

Response:

{
  "mode": "edge-ertsp",
  "edgeStreamURL": "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264",
  "expiresAt": "2026-10-16T12:00:00Z"
}

ERTSP playback takes part in no P2P and no dynamic layer switching; it always returns a single H264 rendition. Scenarios needing P2P direct connect / multi-layer ABR should choose whep.

7.3 How to play a WHEP stream (WebRTC)

The edgeStreamURL returned for capabilities:["whep"] is a WHEP endpoint:

  1. the player POSTs an SDP offer to that address (Content-Type: application/sdp); the server returns an SDP answer;
  2. once the standard WebRTC connection is up, playback begins.
  3. A browser can play it with a standard WHEP client (e.g. PPCDN's pplayer).
  4. Command-line / embedded environments usually have no WebRTC stack; in that case use ertsp from 7.2 instead (see 7.4).

7.4 How to play an RTSP stream

The edgeStreamURL returned for capabilities:["ertsp"] is a standard RTSP pull URL with the username/password already embedded; hand it straight to the device's RTSP client:

  • ffmpeg / ffplay:
ffplay "rtsp://<txTime>:<txSecret>@<edge-host>:8554/app_xxx/B01-frontView/h264"
# pull and save to a file (-rtsp_transport tcp is more robust on weak networks):
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"
  • A device's own RTSP stack: put the whole URL (including user:pass@) into the playback config — no extra auth code needed.

The URL's token has an expiry (expiresAt); call the 7.2 endpoint again for a fresh address before it expires.

8. Self-check

  • [ ] Is the device you're integrating RTSP-only, unable to implement a WebRTC/ICE/DTLS stack?
  • [ ] Is this stream naturally a single fixed rendition (no Simulcast layers needed)?
  • [ ] Can your scenario accept plaintext RTSP, or do you need TLS/DTLS-SRTP-grade encryption (in that case use WHIP/WHEP)?
  • [ ] Do you need to share the same stream with browser viewers (ERTSP and WHEP players can pull the same Origin stream simultaneously)?

If the first two hold and the third accepts plaintext, ERTSP is probably less work than building your own RTSP→WHIP gateway.

9. Disclaimer

  • This note records ERTSP's current implementation and production-configuration state (publish/play URL formats, signing scheme, codec limits); as of writing it is the only documentation of this capability — previously only code comments and internal version history.
  • URL formats, ports and signing details may change as the product evolves; the actual API return values prevail — don't hard-code the string formats shown here in business code.
  • This note makes no compatibility commitment for specific device models; different vendors' RTSP implementations can differ in auth-header handling (see the engineering lesson in §2), so run a real integration test with the target device or its SDK first.