Quando un video online parte sfocato e dopo pochi secondi diventa nitido, oppure perde qualità per un momento mentre si è in treno, si sta osservando lo streaming adattivo al lavoro. È la tecnica usata da quasi tutte le piattaforme video moderne, e si basa su un'idea semplice: invece di inviare un unico file, il server offre lo stesso contenuto in più qualità, tagliato in piccoli pezzi, e il lettore sceglie di volta in volta il pezzo più adatto alla connessione disponibile.
Dal download progressivo allo streaming adattivo
Il metodo più semplice per mettere un video online è caricare un file MP4 e lasciare che il browser lo scarichi mentre lo riproduce. Si chiama download progressivo e funziona bene per video brevi. Ha però due limiti:
- la qualità è una sola: se la connessione è lenta, il video si blocca;
- saltare a metà richiede che il server supporti le richieste di intervalli di byte, e il lettore non può adattarsi.
Lo streaming adattivo risolve entrambi i problemi lavorando sopra il normale protocollo HTTP. Non servono server speciali: i segmenti sono file statici che qualsiasi web server o CDN può distribuire.
Gli elementi di base
- Rendizioni: lo stesso video codificato in più versioni, per esempio 1080p a 5 Mbps, 720p a 3 Mbps, 480p a 1,2 Mbps e 360p a 600 kbps.
- Segmenti: ogni versione è divisa in pezzi di pochi secondi, tipicamente tra 2 e 6.
- Manifest: un file testuale che elenca le versioni disponibili e la posizione dei segmenti.
- Lettore: il software che legge il manifest, misura la banda e decide quale segmento scaricare.
Poiché il lettore può cambiare qualità solo tra un segmento e l'altro, tutti i segmenti devono iniziare con un keyframe e i tagli devono coincidere in tutte le versioni.
HLS
HTTP Live Streaming è stato introdotto da Apple ed è oggi il formato più compatibile, supportato nativamente da iOS, macOS, molti televisori e, tramite librerie JavaScript, da tutti i browser. Usa playlist in formato testuale con estensione .m3u8:
- una playlist principale (master) elenca le varianti con risoluzione, bitrate e codec;
- una playlist per ogni variante elenca i segmenti in ordine.
Un estratto di playlist principale ha questa forma:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5200000,RESOLUTION=1920x1080
1080p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3100000,RESOLUTION=1280x720
720p/index.m3u8
In origine i segmenti erano in MPEG-TS; oggi HLS supporta anche segmenti in MP4 frammentato.
MPEG-DASH
Dynamic Adaptive Streaming over HTTP è uno standard internazionale indipendente dai produttori. Il manifest, chiamato MPD, è un file XML che descrive periodi, insiemi di adattamento e rappresentazioni. DASH è indifferente al codec e lavora tipicamente con MP4 frammentato.
Non è supportato nativamente nei browser, ma funziona tramite le Media Source Extensions con librerie come dash.js o Shaka Player. Non è supportato nativamente nemmeno su iOS Safari, il che spiega perché molti servizi offrano entrambi i formati.
CMAF: un solo set di segmenti
Codificare e archiviare due volte gli stessi contenuti, una per HLS e una per DASH, raddoppia lo spazio occupato. Il formato CMAF definisce segmenti in MP4 frammentato utilizzabili da entrambi i protocolli: si producono due manifest diversi che puntano agli stessi file. È la soluzione più efficiente per chi deve servire tutti i dispositivi.
Come decide il lettore
L'algoritmo di adattamento, detto ABR (Adaptive Bitrate), usa due informazioni principali:
- la banda misurata: quanto velocemente sono stati scaricati gli ultimi segmenti;
- il livello del buffer: quanti secondi di video sono già pronti.
Con il buffer pieno il lettore può permettersi di provare una qualità superiore; con il buffer quasi vuoto scende di qualità per evitare il blocco. Un buon algoritmo evita anche di oscillare continuamente tra due livelli, cosa che lo spettatore percepisce come fastidiosa.
Problemi tipici e cause
| Sintomo | Causa probabile |
|---|---|
| cambi di qualità con scatto visibile | keyframe non allineati tra le rendizioni |
| buffering frequente su buone connessioni | segmenti troppo lunghi o salti troppo grandi tra rendizioni |
| avvio lento | primo segmento pesante o nessuna rendizione leggera |
| audio che sparisce al cambio di qualità | tracce audio diverse tra le varianti |
| funziona su computer ma non su iPhone | manifest DASH senza alternativa HLS |
Creare uno streaming HLS con FFmpeg
Per un singolo livello di qualità il comando di base è:
ffmpeg -i master.mp4 -c:v libx264 -crf 21 -g 50 -sc_threshold 0 -c:a aac -b:a 128k -hls_time 4 -hls_playlist_type vod -hls_segment_filename "seg_%03d.ts" index.m3u8
Per più livelli si usano le opzioni di mappatura multipla e il parametro -var_stream_map, oppure strumenti dedicati al packaging che partono da file MP4 già codificati.
In sintesi
- Lo streaming adattivo offre più qualità in segmenti e lascia scegliere al lettore.
- HLS usa playlist .m3u8 ed è il più compatibile, soprattutto su Apple.
- DASH usa un manifest XML ed è uno standard aperto e indipendente dal codec.
- CMAF permette di servire HLS e DASH con gli stessi segmenti.
- Keyframe allineati e una scala di qualità ben costruita evitano scatti e buffering.