Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Convertir un vídeo con varios audios y subtítulos a "Matroska"

Última Actualización: 18 de febrero de 2008 - Lunes

El fichero original es un AVI de 2 gigabytes. El bitrate de video es de 2075Kbps. Hay dos cadenas de audio en MP3. La primera de 96Kbps (castellano, mono) y la segunda de unos 160kbps en inglés (estéreo). Además hay tres juegos de subtítulos: castellano, inglés y forzados.

La imagen en sí es pequeña y en blanco y negro (es una película antigua), así que un bitrate de vídeo tan elevado es un desperdicio. La banda de sonido de 96Kbps no se debe recodificar, porque ya está bastante comprimida y cualquier proceso adicional reducirá su calidad. La banda de 160Kbps se recodificará en Vorbis, con un nivel de calidad de 2 (unos 96kbps o menos). Es de señalar que la calidad del audio, en cualquier caso, es bastante mediocre, con el "refrito" habitual de la época, como los crujidos de los discos de vinilo :-).

El primer paso será extraer las dos bandas de sonido:

$ mplayer -ao pcm:fast:file=ingles.wav -vo null -vc null pelicula.avi
$ mplayer -aid 2 -dumpaudio -dumpfile castellano.mp3 -vo null -vc null pelicula.avi

El audio en inglés lo extraemos en PCM, para poder recodificarlo de nuevo. El audio en castellano lo sacamos directamente en MP3, y no lo vamos a tocar. Obsérvese que el castellano es el segundo audio. Eso lo cambiaremos en el Matroska final.

Recomprimimos el audio en inglés:

$ normalize -v ingles.wav
$ oggenc -q2 ingles.wav
Mientras está codificando el audio en Vorbis, que lleva un ratillo, vamos adelantando tiempo realizando la primera pasada en el vídeo, en otra sesión, aprovechando que tenemos una máquina con varias CPUs. Lo normal sería que hiciésemos la primera pasada con una parámetros más inexactos pero más rápidos. Pero dado que la película es bastante larga, seamos precisos con los cálculos:
$ mencoder -oac copy -ovc xvid -xvidencopts \
   chroma_opt:vhq=4:bvhq=1:quant_type=mpeg:greyscale:pass=1:turbo \
   -o /dev/null  pelicula.avi

La película dura 2 horas exactas, pero es en blanco y negro. Hay dos audios, totalizando 160056951 bytes. Para compensar por los dos audios, el tamaño final del fichero será de 800MB (en vez de los dos gigas originales). Es decir, para el vídeo tendremos 678803849 bytes.

$ mencoder -oac copy -ovc xvid -xvidencopts \
   chroma_opt:vhq=4:bvhq=1:quant_type=mpeg:greyscale:pass=2:threads=2:bitrate=-662894 \
   -o pelicula2.avi pelicula.avi

El bitrate negativo indica los kbytes que queremos de objetivo para el vídeo. El campo "threads" aprovecha las múltiples CPUs del equipo, para realizar la codificación en paralelo. Es de señalar que la versión actual de la librería XVID (la 1.1.3) no soporta multithreading, así que estoy empleando la versión "del día". Espero que sea estable y no tenga bugs importantes, que genere un video sin fallos, etc. Crucemos los dedos, mientras la gente de XVID no saca una versión nueva oficial :).

El siguiente paso es montar el fichero Matroska. Este proceso es muy rápido (en mi caso, unos 30 segundos). Indicamos todos los tracks de una vez. Aprovecho para etiquetar el idioma:

$ mkvmerge -o pelicula.mkv -A pelicula2.avi --default-language es \
   castellano.mp3 --language 0:en ingles.ogg \
   subs_forzados.srt subs_castellano.srt --language 0:en subs_ingles.srt 

El parámetro "-A" indica que debe tomarse solo el video de ese fichero AVI. El audio se tomará de los otros parámetros.

La película, en total, ocupa 798'6 MB. El error es de solo el 0'18%. Me parece aceptable :-). Veamos el resultado:

