Live-Codierung mit VP9 mit FFmpeg

Codierungsparameter

VP9 bietet eine Reihe von Parametern zur Optimierung der Live-Codierung. Einige allgemeine Grundsätze werden unter Bitratenmodi beschrieben.

FFmpeg-Beispiel für die VP9-Codierung

In der folgenden Tabelle werden die Parameter eines Beispielaufrufs von ffmpeg für die VP9-Codierung beschrieben.

Parameter Beschreibung
-quality realtime realtime ist für Livestreams und Geschwindigkeiten über 5 erforderlich.
-speed 6 Die Geschwindigkeit 5 bis 8 sollte für die Live- bzw. Echtzeitcodierung verwendet werden. Niedrigere Zahlen (5 oder 6) stehen für eine höhere Qualität, erfordern aber mehr CPU-Leistung. Höhere Zahlen (7 oder 8) führen zu einer geringeren Qualität, sind aber für Anwendungsfälle mit niedriger Latenz und für Geräte mit geringerer CPU-Leistung wie Mobilgeräte besser geeignet.
-tile-columns 4 Beim Tiling wird das Video in rechteckige Bereiche aufgeteilt, was die Verwendung von Multithreading für die Codierung und Decodierung ermöglicht. Die Anzahl der Kacheln ist immer eine Zweierpotenz. 0 = 1 Kachel, 1 = 2, 2 = 4, 3 = 8, 4 = 16, 5 = 32.
-frame-parallel 1 Funktionen für parallele Decodierbarkeit aktivieren.
-threads 8 Maximale Anzahl der zu verwendenden Threads.
-static-thresh 0 Grenzwert für die Bewegungserkennung.
-max-intra-rate 300 Maximale Bitrate für I-Frames (in Prozent)
-deadline realtime Alternative (alte) Version von -quality realtime
-lag-in-frames 0 Maximale Anzahl der Frames, die verzögert werden sollen
-qmin 4 -qmax 48 Mindest- und Höchstwerte für den Quantisierer. Die Werte hier sind nur ein Vorschlag. Wenn Sie sie anpassen, wird die Videoqualität erhöht oder verringert, was sich auf die Komprimierungseffizienz auswirkt.
-row-mt 1 Aktivieren Sie das Row-Multithreading. Ermöglicht die Verwendung von bis zu zwei Threads als Kachelspalten. 0 = aus, 1 = an.
-error-resilient 1 Aktivieren Sie Funktionen zur Fehlerbehebung.

Codierungsparameter auswählen

Die folgenden Informationen beziehen sich auf das Encoding mit konstanter Bitrate (CBR) für das adaptive Bitrate-Streaming (ABR) von Livestreams, bei dem jede Zielrate explizit im Manifest des Packagers festgelegt wird. Dadurch wird das „Wechseln“ zwischen Raten für Kunden vereinfacht. Die Codierung mit variabler Bitrate (VBR) und der CQ-Modus sind ebenfalls Optionen, wenn die Bitrate flexibler sein kann oder die Codierung in Chunks erfolgt. Der Q-Modus ist für die Echtzeitcodierung, die für Live-Videos erforderlich ist, nicht geeignet. Weitere Informationen finden Sie unter Bitratenmodi.

Weitere Informationen zur Bearbeitung von VP9 finden Sie auch im zugehörigen Artikel zu VOD-Einstellungen. Hier wird jedoch der Fokus auf CBR gelegt.

Tipps und Tricks

Beim Livestreaming muss die Mindestcodierungsgeschwindigkeit in Echtzeit 1x betragen (FFmpeg gibt die Codierungsgeschwindigkeit im Laufe des Prozesses an). Wenn die Codierungsgeschwindigkeit unter 1x sinkt, kann der Codierungsprozess nicht mit der Eingabe von Live-Video mithalten. Nutzer sehen dann Pufferungen und Unterbrechungen in der Übertragung, die den Stream während der Liveübertragung unbrauchbar machen (obwohl das Archiv im Allgemeinen nutzbar ist).

