¿Qué son M3U y M3U8?
M3U es un formato de lista de reproducción de texto plano originalmente desarrollado por Winamp para gestionar listas de reproducción de audio. Un archivo M3U simplemente enumera rutas de archivos multimedia o URLs, una por línea, con comentarios de metadatos opcionales que comienzan con #EXTM3U y #EXTINF.
M3U8 es la versión codificada en UTF-8 de M3U y es el formato de lista de reproducción utilizado por HLS (HTTP Live Streaming), el protocolo de streaming adaptativo de Apple especificado en el RFC 8216. En HLS, los archivos M3U8 tienen un papel fundamentalmente diferente al de las listas de reproducción simples: orquestan la entrega adaptativa de transmisiones de vídeo/audio divididas en segmentos cortos.
M3U Básico: Listas de Reproducción Simples
#EXTM3U
#EXTINF:180,Nombre del Artista - Título de la Canción
/musica/artista/album/01-cancion.mp3
#EXTINF:245,Otro Artista - Otra Canción
https://stream.ejemplo.com/musica/cancion.mp3
#EXTINF:-1,Radio en Directo
https://radio.ejemplo.com/stream
Reglas de formato:
- Primera línea:
#EXTM3U(identifica formato M3U extendido) #EXTINF:duración,título— duración en segundos (-1 para en directo/desconocido) y título- Siguiente línea: ruta del archivo o URL al multimedia
HLS: Cómo Funciona HTTP Live Streaming
HLS es un protocolo de streaming de tasa de bits adaptativa. La idea clave: en lugar de servir un archivo de vídeo grande, HLS divide la transmisión en segmentos cortos (típicamente de 2-10 segundos cada uno como archivos MPEG-2 TS o fMP4) y los describe en archivos de manifiesto M3U8. El reproductor cliente obtiene el manifiesto, lee las URLs de los segmentos, los descarga secuencialmente y ensambla la reproducción continua.
Lista de Reproducción Maestra (variant.m3u8)
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,CODECS="avc1.42E01E,mp4a.40.2"
360p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720,CODECS="avc1.4D401F,mp4a.40.2"
720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2"
1080p.m3u8
Lista de Reproducción de Medios (720p.m3u8)
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
720p_000.ts
#EXTINF:10.0,
720p_001.ts
#EXTINF:7.543,
720p_002.ts
#EXT-X-ENDLIST
Crear Transmisiones HLS con FFmpeg
Segmentación HLS Básica
# Convertir MP4 a HLS (calidad única)
ffmpeg -i entrada.mp4 \
-codec:v libx264 -crf 20 -preset fast \
-codec:a aac -b:a 128k \
-hls_time 10 \
-hls_list_size 0 \
-hls_segment_filename "segmento_%03d.ts" \
salida.m3u8
HLS Multi-Tasa de Bits (Adaptativo)
ffmpeg -i entrada.mp4 \
-filter_complex "[0:v]split=3[v1][v2][v3]" \
-map "[v1]" -map 0:a -c:v:0 libx264 -b:v:0 5000k -s:v:0 1920x1080 \
-map "[v2]" -map 0:a -c:v:1 libx264 -b:v:1 2800k -s:v:1 1280x720 \
-map "[v3]" -map 0:a -c:v:2 libx264 -b:v:2 800k -s:v:2 640x360 \
-c:a aac -b:a 128k \
-f hls \
-hls_time 6 \
-hls_list_size 0 \
-hls_segment_filename "stream_%v/seg_%03d.ts" \
-master_pl_name master.m3u8 \
-var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" \
stream_%v/playlist.m3u8
Descargar Transmisiones HLS
Usando FFmpeg
# Descargar una transmisión HLS VOD completa a MP4
ffmpeg -i https://ejemplo.com/video/master.m3u8 \
-c copy -movflags +faststart salida.mp4
# Descargar variante de calidad específica
ffmpeg -i https://ejemplo.com/video/720p.m3u8 \
-c copy salida_720p.mp4
Usando yt-dlp
# Descargar transmisión HLS
yt-dlp https://ejemplo.com/watch?v=xyz
# Seleccionar calidad específica
yt-dlp -f "best[height<=720]" https://ejemplo.com/watch?v=xyz
Reproducir HLS en un Navegador Web
Usando hls.js (JavaScript)
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video" controls width="800"></video>
<script>
const video = document.getElementById('video');
const src = 'https://ejemplo.com/stream/master.m3u8';
if (Hls.isSupported()) {
const hls = new Hls({ startLevel: -1 });
hls.loadSource(src);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play());
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari tiene soporte HLS nativo
video.src = src;
video.play();
}
</script>
Safari e iOS/iPadOS tienen soporte HLS nativo. Los demás navegadores necesitan hls.js.
Analizar Listas de Reproducción M3U8 con Python
import urllib.request, re
def analizar_lista_maestra(url: str) -> list[dict]:
"""Analiza una lista de reproducción maestra HLS y devuelve info de variantes."""
with urllib.request.urlopen(url) as f:
contenido = f.read().decode('utf-8')
variantes = []
lineas = contenido.splitlines()
i = 0
while i < len(lineas):
linea = lineas[i]
if linea.startswith('#EXT-X-STREAM-INF:'):
attrs = {}
for m in re.finditer(r'(\w[\w-]*)=((?:"[^"]*"|\d+x\d+|[\d.]+))', linea):
attrs[m.group(1)] = m.group(2).strip('"')
i += 1
url_variante = lineas[i].strip()
if not url_variante.startswith('http'):
base = url.rsplit('/', 1)[0]
url_variante = f"{base}/{url_variante}"
attrs['url'] = url_variante
variantes.append(attrs)
i += 1
return sorted(variantes, key=lambda v: int(v.get('BANDWIDTH', 0)))
for v in analizar_lista_maestra('https://ejemplo.com/stream/master.m3u8'):
bw_kbps = int(v.get('BANDWIDTH', 0)) // 1000
res = v.get('RESOLUTION', 'solo audio')
print(f"{res} @ {bw_kbps} kbps → {v['url']}")
Servir HLS con nginx
server {
listen 80;
server_name video.ejemplo.com;
location /hls {
alias /var/www/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control "no-cache";
add_header Access-Control-Allow-Origin "*";
}
}
Conversiones relacionadas
Conversiones de vídeo que encajan con esta guía: