2006
09.05

Free software wonders

Un post tecnico, ogni tanto, fa bene :). Recentemente, ho scaricato un video dei New Order live al festival “T in the park” del 2005. Il genio che ha encodato tale video ha avuto la fantastica idea di impostare una risoluzione sbagliata nel file, con il risultato che questo viene visualizzato troppo stretto e troppo alto. Non sono molto pratico in queste cose, e forse il problema si poteva risolvere semplicemente modificando l’header del file, ma io ho scelto un’altra strada, approfittandono per provare il fantastico tool del free software che ho scoperto qualche giorno fa: FFmpeg. Si tratta, in sostanza, di convertitore di formati video, assolutamente automatico. Basta dargli in pasto il file sorgente e il nome del file di destinazione, e lui farà del suo meglio per effettuare la conversione mantenendo la maggiore qualità possibile.

Mettiamolo dunque alla prova. Il mio video è in formato MPEG2, e io vorrei convertirlo in MPEG4, usando l’ottimo xvid:

sukko@unholycathedral New order - Misc live $ ffmpeg -i atmosphere.mpg new.avi
FFmpeg version SVN-r6159, Copyright (c) 2000-2004 Fabrice Bellard
  configuration:  --prefix=/usr --enable-gpl --enable-mp3lame --enable-libogg --enable-vorbis --enable-faad --enable-faac --enable-libgsm --enable-xvid --enable-a52 --enable-pp --enable-shared --enable-pthreads --enable-amr_nb --enable-amr_wb
  libavutil version: 49.0.0
  libavcodec version: 51.12.0
  libavformat version: 50.5.0
  built on Sep  4 2006 01:32:39, gcc: 3.4.6
Input #0, mpeg, from 'atmosphere.mpg':
  Duration: 00:04:16.9, start: 0.168000, bitrate: 3988 kb/s
  Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 352x576, 5529 kb/s, 25.00 fps(r)
  Stream #0.1[0x1c0]: Audio: mp2, 48000 Hz, stereo, 224 kb/s
Output #0, avi, to 'new.avi':
  Stream #0.0: Video: mpeg4, yuv420p, 352x576, q=2-31, 200 kb/s, 25.00 fps(c)
  Stream #0.1: Audio: mp2, 48000 Hz, stereo, 64 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #0.1 -> #0.1
[mpeg4 @ 0xb7ddc988]removing common factors from framerate
Press [q] to stop encoding
frame=  140 q=26.5 Lsize=     335kB time=5.3 bitrate= 521.5kbits/s

(sì, so che il codice qua sopra sborda, sul blog, ma fate finta di niente.)

Uhm uhm, ci sono alcune cose che non mi piacciono. Primo: per qualche strana ragione, il bitrate dell’audio viene paurosamente ridotto, e la cosa non mi piace (ma perché?! non doveva mantenere la qualità?). Inoltre penso che sarebbe meglio averlo in MP3, per ridurre lo spazio occupato (Io mi accontento, i perfezionisti sorvolino). Diciamo che potremmo usare un bitrate di 256 kb/s: dato che stiamo ricomprimendo qualcosa che era già compresso, cerchiamo di minimizzare le perdite. Altra cosa che non mi piace è la dimensione del video: dovevamo correggerlo, no? Bene, così a spanne scegliamo un bel 640×400. Una rapida occhiata a man ffmpeg (che si rivelerà poi paurosamente outdated) e aggiungiamo qualche opzione:

sukko@unholycathedral New order - Misc live $ ffmpeg -i atmosphere.mpg \
-acodec mp3 -ab 256 \
-cropleft 20 -s 640x400 -sameq \
-title "New order - Atmosphere" -comment "Live at 'T in the park' 2005" new.avi
FFmpeg version SVN-r6159, Copyright (c) 2000-2004 Fabrice Bellard
  configuration:  --prefix=/usr --enable-gpl --enable-mp3lame --enable-libogg --enable-vorbis --enable-faad --enable-faac --enable-libgsm --enable-xvid --enable-a52 --enable-pp --enable-shared --enable-pthreads --enable-amr_nb --enable-amr_wb
  libavutil version: 49.0.0
  libavcodec version: 51.12.0
  libavformat version: 50.5.0
  built on Sep  4 2006 01:32:39, gcc: 3.4.6
Input #0, mpeg, from 'atmosphere.mpg':
  Duration: 00:04:16.9, start: 0.168000, bitrate: 3988 kb/s
  Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 352x576, 5529 kb/s, 25.00 fps(r)
  Stream #0.1[0x1c0]: Audio: mp2, 48000 Hz, stereo, 224 kb/s
Output #0, avi, to 'new.avi':
  Stream #0.0: Video: mpeg4, yuv420p, 640x400, q=2-31, 200 kb/s, 25.00 fps(c)
  Stream #0.1: Audio: mp3, 48000 Hz, stereo, 256 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #0.1 -> #0.1
[mpeg4 @ 0xb7db9988]removing common factors from framerate
Press [q] to stop encoding
[mp3 @ 0xb7db9988]lame: output buffer too small (buffer index: 304, free bytes: 2000)
frame=   34 q=0.0 Lsize=     710kB time=1.0 bitrate=6057.5kbits/s