Beispiele für die Verwendung von Codierungsparametern

Im Folgenden sehen Sie die CPU-Auslastung bei 25 fps für verschiedene Frame-Größen auf einem Quad-Core-i5-Desktop mit 3,6 GHz unter Linux:

Zielauflösung FFmpeg-VP9-Parameter CPU / Geschwindigkeit (Beispiel)
3.840 × 2.160 (2.160p) -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k ~88% 0,39-fach
2560 × 1440 (1440p) -r 30 -g 90 -s 2560x1440 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 6000k ~86% 0,68-Fach
1920 × 1080 (1080p) -r 30 -g 90 -s 1920x1080 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 4500k ~82% 1.04x
1280 × 720 (720p) -r 30 -g 90 -s 1280x720 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 3000k ~78% 1,77-fach
854 × 480 (480p) -r 30 -g 90 -s 854x480 -quality realtime -speed 6 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 1800k ~64% 3,51‑fach
640 × 360 (360p) -r 30 -g 90 -s 640x360 -quality realtime -speed 7 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 730k ~62% 5,27-fach
426 × 240 (240p) -r 30 -g 90 -s 426x240 -quality realtime -speed 8 -threads 2 -row-mt 1 -tile-columns 0 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 365k ~66% 8.27x

Ein Beispiel für FFmpeg könnte so aussehen:

ffmpeg -stream_loop 100 -i /home/id3as/Videos/120s_tears_of_steel_1080p.webm \
  -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 \
  -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k -c:v libvpx-vp9 \
  -b:a 128k -c:a libopus -f webm pipe1

Tipps und Tricks

  • Hier wird die Ausgabe in eine FIFO-Pipe („pipe1“) geschrieben, die vor der Ausführung des FFmpeg-Befehls erstellt werden muss. Geben Sie dazu den Befehl mkfifo pipe1 in Ihrem Arbeitsverzeichnis ein. Wenn Sie Shaka Packager verwenden, wird dieser Pipe als Eingabequelle für den angegebenen Stream gelauscht. Für andere Verpackungsmodelle ist möglicherweise eine andere Methode erforderlich.

  • Damit -row-mt-Befehle erkannt werden, verwenden Sie die aktuelle stabile Version von FFmpeg (derzeit 3.3.3) von https://www.ffmpeg.org/download.html.

Beispiel für einen adaptiven Bitrate-Satz

Je nach Leistung des Computers, auf dem die FFmpeg-Codierung ausgeführt wird, ist es möglicherweise nicht möglich, alle folgenden Codierungen gleichzeitig bereitzustellen. Daher sollte aus der Liste eine Teilmenge ausgewählt werden, die den verfügbaren Ressourcen und Zielgruppen entspricht.

Vollständiges ABR-Set für FFmpeg

Im Idealfall kombinieren wir die im vorherigen Abschnitt beschriebenen Codierungsbeispiele, um einen einzelnen Befehl zu erstellen, mit dem alle gleichzeitig erzeugt werden:

ffmpeg -stream_loop 100 -i lakes1080p.mp4 \
  -y -r 25 -g 75 -s 3840x2160 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 7800k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe1 \
  -y -r 25 -g 75 -s 2560x1440 -quality realtime -speed 5 -threads 8 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 6000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe2 \
  -y -r 25 -g 75 -s 1920x1080 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe3 \
  -y -r 25 -g 75 -s 1280x720 -quality realtime -speed 5 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe4 \
  -y -r 25 -g 75 -s 854x480 -quality realtime -speed 6 -threads 4 \
  -tile-columns 2 -frame-parallel 1 \
  -b:v 2000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe5 \
  -y -r 25 -g 75 -s 640x360 -quality realtime -speed 7 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe6 \
  -y -r 25 -g 75 -s 426x240 -quality realtime -speed 8 -threads 2 \
  -tile-columns 1 -frame-parallel 0 \
  -b:v 365k -c:v libvpx-vp9 -b:a 64k -c:a libopus -f webm pipe7

