Die Bereitstellung von HLS (HTTP Live Streaming) über nginx ist das Rückgrat der meisten selbst gehosteten Streaming-Setups — VOD, Catch-up und Live-Restreaming basieren alle darauf. Dieser Leitfaden konfiguriert nginx, um HLS-Segmente effizient bereitzustellen, mit den Caching- und CORS-Headern, die Player tatsächlich benötigen.
Wir gehen davon aus, dass Sie bereits .m3u8-Playlists und .ts- (oder .m4s)-Segmente generieren — zum Beispiel aus der FFmpeg NVENC-Pipeline.
Voraussetzungen
- Ubuntu 22.04 mit installiertem nginx (
apt install -y nginx) - HLS-Segmente, die in ein Verzeichnis geschrieben werden (z.B.
/var/www/hls) - Eine auf den Server zeigende Domain
Schritt 1 — Grundlegender HLS-Location-Block
Bearbeiten Sie Ihre Site-Konfiguration (/etc/nginx/sites-available/streaming):
server {
listen 80;
server_name stream.yourdomain.com;
location /hls/ {
# Segmente von der Festplatte bereitstellen
root /var/www;
# Korrekte MIME-Typen für HLS
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
video/iso.segment m4s;
}
# CORS — erforderlich für Browser-Player (hls.js, video.js)
add_header Access-Control-Allow-Origin * always;
add_header Cache-Control no-cache always;
}
}Der Cache-Control: no-cache-Header auf der Playlist ist wichtig — Player müssen die .m3u8 neu abrufen, um neue Segmente zu sehen. Das Caching werden wir als Nächstes verfeinern.
Schritt 2 — Getrenntes Caching: Playlists vs. Segmente
Playlists ändern sich mit jedem Segment; Segmente ändern sich nach dem Schreiben nie. Cachen Sie sie unterschiedlich:
location ~ \.m3u8$ {
root /var/www;
add_header Access-Control-Allow-Origin * always;
add_header Cache-Control "no-cache, no-store" always;
types { application/vnd.apple.mpegurl m3u8; }
}
location ~ \.(ts|m4s)$ {
root /var/www;
add_header Access-Control-Allow-Origin * always;
# Segmente sind unveränderlich — aggressiv cachen
add_header Cache-Control "public, max-age=86400" always;
types {
video/mp2t ts;
video/iso.segment m4s;
}
}Dies ermöglicht es CDNs und Browsern, die großen .ts-Dateien zu cachen, während die kleine Playlist immer neu überprüft wird.
Schritt 3 — sendfile aktivieren und für Durchsatz optimieren
Streaming ist bandbreitenbegrenzt. Im http {}-Block von /etc/nginx/nginx.conf:
sendfile on;
tcp_nopush on;
tcp_nodelay on;
sendfile_max_chunk 1m;
# Worker-Verbindungen für hohe Parallelität erhöhen
worker_processes auto;
events {
worker_connections 8192;
use epoll;
multi_accept on;
}
# Größere Ausgabepuffer für große Segmente
output_buffers 4 256k;sendfile on ermöglicht es dem Kernel, Segmentdateien direkt von der Festplatte zum Socket zu kopieren, ohne den Umweg über den Userspace zu nehmen — ein großer Vorteil für die Bereitstellung von Segmenten mit hoher Parallelität.
Schritt 4 — HTTPS hinzufügen (Player benötigen es zunehmend)
Browser blockieren gemischte Inhalte, daher kann eine Seite über HTTPS kein HLS über HTTP abrufen. Holen Sie sich ein Zertifikat mit Certbot:
apt install -y certbot python3-certbot-nginx
certbot --nginx -d stream.yourdomain.comCertbot schreibt Ihren Server-Block um, um auf Port 443 mit dem Zertifikat zu lauschen. Überprüfen Sie die automatische Verlängerung:
certbot renew --dry-runSchritt 5 — HTTP/2 aktivieren (und HTTP/3, wenn möglich)
HTTP/2 multiplexiert Segmentanfragen über eine einzige Verbindung — sinnvoll für HLS, wo ein Player viele kleine Dateien abruft:
listen 443 ssl;
http2 on;Für HTTP/3 (QUIC) benötigen Sie nginx, das mit dem http_v3-Modul oder einem Build wie nginx-quic erstellt wurde. HTTP/3 hilft Playern in verlustbehafteten Mobilfunknetzen am meisten.
Schritt 6 — Den „Thundering Herd“-Effekt bei Live-Streams handhaben
Wenn ein Segment eines beliebten Live-Streams verfügbar wird, fordern Tausende von Playern es nahezu gleichzeitig an. Ohne Vorsichtsmaßnahmen würden sie alle gleichzeitig auf die Festplatte zugreifen. Aktivieren Sie das Open-File-Caching:
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;Dies speichert Dateideskriptoren und Metadaten im Cache, sodass die zweite bis tausendste Anfrage für ein heißes Segment aus dem Cache bedient wird und nicht durch ein frisches stat()+open().
Schritt 7 — Testen
Neu laden und überprüfen:
nginx -t && systemctl reload nginx
curl -I https://stream.yourdomain.com/hls/stream.m3u8Sie möchten 200 OK, Content-Type: application/vnd.apple.mpegurl, Access-Control-Allow-Origin: * und Cache-Control: no-cache auf der Playlist sehen. Laden Sie sie in einem Browser mit hls.js oder in VLC, um die Wiedergabe zu bestätigen.
Fehlerbehebung
CORS-Fehler in der Browserkonsole: Der Access-Control-Allow-Origin-Header erreicht den Client nicht. Überprüfen Sie, ob er sowohl für die .m3u8- als auch für die .ts-Locations gesetzt ist und dass kein Upstream-Proxy ihn entfernt.
Player stockt / puffert neu: Normalerweise kann die Segmentlieferung nicht mithalten. Überprüfen Sie die Bandbreite mit iftop; wenn der Port ausgelastet ist, benötigen Sie einen größeren Uplink. Vergewissern Sie sich auch, dass hls_time (Segmentdauer) nicht zu kurz ist — 6s ist ein sicherer Standardwert.
404 bei Segmenten, aber Playlist lädt: Der root-Pfad ist falsch, oder Segmente werden gelöscht (kurze hls_list_size), bevor Player sie anfordern. Erhöhen Sie hls_list_size in Ihrem FFmpeg-Befehl.
Nächste Schritte
Für die geografisch verteilte Bereitstellung platzieren Sie eine CDN-Edge-Flotte vor diesem Origin. Für die Transkodierungsseite siehe den FFmpeg NVENC-Leitfaden. Und dimensionieren Sie Ihre Origin-Bandbreite mit unserem Port-Geschwindigkeitsleitfaden.