CDN

Diese Doku beschreibt unser Live-Streaming CDN, wie es seit dem 34C3 existiert.

Architektur

Die CDN-Kaskade hat 5 Stufen: Master-Encoder, Transcoder, Fanout, Transport-/Master-Relays und schließlich Edge-Relays.

1. Master-Encoder

Das Master-Encoding entsteht auf dem encoder-cube im Saal aus dem Ausgabesignal des Voctomix. Das Master-Encoding enthält den Mix als 1080p25 in h264 sowie die Slides als 1080p5 in h264 mit bis zu drei Audiospuren in AAC (Native, Translated, Translated-2). Wahlweise können die Übersetzerspuren sowie die Slide-Spur weggelassen werden. Alle Spuren werden in einem Matroska-Container verpackt.

Das Master-Encoding wird von einem Script erzeugt, welches vom ansible aus folgendem Template erzeugt wird: https://github.com/voc/cm/blob/master/ansible/roles/encoder/templates/voctomix-scripts/streaming-sink-mkvonly.sh.j2

Das Master-Encoding wird auf den lokalen (= auf dem encoder-cube laufenden) Icedist (= Icecast zur internen Distribution) auf Port 7999 gepusht (http://encoderX.lan.c3voc.de:7999/sX). Der Icedist auf dem Master-Relay (z.B. live.ber.c3voc.de) pullt diesen und bietet ihn seinerseits auf http://live.ber.c3voc.de:7999/sX an.

Debugging

http://195.54.164.164:7999 (oder http://live.ber.c3voc.de:7999 im Inkognito-Modus damit einen der Browser nicht zu HTTPS zwingen will)

voc@live.ber:/etc/icecast2$ systemctl status icedist 2019-08-20 21:52:20
● icedist.service - distribution Icecast
Loaded: loaded (/etc/systemd/system/icedist.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-07-30 19:50:07 CEST; 3 weeks 0 days ago
Main PID: 794 (icecast2)
Tasks: 25 (limit: 4915)
CGroup: /system.slice/icedist.service
└─794 /usr/bin/icecast2 -c /etc/icecast2/icedist.xml
sudo tail -f /var/log/icedist/error.log

1.5 Exkurs Stream-API

Die “Stream-API” ist aktuell ein statisches JSON-File mit Pfaden und Transcoder-Zuordnungen für aktuelle Streams.Aktuelles Beispiel siehe https://live.ber.c3voc.de/stream_info.json (Zugang im Keepass unter stream-api).

Das JSON wird periodisch auf dem Master Relay von einem Skript durch die Abfrage von Icedist/Icecast-Instanzen (lokal, ingest, etc.) erstellt. Damit enthält es alle Streams die aktuell oder kürzlich (bis zum timeout) auf dem icedist/icecast ankamen. Weiterhin wird anhand einer Config automatisiert ein (nicht-voller) Transcoder zum Stream zugeordnet. Jeder Transcoder hat in der Config eine “Kapazität” d.h. eine Maximalzahl von möglichen Streams anhand derer die Verteilung gewählt wird.

2. Transcoder

Das Transcoding läuft auf verschiedenen Transcodern. Aktuelle Zuordnung siehe event-Inventory im ansible https://github.com/voc/cm/blob/master/ansible/event#L49 “alb”.

Jeder Transcoder pollt regelmäßig die Stream-Api und startet/stoppt entsprechende Systemd-Units der Form “transcode@sX.target”.Abhängig von der Hardware starten diese entweder einzelne “transcodeh264@sX.service”, “transcodevpx@sX.service”, etc. Units oder einen einzelnen “transcode_vaapi@sX.service”.

Die Pull/Push-Konfiguration jedes Streams wird aus der Stream-API entnommen und in ein File entsprechend “/opt/transcoder/config/sloop”. Die Transcoding-Services verwenden dann diese Datei als EnvironmentFile.

Die Quelle eines transkodierten Streams ist immer eine Icecast-URL der Form http://host:port/sX und das Ziel ist immer eine Icecast-URL der Form http://host2:port2/sX_format.(Beispiel: http://live.ber.c3voc.de:7999/s1 → http://live.ber.c3voc.de:7999/s1_h264)

Die transkodierten Formate sind dabei: h264, vpx (VP9), audio (MP3, Opus) und thumbnail (MJPEG mit 0.1Hz).Dementsprechend z.B.:

http://live.lan.c3voc.de:7999/sX_h264

http://live.lan.c3voc.de:7999/sX_vpx

http://live.lan.c3voc.de:7999/sX_audio

http://live.lan.c3voc.de:7999/sX_thumbnail

Die Scripte dazu werden vom ansible aus folgenden Templates erzeugt: https://github.com/voc/cm/tree/master/ansible/roles/transcoder/templates/transcoder

Da jeder Format-Stream aus einem einzelnen ffmpeg-Prozess stammt und in einem Container landet sind die darin enthaltenen Videoströme Zeitsynchron zueinander.

Verwaltung

Die Verteilung der Transcodings wird wie oben erwähnt über die Stream-API realisiert. Dadurch werden die Streams immer gleichmäßig verteilt und es gibt keine doppelten Zuweisungen.

Die Maximalzahl der Streams pro Transcoder und eventuelle Stream-Bindungen an bestimmte Transcoder können über Variablen im ansible gesteuert werden.

Um einen Überblick über die derzeit aktivierten Transcodings zu erhalten kann folgender Befehl verwendet werden:

voc@tweety.int:~$ systemctl list-units 'trans*' 2018-01-23 0:22:42
UNIT LOAD ACTIVE SUB DESCRIPTION
transcode_s1_audio.service loaded active running Transcoder audio Stream s1
transcode_s1_h264.service loaded active running Transcoder h264 Stream s1
transcode_s1_vpx.service loaded active running Transcoder vpx Stream s1
transcode_s2_audio.service loaded active running Transcoder audio Stream s2
…
transcode_s1.target loaded active active All Transcoders of Stream s1
transcode_s2.target loaded active active All Transcoders of Stream s2
…

Der Zustand des API-Clients ist gelegentlich sinnvoll abzufragen

sudo journalctl -afu update_transcoding

3. Fanout

Die Format-Streams je Raum werden von der nächsten Stufe auf dem Master-Relay (live.ber.c3voc.de) in die finalen Streams in allen für Endnutzer angebotenen Kombinationen auseinander gemuxt (=“fanout”).

Dabei entstehen alle Kombinationen aus sX[hd|sd|slides][native|translated|translated-2] in webm, hls und dash sowie sX_[native|translated|translated-2].[mp3|opus] und die Thumbnails.

Die WebM- und die Audio-Streams werden gegen den Icecast auf http://live.ber.c3voc.de:8000/ gepusht, die HLS- und DASH-Streams werden vom nginx unter http://live.ber.c3voc.de/hls/ bzw. http://live.ber.c3voc.de/dash/ angeboten.Segmente im File-System:

/srv/nginx/dash/sX/[manifest.mpd|init\d.webm|segment\d\d+.webm] * /srv/nginx/hls/[sXnative[hd|sd|slides].m3u8] * /srv/nginx/hls/sX/[chunks\d.m3u8|\d+-\d+_\d.ts]

/srv/nginx/thumbnail/sX/[poster.jpeg|thumb.jpeg]

Die Scripte dazu werden vom ansible aus folgenden Templates erzeugt werden: https://github.com/voc/cm/tree/master/ansible/roles/relay/files/fanout.

Um einen Überblick über die laufenden Fanout Skripte zu erhalten kann folgender Befehl verwendet werden:

voc@live.ber:~$ systemctl list-units 'fanout*'

Die Pull-Quelle und das Push-Ziel sowie der Pfad unter dem die HLS/DASH-Schnipsel und Playlisten abgelegt werden ist über Group-Vars konfigurierbar: https://github.com/voc/cm/blob/master/ansible/group_vars/relays#L5

Zu den Aufgaben der fanout-Scripte gehört auch das übermitteln des h264-Videostroms zu Youtube. Die Stream-Keys dazu kommen aus dem KeePass, die Scripte aus dem oben verlinkten Git-Repo.

Youtube ist derzeit deaktiviert und wird üblicherweise nur für den Congress aktiviert.

Das Transcoding und Fanout reagiert dynamisch auf die Konfiguration des Streams der vom encoder-cube gesendet wird. Fehlt die Slides-Spur oder die Translation-Spuren wird diese nicht in den Master-Playlists und Dash-Manifestd für Adaptives streaming angeboten. Dadurch kann von Event zu Event entschieden werden, ob der Einsatz der Slide-Spur bzw. von Translations sinn ergibt. Siehe dazu Audiomapping in Voctomix zu Details wie Translations de/aktiviert werden können.

4. Transport- und Master-Relays

Im Non-Congress Setup ist live.ber.c3voc.de das einzige (Non-Public) Transport-Relay. Die (Public) Edge-Relays ziehen ihre Daten von dort.

5. Edge-Relays

Die ganzjährigen Edge-Relay lauten:

live.bn.c3voc.de

live.alb.c3voc.de

live2.alb.c3voc.de

live.dus.c3voc.de

live.self.c3voc.de

live.fem.c3voc.de

Diese pullen alle Icecast-Streams (Port :8000) – nicht die Icedist-Streams – von live.ber.c3voc.de.Für die schlussendliche Auslieferung kommt ein nginx zum Einsatz, der abhängig von der URL Daten von einem der unterschiedlichen Backend proxied:

Für Anfragen zu einem WebM, MP3 oder Opus-Stream (z.B: http://live.x.c3voc.de/sX_native_hd.webm) agiert der nginx als Proxy zu seinem eigenen Icecast. Er übernimmt in dieser Rolle das Aggregieren auf die Ports 80/443 sowie das SSL-Handling (für 443).

Für Anfragen nach HLS oder DASH-Schnipseln, -Playlisten und -Manifests oder Thumbnails (z.B. http://live.x.c3voc.de/hls/sX_native_hd.m3u8) agiert der nginx als Proxy zum Master-Relay live.ber.c3voc.de, von welcher er die angefragten Datein abholt und für einen genau festgelegten Zeitraum zwischenspeichert. Dieser Zeitraum muss dabei mit der Segmentlänge der Playlists abgestimmt sein, um eine fehlerfreie Wiedergabe zu ermöglichen.

Stream-URLs

Die endgültigen Stream-URLs für einen Beispielstream sX sind dann wie folgt:

MPEG-DASH (Multi-Qualität + Multi-Lang)

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

HLS (Multi-Qualität + Multi-Lang)

http://cdn.c3voc.de/sX_native_hd.m3u8

http://cdn.c3voc.de/sX_native_sd.m3u8 (nur SD, aber Multi-Lang)

VPx-HD:

http://cdn.c3voc.de/sX_native_hd.webm

http://cdn.c3voc.de/sX_translated_hd.webm

http://cdn.c3voc.de/sX_translated-2_hd.webm

VPx-SD:

http://cdn.c3voc.de/sX_native_sd.webm

http://cdn.c3voc.de/sX_translated_sd.webm

http://cdn.c3voc.de/sX_translated-2_sd.webm

VPx-Slides:

http://cdn.c3voc.de/sX_native_slides.webm

http://cdn.c3voc.de/sX_translated_slides.webm

http://cdn.c3voc.de/sX_translated-2_slides.webm

h264-HD:

http://cdn.c3voc.de/hls/sX_native_hd.m3u8

http://cdn.c3voc.de/hls/sX_translated_hd.m3u8

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

h264-SD:

http://cdn.c3voc.de/hls/sX_native_sd.m3u8

http://cdn.c3voc.de/hls/sX_translated_sd.m3u8

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

h264-Slides:

http://cdn.c3voc.de/hls/sX_native_slides.m3u8

http://cdn.c3voc.de/hls/sX_translated_slides.m3u8

http://cdn.c3voc.de/hls/sX_translated-2_slides.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

Loadbalancer

Neben den Transport- und Edge-Relays gibt es noch zwei Loadbalancer:

lb.dus.c3voc.de

lb.alb.c3voc.de

Diese sind sowohl für die Domains streaming.media.ccc.de als auch für cdn.c3voc.de zuständig. Im DNS sind für beide Domains beide Server angegeben, so dass Clients per statistischem Round-Robin auf einen der beiden Server verteilt werden.

streaming.media.ccc.de

Unter dieser Domain liefern beide LBs unabhängig von einander die Streaming-Webseite aus. Die LBs sind dabei komplett unabhängig voneinander und haben auch je eine eigene Konfiguration. Es ist aufgabe des Website-Deployments die Konfiguration synchron zu halten. Durch dieses Setup kann bei Bedarf der jeweilige LB einfach aus der DNS-Rotation herausgenommen werden.

cdn.c3voc.de

Die Domain cdn.c3voc.de wird auf beiden LBs von einem HAProxy bedient. Dieser sortiert eventuell zwischen DTAG und Lokalen Klienten und wählt auf dieser Basis einen des obenstehenden Relays aus. Im unterjährigen Betrieb gibt es keine Unterscheidung: Alle Anfragen werden unter den genannten Relays verteilt.

Der HAProxy verteilt dabei ausschließlich per Redirect, er proxied (entgegen seines Namens) nicht.

RTMP Ingest

Für Spezialanwendungen (z.B. Cam-Only Streaming im Fritz-Studio) existieren die RTMP-Endpunkte q1 und q2 auf ingest.c3voc.de.Die Push-Targets lauten rtmp://ingest.c3voc.de/stream/q1 bzw. q2. Eine Systemd-Unit setzt diese dann auf Icedist-Ströme gleichen Namens um, von wo Transcoding und Fanout wie oben beschrieben seinen Weg nehmen.

Achtung: Aufgrund der langen rtmp-Timeouts in ffmpeg kann es bis zu 40 Sekunden dauern, bis die Streams auftauchen und weitere 30 Sekunden, bis alle Formate zur Verfügung stehen. Keine Ungeduld.