sobota 9. července 2011

Extrakce audio stopy nejen z flash videa

Potřebuju asi z padesáti videí z youtube vytáhnout zvuk do samostatného souboru ve formátu mp3. Všechny videosoubory jsou v kontejneru flv, ale některé obsahují flv video se zvukem v kompresi mp3 a zbytek h264 video se zvukem v kompresi aac. Musím tedy projít jednotlivé soubory, pokud bude zvuk ve formátu mp3 jen uložit audiostopu a zbytečně ji nekomprimovat znovu (to je vždy na úkor už tak bídné kvality), a ostatní audiostopy překomprimovat do formátu mp3. Ještě že máme ten příkazový řádek. Následující se ale netýká pouze flash videa, s ostatními kontejnery je to stejné...

MPlayer
Začal jsem zkoumáním možností MPlayeru, protože jsem ho již k podobnému úkolu kdysi úspěšně použil.
Mplayer je jedním z nejpopulárnějších multimediálních přehrávačů, je to program pro příkazový řádek, ke kterému je dostupná spousta grafických front-endů, jako např. gMplayer, Gnome MPlayer, KMplayer a můj oblíbený SMPlayer. Každopádně je to program, který toho umí hodně a o to hůř se čte jeho ukrutně dlouhý manuál (skoro 7000 řádků). Pokud ho náhodou nemáte (a chcete), nainstalujete stejnojmenný balík:

sudo apt-get install mplayer

Audiostopu pak oddělíte velmi jednoduše:

mplayer -dumpaudio audiostopa.mp3 videosoubor.flv

Pokud jde tedy o mp3 audio. Ani tak nejde o koncovku, podle té se rozhoduje pouze to, kterým programem vám vaše desktopové prostředí soubor otevře, klidně můžete dát souboru koncovku emil, a stejně to stále bude mp3 a multimediální programy to tak budou přehrávat.
Jenže pokud je zvuk ve formátu aac, takto oddělená audiostopa bude k ničemu, protože ji, na rozdíl od té mp3, žádný program nerozpozná, ať bude mít koncovku jakoukoli. Bude jí chybět nějaký ten kontejner, který jí dá identitu. Nemám tušení, jestli mplayer, nebo jeho kodér mencoder umí toto bez překódování ošetřit, tak daleko jsem nedošel, protože jsem zájem přesunul na FFmpeg.
Ještě zmíním způsob, jakým lze z mplayeru dostat nějaké informace o souboru. Není to moc elegantní, ale info to dá:

mplayer -ss 04:00:00 -quiet -identify videosoubor.flv

Tím dostanete všechny informace, včetně toho, jaké kodeky mplayer použije pro přehrávání. Použitý přepínač -ss je finta, která má zabránit přehrávání, začne se v tomto případě přehrávat od čtvrté hodiny záznamu, což je daleko za jeho koncem, takže k žádnému přehrávání nedojde a mplayer jen vypíše info.

FFmpeg
Pokračoval jsem tedy zkoumáním FFmpeg, což je nástroj, kterým lze konvertovat v podstaě jakékoli audio a videosoubory z různých zdrojů, včetně třeba DVB-T tunerů, a jeho služeb umí využívat nejeden multimediální program, včetně MPlayeru. Pod projektem FFmpeg se skrývá víc, než jen konvertor, více třeba na Wiki, nebo na domovské stránce projektu.

Pokud nemáte (a chcete), nainstalujete klasicky:

sudo apt-get install ffmpeg

Začnu postupně, zjištěním informací o videosouboru:

ffmpeg -i videosoubor

Pokud ffmpegu dodáte jen zdrojový soubor, vypíše info o sobě samém, i onom souboru a chybu, že není dán žádný soubor výstupní.
Oddělit audiostopu můžete následujícím způsobem:

ffmpeg -i videosoubor -vn -acodec copy audiostopa.koncovka

