Adott egy könyvtár, amiben van több száz alkönyvtár, amelyek mindegyikében van több ezer jpg kép. Ezekből kellene videót gyártani… automatizáltan… valahogy.
Szóval a fenti esetre kerestem megoldást. Mivel nem akartam az elkövetkezendő pár hónapot kattintgatással tölteni egy GUI felett, amivel talán meg tudtam volna oldani a feladatot, bár kétlem, mivel megpróbáltam pár programot, de szinte mindegyik megadta magát, amikor próbáltam beolvastatni velük azt a töménytelen mennyiségű képet. És valljuk be, nem annyira kényelmes megoldás, mint egy script, amit magára hagy az ember, hogy „dolgozz, majd holnap rád nézek, hogy kész vagy-e…”.
Gugliztam egy kicsit és sok egyéb program mellett a legkézenfekvőbb és legtöbbet emlegetett az ffmpeg volt. A többi is jónak tűnt, de mind elég régi (2014-16-os) cli programok voltak, nulla frissítéssel. Az ffmpeg viszont teljesen naprakész, tudja az x264-es kódolást, meg minden. A nehezítés az volt, hogy a környezet Windows. Ahol nem annyira kézenfekvő a command line használata, mint linux alapú környezetekben. Itt csak batch fileokat lehet fabrikálni többnyire, ami valljuk be, elég nagy fájdalom tud lenni. A másik nehezítés pedig a file-ok elnevezése volt. Nem tartalmaznak folyamatos sorszámot (pl. image-001.jpg
, image-002.jpg
, stb.), hanem időbélyeget (pl. image_2018-10-13_00.31.00_017.jpg
). Ezért az ffmpeg beépített funkcióját nem is tudtam rá alkalmazni.
Töltsük le a legújabb stable verziót („Download build”): https://ffmpeg.zeranoe.com/builds/
Első körben azt kellett kitalálnom, hogy mi is a jó paraméterezése az ffmpeg-nek, hogy normálisan kódolja a képeket videóvá. A szóba jöhető típusok az mp4 és az mkv voltak. Ehhez a következő paraméter kellett:
-c:v libx264
A következő kérdés, hogy hogyan tudnám rávenni arra, hogy a könyvtárban lévő összes jpg képet beolvassa és összefűzze. Ehhez előbb pipeline-t használtam és sima type
paranccsal küldtem neki a jpg képek tartalmát:
type *.jpg | d:\temp\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe -f image2 -f image2pipe -i - -c:v libx264 video.mp4
Ezzel az volt a gond, hogy a jpg képen nem olyan sorrenben jöttek, ahogy az kellett volna. Nekem arra volt szükségem, hogy név szerinti rendezésben jöjjenek. Kicsit tovább gugliztam és végül az alábbi batch file jött létre:
for /f "tokens=*" %%i in ('dir /b /o:n "*.jpg"') do ( type %%i | d:\temp\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe -f image2 -f image2pipe -i - -c:v libx264 video.mp4 )
Ezt egy kicsit továbbgondolva, az alábbira csiszoltam:
(for /f "tokens=*" %%i in ('dir /b /o:n "*.jpg"') do @echo file '%%i') > images.txt d:\temp\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe -f concat -i images.txt -c:v libx264 video.mp4 del images.txt
Ez így már jó is volt. A következő lépés az volt, hogy a kész videó file neve ne az legyen, hogy video.mp4
, hanem mindig az adott könyvtár neve, ami egy dátum, tehát pl. 201-04-19.mp4
. Ehhez az alábbiak szerint módosítottam a scriptet:
for %%a in ("%cd%") do set "DirName=%%~na" (for /f "tokens=*" %%i in ('dir /b /o:n "*.jpg"') do @echo file '%%i') > images.txt d:\temp\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe -f concat -i images.txt -c:v libx264 %DirName%.mp4 del images.txt
Már csak egy lépés maradt hátra. A scriptnek rekurzívan be kellene járni az összes könyvtárt és minden alkönyvtárban lévő kép kupacból videókat kéne gyártania. Kis kutakodás után, ez is meglett… Íme az eredmény:
@echo off call :treeProcess goto :eof :treeProcess rem Do whatever you want here over the files of this subdir, for example: for %%a in ("%cd%") do set "DirName=%%~na" (for /f "tokens=*" %%i in ('dir /b /o:n "*.jpg"') do @echo file '%%i') > images.txt d:\temp\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe -n -f concat -i images.txt -c:v libx264 h:\motions\%DirName%.mp4 del images.txt for /D %%d in (*) do ( cd %%d call :treeProcess cd .. ) exit /b