Für den oben genannten vollständigen Satz ist jedoch eine sehr leistungsstarke CPU oder möglicherweise die Unterstützung durch Hardware-GPU-Offload erforderlich, wie sie von einigen Chipsätzen zunehmend bereitgestellt wird. Intel Kabylake (und höher) verfügt über eine vollständige Hardware-Codierungspipeline. Die Kabylake-GPU kann 8-Bit-VP9-Codierung, aber keine 10-Bit-Codierung durchführen.

Praxisbeispiel für Computer mit Shaka Packager

Ein praktischeres Beispiel für gängige Desktopcomputer könnte Shaka Packager verwenden. Eine einfache Möglichkeit, Shaka einzurichten, ist die Installation in einem Docker-Container mit dem DockerHub-Image von Google. Eine Anleitung dazu finden Sie hier:

https://github.com/google/shaka-packager#using-docker-for-testing--development

Für dieses Beispiel haben wir einen Computer mit der folgenden Konfiguration verwendet:

System Host: obs Kernel: 4.4.0-91-lowlatency x86_64 (64 Bit)
Computer Xfce 4.12.3 – Distribution: Betriebssystem: https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/
CPU Quad-Core Intel Core i5-6500 (-MCP-)
Cache: 6144 KB
Taktfrequenzen: max.: 3600 MHz 1: 800 MHz 2: 800 MHz 3: 800 MHz 4: 800 MHz
Grafikkarte Integrierte Intel Skylake-Grafik
Arbeitsspeicher 8 GB RAM

In der Praxis könnte diese Maschine optimal den folgenden nutzbaren Bereich von ABR-Codierungen mit einer von FFmpeg durchgehend gemeldeten Codierungsgeschwindigkeit von 1x erzeugen:

ffmpeg -stream_loop 100 -i 120s_tears_of_steel_1080p.webm \
  -y -r 30 -g 90 -s 1920x1080 -quality realtime -speed 7 -threads 8 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 4500k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe1 \
  -y -r 30 -g 90 -s 1280x720 -quality realtime -speed 8 -threads 6 \
  -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 3000k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe2 \
  -y -r 30 -g 90 -s 640x360 -quality realtime -speed 8 -threads 2 \
  -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 \
  -b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe3

Beachten Sie, dass die -speed-Einstellungen recht hoch sind. Diese Einstellungen wurden experimentell ermittelt und variieren von Maschine zu Maschine.

Shaka Packager-Overhead

Das Verpacken ist keine besonders CPU-intensive Aktivität. Shaka Packager kann so eingestellt werden, dass alle Ausgaben überwacht werden, auch wenn nur eine Teilmenge von FFmpeg bereitgestellt wird. Dies sind die Packager-Einstellungen, die auf der oben beschriebenen Maschine getestet wurden:

packager \
  in=pipe1,stream=audio,init_segment=livehd-audio-1080.webm,segment_template=livehd-audio-1080-\$Number\$.webm \
  in=pipe1,stream=video,init_segment=livehd-video-1080.webm,template=livehd-video-1080-\$Number\$.webm \
  in=pipe2,stream=audio,init_segment=livehd-audio-720.webm,segment_template=livehd-audio-720-\$Number\$.webm \
  in=pipe2,stream=video,init_segment=livehd-video-720.webm,template=livehd-video-720-\$Number\$.webm \
  in=pipe3,stream=audio,init_segment=livehd-audio-360.webm,segment_template=livehd-audio-360-\$Number\$.webm \
  in=pipe3,stream=video,init_segment=livehd-video-360.webm,template=livehd-video-360-\$Number\$.webm \
  --mpd_output livehd.mpd --dump_stream_info --min_buffer_time=10 --time_shift_buffer_depth=300 \
  --segment_duration=3 --io_block_size 65536