Mi FFmpeg no reconoce correctamente los subtítulos WebVTT
Estoy teniendo problemas a la hora de procesar ficheros Matroska con subtítulos en formato WebVTT.
Veamos un ejemplo:
La utilidad Matroska mkvmerge -i reconoce las pistas correctamente:
Track ID 0: video (AVC/H.264/MPEG-4p10) Track ID 1: audio (E-AC-3) Track ID 2: audio (AC-3) Track ID 3: subtitles (SubRip/SRT) Track ID 4: subtitles (WebVTT)
En cambio la utilidad FFmpeg ffprobe tiene problemas para identificar el códec a utilizar con los subtítulos WebVTT:
Stream #0:4: Subtitle: none
Metadata:
title : Completos
BPS : 53
DURATION : 01:43:10.562000000
NUMBER_OF_FRAMES: 1471
NUMBER_OF_BYTES : 41590
Unsupported codec with id 0 for input stream 4
El none indica que no sabe qué hacer con esa pista.
Curiosamente mi instalación FFmpeg sí soporta el formato WebVTT:
jcea@jcea:~$ ffmpeg -codecs | grep -i webvtt ffmpeg version 6.1.2 Copyright (c) 2000-2024 the FFmpeg developers [...] DES... webvtt WebVTT subtitle
Vemos que mi FFmpeg sí tiene soporte de subtítulos WebVTT, tanto para codificar como para decodificar.
Investigando por qué FFmpeg 6.1 no reconoce las pistas WebVTT de mis ficheros Matroska, veo que se trata de un problema conocido:
- [FFmpeg-devel] [PATCH] Add matroska codec id S_TEXT/WEBVTT for WebVTT streams (I).
- [FFmpeg-devel] [PATCH] Add matroska codec id S_TEXT/WEBVTT for WebVTT streams (II).
La explicación sencilla es que hay dos formas de codificar subtítulos WebVTT y mi versión de FFmpeg solo soporta el formato antiguo, no el nuevo utilizado en los ficheros Matroska modernos.
Parece que lo más sencillo sería actualizar a FFmpeg 7, pero por diversos motivos no es algo que pueda hacer a corto plazo.
¿Qué opciones tengo?
Dado que mi FFmpeg sí que es capaz de procesar los subtítulos WebVTT si se los doy en un formato que entienda, puedo hacer lo siguiente:
- Exportar los subtítulos WebVTT a formato texto, sin utilizar un contenedor Matroska.
- Utilizar FFmpeg para convertir esos subtítulos WebVTT a otro formato que mi FFmpeg sepa manejar correctamente dentro de un archivo Matroska. Por ejemplo, SubRip.
- Volver a montar el archivo Matroska original, pero reemplazando la pista WebVTT por la nueva pista SubRip equivalente.
Veamos un ejemplo concreto:
jcea@jcea:~$ mkvextract tracks FICHERO.MKV 4:z.vtt Extracting track 4 with the CodecID 'S_TEXT/WEBVTT' to the file 'z.vtt'. Container format: WebVTT subtitles Progress: 100% jcea@jcea:~$ ffmpeg -i z.vtt z.srt [...] Input #0, webvtt, from 'z.vtt': Duration: N/A, bitrate: N/A Stream #0:0: Subtitle: webvtt Output #0, srt, to 'z.srt': Metadata: encoder : Lavf60.16.100 Stream #0:0: Subtitle: subrip Metadata: encoder : Lavc60.31.102 srt Stream mapping: Stream #0:0 -> #0:0 (webvtt (native) -> subrip (srt)) [...] jcea@jcea:~$ chardetect z.srt z.srt: UTF-8-SIG with confidence 1.0 jcea@jcea:~$ mkvmerge -o z.mkv --subtitle-tracks '!4' FICHERO.MKV --language 0:es --sub-charset 0:UTF-8-SIG z.srt [...] jcea@jcea:~$ rm z.srt z.vtt jcea@jcea:~$ mv z.mkv FICHERO.MKV
El primer comando extrae los subtítulos WebVTT del fichero Matroska. El segundo comando convierte los subtítulos de WebVTT a SubRip y podemos ver el proceso con detalle. El siguiente comando determina el juego de caracteres que se emplea en los subtítulos, en este caso UTF-8-SIG.
A continuación creamos un nuevo fichero Matroska copiando todas las pistas originales excepto la cuatro (la pista WebVTT) y añadiendo la nueva pista, proveniente de un fichero diferente, en formato SubRip. Le indicamos el idioma de los subtítulos, y su juego de caracteres. Obsérvese cómo se excluye la pista cuatro, usando el símbolo ! y poniendo el parámetro entre apóstrofes porque el carácter ! tiene un significado especial en Bash que nos inteferiría y que desactivamos rodeando el parámetro con los apóstrofes.
Por último, borramos los ficheros temporales y renombramos el archivo Matroska para reemplazar al original.
Todo esto será innecesario, espero, cuando actualice a FFmpeg 7.