Ho abbondato di nuove opzioni scoperte nel man: -cropleft serve a tagliare dei pixel dal lato sinistro del video: siccome c’era una orrenda barra nera, era proprio il caso di usarla (20 pixel l’ho stimato a naso/caso :D). -title e -comment servono ad aggiungere informazioni embeddate nel video: siccome nel filename è facile perderle, meglio scriverci dentro che cos’è, una volta per tutte. -s serve ad effettuare il ridimensionamento tanto agognato. Notare che va messa dopo eventuali opzioni di ritaglio, dato che il ridimensionamento deve avvenire dopo questo. -sameq serve invece a mantenere la stessa qualità del video sorgente. Non ho capito perché metterla, ma vi garantisco che la conversione riesce decisamente meglio utilizzandola. Tra l’altro, il bitrate che indica è sempre lo stesso, usandola o meno, quindi mi chiedo cosa possa cambiare…

Il risultato è esattamente come ci aspettamo: buono. Ma… c’è un problema: noto solo ora – che vedo il video con proporzioni decenti per la prima volta – che audio e video sono sfasati. Il buon mplayer, il player multimediale che uso di solito per vedere i video, permette di ritardare/anticipare l’audio rispetto al video, premendo i tasti + e - del tastierino numerico. Scopro così che con 200-300 ms di ritardo del video il tutto sembra più naturale. Potrei accontentarmi, ma… se un giorno vedessi questo video su un altro player, magari di quelli da tavolo, senza questa utilissima funzione? Dobbiamo risolvere una volta per tutte!

Dato che nel man di ffmpeg non vedo opzioni per “rifasare” audio e video facilmente utilizzabili, mi invento il seguente procedimento. Passo 1: estrarre l’audio dal filmato originale. L’ottimo ffmpeg viene ancora una volta in aiuto:

sukko@unholycathedral New order - Misc live $ ffmpeg -i atmosphere.mpg -vn new.wav
FFmpeg version SVN-r6159, Copyright (c) 2000-2004 Fabrice Bellard
  configuration:  --prefix=/usr --enable-gpl --enable-mp3lame --enable-libogg --enable-vorbis --enable-faad --enable-faac --enable-libgsm --enable-xvid --enable-a52 --enable-pp --enable-shared --enable-pthreads --enable-amr_nb --enable-amr_wb
  libavutil version: 49.0.0
  libavcodec version: 51.12.0
  libavformat version: 50.5.0
  built on Sep  4 2006 01:32:39, gcc: 3.4.6
Input #0, mpeg, from 'atmosphere.mpg':
  Duration: 00:04:16.9, start: 0.168000, bitrate: 3988 kb/s
  Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 352x576, 5529 kb/s, 25.00 fps(r)
  Stream #0.1[0x1c0]: Audio: mp2, 48000 Hz, stereo, 224 kb/s
Output #0, wav, to 'new.wav':
  Stream #0.0: Audio: pcm_s16le, 48000 Hz, stereo, 1536 kb/s
Stream mapping:
  Stream #0.1 -> #0.0
Press [q] to stop encoding
size=   48240kB time=257.3 bitrate=1536.0kbits/s
video:0kB audio:48240kB global headers:0kB muxing overhead 0.000089%

Passo 2: apriamo un editor audio, tipo Audacity, e tagliamo via i primi 250 ms (anche qua, a naso) dal file (basta selezionarli e premere canc). Salviamo e torniamo alla shell per l’ultimo passo:

sukko@unholycathedral New order - Misc live $ ffmpeg -i atmosphere.mpg -i new.wav \
-acodec mp3 -ab 256 \
-cropleft 20 -s 640x400 -sameq \
-title "New order - Atmosphere" -comment "Live at 'T in the park' 2005" new.avi \
-map 0:0 -map 1:0
FFmpeg version SVN-r6159, Copyright (c) 2000-2004 Fabrice Bellard
  configuration:  --prefix=/usr --enable-gpl --enable-mp3lame --enable-libogg --enable-vorbis --enable-faad --enable-faac --enable-libgsm --enable-xvid --enable-a52 --enable-pp --enable-shared --enable-pthreads --enable-amr_nb --enable-amr_wb
  libavutil version: 49.0.0
  libavcodec version: 51.12.0
  libavformat version: 50.5.0
  built on Sep  4 2006 01:32:39, gcc: 3.4.6
Input #0, mpeg, from 'atmosphere.mpg':
  Duration: 00:04:16.9, start: 0.168000, bitrate: 3988 kb/s
  Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 352x576, 5529 kb/s, 25.00 fps(r)
  Stream #0.1[0x1c0]: Audio: mp2, 48000 Hz, stereo, 224 kb/s
Input #1, wav, from 'new.wav':
  Duration: 00:04:17.0, start: 0.000000, bitrate: 1536 kb/s
  Stream #1.0: Audio: pcm_s16le, 48000 Hz, stereo, 1536 kb/s
Output #0, avi, to 'new.avi':
  Stream #0.0: Video: mpeg4, yuv420p, 640x400, q=2-31, 200 kb/s, 25.00 fps(c)
  Stream #0.1: Audio: mp3, 48000 Hz, stereo, 256 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #1.0 -> #0.1
[mpeg4 @ 0xb7d75988]removing common factors from framerate
Press [q] to stop encoding
frame= 1115 q=0.0 size=   21716kB time=44.6 bitrate=3991.6kbits/s

In questo modo effettuiamo la conversione, come prima, ma grazie alle opzioni -map, ffmpeg prenderà il video dal file iniziale, e l’audio da quello che abbiamo appena modificato, al quale mancano i primi 250 ms. Un po’ di pazienza e… ecco raggiunto il nostro risultato con soddisfazione del 100%! E abbiamo fatto il tutto usando solo ed esclusivamente software libero, nonché gratuito, alla facciazza di Adobe Premiere e Adobe Audition! Ovviamente, tutto quel che ho scritto è stato fatto su GNU/Linux :).