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:

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:

  1. Exportar los subtítulos WebVTT a formato texto, sin utilizar un contenedor Matroska.
  2. 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.
  3. 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.