A tady je rozdíl oproti použití MPlayeru, protože na oné koncovce v příkazu zaleží. FFmpeg podle vámi dodané koncovky upraví výstupní soubor tak, aby odpovídal danému formátu. Pokud víte, že audiostopa je ve formátu aac, můžete použít běžnou koncovku .m4a, nebo .aac a FFmpeg zařídí, že ten soubor bude opravdu aac audio a každý přehrávač podporující tento formát ho přehraje. Když dáte aac audiu koncovku .mp3, FFmpeg to vyplivne jako mp3 a bude to pro přehrávače nečitelné. Pokud přidáte koncovku .emil, dostanete chybové hlášení, že FFmpeg nenašel patřičný formát výstupního souboru.
Máte-li mix videí, které obsahují mp3, i aac zvuk a chcete z nich audio vytáhnout tak, jak je, bez překódování, můžete si napsat skript, který projde všechny flv soubory v adresáři a z každého vytáhne audiostopu tak, aby výsledný soubor měl správný formát i koncovku. Pozor následující je jeden příkaz, jen je rozdělený na dva řádky pro přehlednost, zpětné lomítko v shellu umožňuje pokračovat na dalším řádku:

for i in *.flv ; do ffmpeg -i "$f" -vn -acodec copy "`echo $f | \
sed 's/\.flv$//'`.`ffmpeg -i "$f" 2>&1 | grep "Stream.*Audio" | \
awk '{print $4}' | sed 's/,//'`"; done

Tento skript předpokládá spuštění v adresáři s videi, ze kterých chcete audio vypreparovat, ale můžete si přidat cesty podle potřeby. Skript funguje následovně: jeden po druhém se probírají soubory s koncovkou .flv v aktuálním adresáři (pokud v adresáři jiné soubory nejsou, můžete použít jen hvězdičku), oddělí se zvuková stopa a uloží se do souboru, jehož jméno se složí ze jména původního souboru bez koncovky .flv a jako koncovka se přidá jméno formátu audia, které se zjistí přímo z videosouboru. Tedy aac soubory budou mít koncovku .aac.

Nicméně já jsem to potřeboval převést vše do formátu mp3. To s FFmpeg není problém, stačí mít nainstalován kodek pro mp3 konverzi - lame

sudo apt-get install lame

a rozšíření knihovny libavcodec o balík libavcodec-unstripped. V Ubuntu 10.04 a 10.10 je to konkrétně tento soubor:

sudo apt-get install libavcodec-unstripped-52

Základní konverze vypadá takto:

ffmpeg -i videosoubor.flv -vn -acodec libmp3lame -ab 128kb audiostopa.mp3

Přepínač -ab samozřejmě určuje bitrate výsledné empétrojky.

Takže k tomu, co jsem zmínil v úvodu: Projít všechna videa v adresáři, z těch, které mají zvuk ve formátu mp3 jen vyjmout audiostopu bez rekomprese a ostatní audiostopy z jiných formátů překonvertovat také do mp3. Tady je v podstatě jedno, zda je výchozí audio aac, nebo jiného formátu, ffmpeg cokoliv (co zná) převede do mp3:

for f in *.flv; do n=`echo $f|sed 's/\.flv$//'`; \
if [ `ffmpeg -i "$f" 2>&1|grep "Stream.*Audio"` =~ "mp3," ]; \
then ffmpeg -i "$f" -vn -acodec copy "$n.mp3"; \
else ffmpeg -i "$f" -vn -acodec libmp3lame -ab 128kb "$n.mp3"; fi; done

Opět je to jednořádkový skript.

Takže já mám hotovo.

Žádné komentáře:

Okomentovat

Zkuste prosím při komentováni používat místo volby Anonymní volbu Název/adresa URL, kde vyplníte nějakou přezdívku, adresu zadávat nemusíte. Vědět, které příspěvky jsou od jednoho člověka, je fajn. Díky.

Pokud by se vám náhodou odeslaný komentář na stránce nezobrazil, vytáhnu ho z koše hned jak si toho všimnu. I Google spam filter se občas sekne.