Írjunk FFmpeg frontend-et – 1. rész
Az FFmpeg egy remek, igen nagy tudású program, de finoman fogalmazva is megválogatja a barátait, ha a felhasználói élményről van szó. Ezért gondoltam, készítek hozzá egy n+1. frontend implementációt.
De miért?
Az első egyértelműen felmerülő kérdés, hogy miért ír ilyet az ember, ha már van n+1 megoldás? Igazából két okból kezdtem bele a projektbe. Az első ok szimplán az, hogy amiket kipróbáltam, azok túlkomplikáltak és végső soron nem tetszettek. A másik ok pedig a tanulás. Rengeteget lehet tanulni egy ilyen projektből és nem utolsó sorban cikk alapanyagnak sem elhanyagolható a téma.
Mi az a FFmpeg?
Egy másik, egyértelműen felmerülő kérdés, hogy mi is az az FFmpeg? A projekt hivatalos leírása alapján (https://ffmpeg.org/) “Egy komplett, platformfüggetlen megoldás hang és videó rögzítésére, konvertálására és streamelésére”.
Ebből azonban nem derül ki teljesen, hogy mi is ez. Én inkább úgy fogalmaznék, hogy az FFmpeg egy olyan önálló kodek, program csomag, ami mindenből mindenbe is konvertálni tud. Túlzás nélkül valóban állíthatom, hogy az FFmpeg tényleg bármilyen formátummal elboldogul, legyen az bármennyire egzotikus is. Erre egy jó példa, ha a Quake III engine által használt ROQ formátumból szeretnénk WMV-be konvertálni, azt is megoldja. Természetesen az egzotikus formátumok mellett támogat minden modern megoldást is.
Az FFmpeg univerzalitását és népszerűségét szerintem jól leírja, hogy a YouTube videófeltöltő backend részén is ez dolgozik, illetve a népszerű VLC Player mögött is ez a kodek dolgozik. További előnye, hogy hatalmas hardvertámogatással rendelkezik. Ha van a gépünkben egy “krumplinál” nagyobb számítási teljesítménnyel rendelkező NVIDIA vagy AMD grafikus kártya, akkor az ezekben megtalálható hardveres videó dekódolót használatba tudja venni, illetve ha a hardver tud kódolni is, akkor erre is lehetőséget biztosít.
Ez a gyakorlatban azt jelenti, hogy ha van mondjuk egy GTX960-nál újabb videó kártyánk, akkor HD (h264) és UHD (h265) kódolást minimális (1-5%) CPU használat mellett el tudunk végezni.
FFmpeg gyorstalpaló
Az FFmpeg, mint említettem, leginkább egy kodek, amit más programokba, videólejátszókba lehet építeni. Többek között ez van beépítve a VLC-be, az MPlayer-be és az MPV lejátszóba is. Ezen felül azonban használható önálló parancssori programként is. Ezentúl, ha az FFmpeg szó szerepel a cikkben, akkor a parancssori program értendő alatta.
Eltérően a hagyományos programoktól FFmpeg esetén nem jó, ha az ember valamelyik „stabil” kiadást használja. Ennek az az oka, hogy a program fejlesztése viszonylag gyorsan pörög és a stabil kiadás Debian szint szerinti stabil. Ebből adódóan nem sűrűn van ilyen kiadás. Legutóbb 2016-ban jött ki a 3.0-ás verzió.
Éppen ezért mindig a legfrissebb változat használata célszerű. Ez azonban nem azt jelenti, hogy egy olyan programot kell használnunk, ami az esetek nagy részében a feladat elvégzése helyett összeomlik. A közvetlen a Git tárolóból beszerezett és fordított programok is ugyanolyan stabilak, mint a tényleges kiadások. Ritkán fogunk összeomlással találkozni.
Ez alapján felmerülhet a kérdés, hogy akkor miért nincs sűrűbben stabil kiadás? Ennek az oka talán abban kereshető, hogy az FFmpeg rengeteg egzotikus formátumot támogat. Ezek támogatása sok esetben specifikáció hiányában reverse engineering-gel történik, ami azt jelenti, hogy a kodek eredeti binárisa vagy rosszabb esetben a kódolt médiafájl alapján próbálják a fejlesztők kitalálni, megérteni, hogy hogyan is működik a kódolás és hogyan lehet reprodukálni azt. Ez egy időigényes folyamat és amíg egy kodek, ami a támogatott listában van, nem véglegesedik, addig nem jelölik stabilnak a verziót.
Mivel a kodekek nagy része reverse engineering-gel fejlesztett és a világ másik részén létezik szoftver szabadalom, ezért az FFmpeg-et alapvetően forráskódban terjesztik. Ebből bináris, futtatható programot a felhasználónak kellene fordítania. Azért csak kellene, mert léteznek emberek, akik fordítanak binárist, de hivatalos FFmpeg által kiadott bináris nem létezik. Windows esetén, ha magunk akarunk fordítani binárist, akkor a https://github.com/m-ab-s/media-autobuild_suite bach szkript egész jól automatizálva, interaktívan végigvezet bennünket a folyamaton, hogy ne kelljen bajlódnunk a függőségek és a megfelelő fordítók, segédprogramok beszerzésével.
Ha ezt a módszert választjuk, akkor az előnye az, hogy egy testre szabott FFmpeg binárist kapunk, ami valóban azt tudja amit szeretnénk. De ennek az az ára, hogy nagyjából ~30GiB szabad helyre és processzor típustól függően legalább 3-4 óra szabadidőre lesz szükségünk az első alkalommal.
Egy másik módszer a binárishoz jutáshoz az az, hogy más által fordított binárist használjunk. Ennek a hátránya, hogy a bináris tudását nem mi választjuk meg, de csak szimplán le kell töltenünk és már használható is. Ilyen letöltési lehetőségeket a projekt hivatalos oldala (https://www.ffmpeg.org/download.html) is kínál. Én a https://www.gyan.dev/ffmpeg/builds/ oldalról szoktam binárist beszerezni, mivel ezek a binárisok tartalmazzák az NVIDIA kártyák használatba vételéhez szükséges kódokat is.
Hátránya ezeknek a binárisoknak, hogy ezek úgynevezett statikus build-ek. Ez azt jelenti, hogy osztott komponensek nélkül, önállóan is használható EXE fájlokat tartalmaznak. Ez papíron jól hangzik, de mint mindennek, ennek is meg van az ára.
Ez az ár pedig a tárhely. Egy ilyen ffmpeg.exe mérete simán 80-100MiB körüli, mivel minden benne van az egy darab EXE fájlban. A probléma csupán az, hogy szükségünk van az ffprobe.exe-re is.
Az ffprobe egy médiatípus felismerő program, ami információkat tud szolgáltatni a médiafájlról. Például olyanokat, hogy milyen hosszú az adott média, mivel és mikor lett kódolva, stb…
Média konvertálás esetén nem feltétlen van erre szükségünk, de sajnos egy funkció miatt mégis építeni fog rá a frondendünk. Ez pedig a hossz lekérdezése. Sajnos az FFmpeg segítségével nem kérdezhető le egy médiafájl hossza. Erre az információra lényegében azért van szükségünk, hogy majd szép folyamatjelzőt tudjunk rajzolni a jelenlegi állapotról.
Szóval egy statikus FFmpeg build (ffmpeg.exe és ffprobe.exe) páros mérete simán elérheti a 200MiB méretet, míg ez dinamikusan betölthető és megosztható komponensek (DLL fájlok) használatával jóval kevesebb lenne, de valamit valamiért.
Az FFmpeg használata és betekintés a problémakörbe
A program alapvető használata nem bonyolult, de hamar el lehet veszni a különböző beállításokban. A két legfontosabb argumentum, amit mindenképpen meg kell határoznunk, az a bemeneti fájl és a kimeneti fájl.
A bemeneti fájl a -i kapcsoló segítségével adható meg, a kimenet pedig az első fájl lesz, ami kapcsolók nélkül szerepel. Ez a gyakorlatban így néz ki:
ffmpeg -i be.wav ki.mp3
A fenti parancssor már működőképes, mivel az mp3 egy olyan konténer formátum, ami csak mp3 kódolt hanganyagot tartalmazhat, ezért nem kell meghatároznunk a kodeket.
Ha olyan konténer formátumot használnánk, ami többféle kódolást is támogat, akkor a -c:a kapcsoló segítségével meg kellene határoznunk a használni kívánt kódolót. Például ha a be.wav˙fájlunkat Apple lossless formátumba szeretnénk alakítani, akkor a következő parancsot kellene beírnunk:
ffmpeg -i be.wav -c:a alac ki.m4a
Egyes formátumok esetén szükségünk lesz meghatározni a bitrátát is. Erre a -b:a és -b:v opció alkalmazható audió és videó esetén. Videó kódolót ezen logika mentén a -c:v opcióval tudunk meghatározni.
Az említett -c:v opció másolásra is használható, ami egy speciális konverzió, az úgynevezett muxolás. Ez azért speciális, mert nem kódoljuk újra a fájlt, csupán konténer formátumot váltunk alatta. Például ha van egy AVI fájlunk, amit át szeretnénk alakítani MKV-be, akkor az alábbi parancsot adhatjuk ki:
ffmpeg -i be.avi -c:a copy -c:v copy ki.mkv
A copy kodek név jelzi az FFmpeg számára, hogy másolni szeretnénk. Itt megjegyzem, hogy az AVI és az MKV a két olyan joker konténer, ami bármit is tartalmazhat, míg mondjuk az MP4 esetén limitálva vannak a lehetőségek.
Ha lehetőségünk van rá, akkor kerüljük az AVI fájlok használatát, mivel ezen formátum képtelen 2GiB méret fölött működni.
Egyes formátumok esetén például rögzítve van a videó kodek és a használható hang kodek is. Ilyen például a WMV, de a DVD formátum is. A DVD esetén van némi mozgástér, de nem sok. Éppen ezért, ha DVD lejátszóval kompatibilis Mpeg2 fájlt szeretnénk kódolni, akkor erre egy külön kapcsolót biztosít az FFmpeg:
ffmpeg -i be.mkv -target pal-dvd ki.mpeg
Ez a hangot AC3 kódolással tárolja, valamint a videót olyan felbontással és kódolással, hogy egy PAL szabványos DVD lejátszó gond nélkül boldoguljon vele. Ez a kódolás változó bitrátát fog alkalmazni úgy, hogy 2 óra videó és hang ráférjen egy egy rétegű DVD lemezre.
Ez csak egy volt az FFmpeg egzotikus képességeiből, de nézzünk egy másik, hasznos gyakorlati példát: a telefonunk által rögzített HD videót szeretnénk kisebb méretűvé konvertálni (h.265 formátumba) hardver gyorsítással úgy, hogy csak a képet tömörítjük újra. Ebben az esetben, ha NVIDIA kártyánk van, akkor valami hasonló parancsot adhatnánk meg:
ffmpeg -hwaccel nvdec -i telefon.mp4 c:v hevc_nvenc -preset slow -c:a copy ki.mp4
Mint látható, itt már bonyolódik a parancssor és még csak a felszínt kapargatjuk. A programunk abban fog segíteni, hogy ezt a rengeteg opciót, ami rendelkezésünkre áll, egyszerűsíti előre definiált beállításokkal (preset), hogy ne kelljen ezt a rengeteg kapcsolót és mindent megjegyeznünk és fejben tartanunk.
Folytatása következik…
2022.04.26. @ 14:38
Tök jó ez a cikk. Nyomtatott könyv terve hogy áll?