CDN

Voctoweb

Repo Links

Stream-api, Upload-Proxy, Upload-Server: https://github.com/voc/stream-api

rtmp-auth daemon: https://github.com/voc/rtmp-auth

Transcoding-Script: https://github.com/voc/transcoding

Architecture

The CDN-Cascade has 5 stages: Master-Encoder, Ingest, Transcoder, Master-Relays and finally Edge-Relays.

1. Master-Encoder

The master stream encoding is created near the stage on the encoder PC running voctomix or on with other videoencoder for third party streams.The master encoding contains a 1080p25 H264 video signal, the slides as 1080p5 and up to 3 tracks of audio encoded in AAC (Native, Translated, Translated-2).The translated audio tracks and the slide video track are optional.

The master encoding is pushed as MPEG-TS via SRT to the ingest stage.

2. Ingest

The ingest machines run both srtrelay and nginx-rtmp to receive pushed streams from the master encoders. This also serves as the entry point for third party streams.

Additionally the ingest machines run a stream-api daemon which scrapes the local stream information from both srtrelay and nginx-rtmp and publishes it to consul KV.The consul KV path is /stream/<stream slug>

# consul kv get /stream/s96
{"format":"mpegts","source":"srt://ingest.c3voc.de:1337?streamid=play/s96","slug":"s96","publishedAt":0}

3. Transcoder

The stream transcoding transforms the mpegts stream into multiple segmented streams (one per quality) via one big ffmpeg script. Additionally it creates thumbnails and preview images.The transcoding script can be found here https://github.com/voc/transcoding.

A python script runs constantly on each transcoder which fetches streams from consul and tries to claim streams which don't have a transcoder assigned yet.The consul KV path is /stream/<stream slug>/transcoder

# consul kv get /stream/s96/transcoder
myloc-transcoder3
# To reallocate a transcoder for a stuck stream
consul kv delete /stream/s96/transcoder

Every time a transcoder claims a stream it writes an env file and starts a systemd unit to run the transcoding script.The transcode updates are also published to the #voc-wok IRC.

The transcoding outputs are directly pushed with HTTP uploads to the Master relay. To ensure proper retries the uploads are sent over a local http-proxy (https://github.com/voc/stream-api/tree/master/cmd/upload-proxy).

4. Master Relay

Runs the upload server (https://github.com/voc/stream-api/tree/master/cmd/upload-server) which receives the http uploads and stores the files on local disk.The upload server has some additional logic to rewrite the HLS playlists on the fly in order to properly handle stream restarts.

The segmented streams, thumbnails etc. are served by nginx.

5. Edge-Relays

The edge relays run nginx with caching proxy config and upstream set to the master relay.

Stream-URLs

The resulting stream URLs are as follows:

HLS (H.264 multi-quality + multi-language)

http://cdn.c3voc.de/hls/sX/native_hd.m3u8

MPEG-DASH (VPx multi-quality + multi-language)

http://cdn.c3voc.de/dash/sX/manifest.mpd

Moar HLS

http://cdn.c3voc.de/hls/sX/translated_hd.m3u8 (also multi-language, just a different default language)

http://cdn.c3voc.de/hls/sX/translated-2_hd.m3u8

http://cdn.c3voc.de/hls/sX/native_sd.m3u8 (only SD, but still multi-language)

http://cdn.c3voc.de/hls/sX/translated_sd.m3u8

http://cdn.c3voc.de/hls/sX/translated-2_sd.m3u8

Audio-MP3:

http://cdn.c3voc.de/sX_native.mp3

http://cdn.c3voc.de/sX_translated.mp3

http://cdn.c3voc.de/sX_translated-2.mp3

Audio-Opus:

http://cdn.c3voc.de/sX_native.opus

http://cdn.c3voc.de/sX_translated.opus

http://cdn.c3voc.de/sX_translated-2.opus

Loadbalancers

The end-user facing domains streaming.media.ccc.de as well as cdn.c3voc.de are served by the load-balancers using DNS round robin.

streaming.media.ccc.de

The load-balancers serve the Streaming-Webseite under this domain. The sites run completely independent and are just kept in sync by the deployment script. With this procedure one or more load-balancers can easily be taken out of the DNS rotation if necessary.

cdn.c3voc.de

Requests to cdn.c3voc.de are handled by haproxy on the load-balancers with redirects to one of the edge relays. The redirects are performed following a preconfigured weight distribution.

The relay weight distribution is stored in consul KV and can be tweaked in real time. The haproxy configs automatically get updated by consul-template after a change.

# Get the current weight distribution, if not explicitly set the default is 100
consul kv get -recurse /services/haproxy/backends/ 2025-02-06 0:54:27
services/haproxy/backends/live.event.c3voc.de/weight:1
services/haproxy/backends/relive.c3voc.de/weight:1

Because of the behavior of HLS/DASH clients if a client fetches a playlist file and gets a redirect, all further requests go to the same origin. With this trick the clients stay persistently on one relay until they are redirected.

Dynamic SRT/RTMP endpoints with RTMP Auth

SRT and RTMP Endpoints can be created under https://ingest.c3voc.de/backend/ (Password in keepass under ansible/stream-api/htpasswd). After creating the endpoint the stream can be pushed to any ingest machine.

The RTMP-URL for the endpoint stream/qtest23 on ingest1 would be: rtmp://ingest.c3voc.de/stream/qtest23?auth=<token>

The SRT-URL would be : srt://ingest.c3voc.de:1337?streamid=publish/qtest23/<token>

Future improvements

The diagram below shows the envisioned architecture as of 2020. In the meantime many of the improvements have been integrated into the CDN.Some more potential improvements are as follows:

Dynamically adapting the streaming-website to the existence/lack of a stream

Building a live status dashboard which shows the current stream→ingest→transcoder pipelines

To gracefully shutdown a relay it could be instructed via consul KV to redirect all clients back to a load balancer while taking it out of the haproxy redirects. That way all clients would be redistributed to different relays.

Build master relay redundancy using dynamic upload client and relay upstream configuration. (Relay upstreams need to be sticky, because the HLS playlists generated on the master relay are not deterministic)

Use DNS rotation on ingest

Finalize srtrelay meshing to allow pushed streams to be pulled from any ingest machine.

Overview