$ mkvinfo *mkv
+ EBML head
|+ Doc type: matroska
|+ Doc type version: 1
|+ Doc type read version: 1
+ Segment, size 837377643
|+ Seek head (subentries will be skipped)
|+ EbmlVoid (size: 4027)
|+ Segment information
| + Timecode scale: 1000000
| + Muxing application: libebml v0.7.7 + libmatroska v0.8.1
| + Writing application: mkvmerge v2.1.0 ('Another Place To Fall') built on Feb 18 2008 17:13:11
| + Duration: 7276.616s (02:01:16.616000000)
| + Date: Mon Feb 18 22:43:28 2008 UTC
| + Segment UID: 0x14 0xbf 0x7d 0x20 0x8b 0xef 0x08 0x3b 0xf0 0x77 0xe7 0x56 0xe1 0x1e 0xa7 0xcf
|+ Segment tracks
| + A track
|  + Track number: 1
|  + Track UID: 2962089645
|  + Track type: video
|  + Enabled: 1
|  + Default flag: 1
|  + Forced flag: 0
|  + Lacing flag: 0
|  + MinCache: 1
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: V_MS/VFW/FOURCC
|  + Codec decode all: 1
|  + CodecPrivate, length 40 (FourCC: XVID, 0x44495658)
|  + Default duration: 41.708ms (23.976 fps for a video track)
|  + Language: spa
|  + Video track
|   + Pixel width: 624
|   + Pixel height: 464
|   + Interlaced: 0
|   + Display width: 624
|   + Display height: 464
| + A track
|  + Track number: 2
|  + Track UID: 2748744459
|  + Track type: audio
|  + Enabled: 1
|  + Default flag: 1
|  + Forced flag: 0
|  + Lacing flag: 1
|  + MinCache: 0
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: A_MPEG/L3
|  + Codec decode all: 1
|  + Default duration: 24.000ms (41.667 fps for a video track)
|  + Language: spa
|  + Audio track
|   + Sampling frequency: 48000.000000
|   + Channels: 1
| + A track
|  + Track number: 3
|  + Track UID: 2314523546
|  + Track type: audio
|  + Enabled: 1
|  + Default flag: 0
|  + Forced flag: 0
|  + Lacing flag: 1
|  + MinCache: 0
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: A_VORBIS
|  + Codec decode all: 1
|  + CodecPrivate, length 3874
|  + Language: eng
|  + Audio track
|   + Sampling frequency: 48000.000000
|   + Channels: 2
| + A track
|  + Track number: 4
|  + Track UID: 694148534
|  + Track type: subtitles
|  + Enabled: 1
|  + Default flag: 1
|  + Forced flag: 0
|  + Lacing flag: 0
|  + MinCache: 0
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: S_TEXT/UTF8
|  + Codec decode all: 1
|  + Language: spa
| + A track
|  + Track number: 5
|  + Track UID: 4046752372
|  + Track type: subtitles
|  + Enabled: 1
|  + Default flag: 0
|  + Forced flag: 0
|  + Lacing flag: 0
|  + MinCache: 0
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: S_TEXT/UTF8
|  + Codec decode all: 1
|  + Language: spa
| + A track
|  + Track number: 6
|  + Track UID: 4085419875
|  + Track type: subtitles
|  + Enabled: 1
|  + Default flag: 0
|  + Forced flag: 0
|  + Lacing flag: 0
|  + MinCache: 0
|  + Timecode scale: 1.000000
|  + Max BlockAddition ID: 0
|  + Codec ID: S_TEXT/UTF8
|  + Codec decode all: 1
|  + Language: eng
|+ EbmlVoid (size: 1024)
|+ Cluster

Ahora solo queda probar el vídeo en el reproductor. Comprobar la calidad, el dual, los subtítulos, etc.

Ya que estamos utilizando Matroska, que es un contenedor que no soporta ningún reproductor de salón (al menos hasta el momento - febrero 2008), ¿por qué no aprovechamos para codificar el vídeo en algo más moderno y eficiente, como x264?. La razón es simple: si alguien me pide la película pero no puede (o no quiere) reproducir un fichero MKV (Matroska), generar un fichero AVI compatible es una tarea trivial, porque el vídeo se puede copiar tal cual, y el audio se puede recodificar de forma rápida y simple. De hecho en este caso ni siquiera es necesario, ya que mantenemos el audio en castellano como MP3.


Historia

  • 18/feb/08: Primera versión de este documento



Python Zope ©2008 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS