Udostępnianie HLS (HTTP Live Streaming) z nginx stanowi podstawę większości samodzielnie hostowanych konfiguracji strumieniowania — VOD, catch-up i restreaming na żywo opierają się na nim. Ten przewodnik konfiguruje nginx do efektywnego udostępniania segmentów HLS, z nagłówkami buforowania i CORS, których faktycznie potrzebują odtwarzacze.
Zakładamy, że już generujesz listy odtwarzania .m3u8 i segmenty .ts (lub .m4s) — na przykład z potoku FFmpeg NVENC.
Wymagania wstępne
- Ubuntu 22.04 z zainstalowanym nginx (
apt install -y nginx) - Segmenty HLS zapisywane do katalogu (np.
/var/www/hls) - Domena wskazująca na serwer
Krok 1 — Podstawowy blok lokalizacji HLS
Edytuj konfigurację swojej witryny (/etc/nginx/sites-available/streaming):
server {
listen 80;
server_name stream.yourdomain.com;
location /hls/ {
# Serve segments from disk
root /var/www;
# Correct MIME types for HLS
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
video/iso.segment m4s;
}
# CORS — required for browser players (hls.js, video.js)
add_header Access-Control-Allow-Origin * always;
add_header Cache-Control no-cache always;
}
}Nagłówek Cache-Control: no-cache dla listy odtwarzania jest ważny — odtwarzacze muszą ponownie pobrać .m3u8, aby zobaczyć nowe segmenty. Następnie dopracujemy buforowanie.
Krok 2 — Rozdzielone buforowanie: listy odtwarzania vs segmenty
Listy odtwarzania zmieniają się z każdym segmentem; segmenty nigdy się nie zmieniają po zapisaniu. Buforuj je inaczej:
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;
# Segmenty są niezmienne — buforuj agresywnie
add_header Cache-Control "public, max-age=86400" always;
types {
video/mp2t ts;
video/iso.segment m4s;
}
}Pozwala to CDN-om i przeglądarkom buforować duże pliki .ts, jednocześnie zawsze ponownie sprawdzając małą listę odtwarzania.
Krok 3 — Włącz sendfile i zoptymalizuj przepustowość
Strumieniowanie jest ograniczone przepustowością. W bloku http {} pliku /etc/nginx/nginx.conf:
sendfile on;
tcp_nopush on;
tcp_nodelay on;
sendfile_max_chunk 1m;
# Zwiększ liczbę połączeń workerów dla wysokiej współbieżności
worker_processes auto;
events {
worker_connections 8192;
use epoll;
multi_accept on;
}
# Większe bufory wyjściowe dla dużych segmentów
output_buffers 4 256k;sendfile on pozwala jądru kopiować pliki segmentów bezpośrednio z dysku do gniazda bez przechodzenia przez przestrzeń użytkownika — to duża zaleta dla obsługi segmentów o wysokiej współbieżności.
Krok 4 — Dodaj HTTPS (odtwarzacze coraz częściej tego wymagają)
Przeglądarki blokują mieszaną zawartość, więc strona na HTTPS nie może pobierać HLS przez HTTP. Uzyskaj certyfikat za pomocą Certbot:
apt install -y certbot python3-certbot-nginx
certbot --nginx -d stream.yourdomain.comCertbot przepisuje twój blok serwera, aby nasłuchiwał na porcie 443 z certyfikatem. Zweryfikuj automatyczne odnawianie:
certbot renew --dry-runKrok 5 — Włącz HTTP/2 (i HTTP/3, jeśli możesz)
HTTP/2 multipleksuje żądania segmentów przez jedno połączenie — ma to znaczenie dla HLS, gdzie odtwarzacz pobiera wiele małych plików:
listen 443 ssl;
http2 on;Dla HTTP/3 (QUIC) potrzebujesz nginx zbudowanego z modułem http_v3 lub kompilacji takiej jak nginx-quic. HTTP/3 najbardziej pomaga odtwarzaczom w niestabilnych sieciach mobilnych.
Krok 6 — Obsługa problemu „thundering herd” na krawędziach transmisji na żywo
Gdy segment popularnej transmisji na żywo zostanie udostępniony, tysiące odtwarzaczy żąda go niemal jednocześnie. Bez odpowiedniej konfiguracji wszystkie jednocześnie obciążają dysk. Włącz buforowanie otwartych plików:
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;Buforuje to deskryptory plików i metadane, dzięki czemu drugie i kolejne tysiące żądań gorącego segmentu są obsługiwane z pamięci podręcznej, a nie z nowego stat()+open().
Krok 7 — Testowanie
Przeładuj i zweryfikuj:
nginx -t && systemctl reload nginx
curl -I https://stream.yourdomain.com/hls/stream.m3u8Oczekujesz 200 OK, Content-Type: application/vnd.apple.mpegurl, Access-Control-Allow-Origin: * i Cache-Control: no-cache dla listy odtwarzania. Załaduj ją w przeglądarce za pomocą hls.js lub w VLC, aby potwierdzić odtwarzanie.
Rozwiązywanie problemów
Błędy CORS w konsoli przeglądarki: nagłówek Access-Control-Allow-Origin nie dociera do klienta. Sprawdź, czy jest ustawiony zarówno w lokalizacjach .m3u8, jak i .ts, oraz czy żaden pośredniczący proxy go nie usuwa.
Zacinanie się / buforowanie odtwarzacza: zazwyczaj dostarczanie segmentów nie nadąża. Sprawdź przepustowość za pomocą iftop; jeśli port jest nasycony, potrzebujesz większego łącza uplink. Zweryfikuj również, czy hls_time (czas trwania segmentu) nie jest zbyt krótki — 6s to bezpieczna wartość domyślna.
Błąd 404 dla segmentów, ale lista odtwarzania się ładuje: ścieżka root jest nieprawidłowa, lub segmenty są usuwane (krótki hls_list_size) zanim odtwarzacze je zażądają. Zwiększ hls_list_size w poleceniu FFmpeg.
Co dalej
Dla dostarczania geo-rozproszonego umieść flotę brzegową CDN przed tym źródłem. W kwestii transkodowania, zobacz przewodnik FFmpeg NVENC. A przepustowość swojego źródła dobierz za pomocą naszego przewodnika po prędkościach portów.