Jag har videoramar i PNG-format vid 1 FPS och jag försöker konvertera dem till en video med ffmpeg.
Om jag gör något så här:
ffmpeg -i data/input-%4d.png data/output.mp4
får jag en video vid 25FPS som i grunden är en väldigt snabbt framåt för ingången (som fångas upp vid 1FPS).
Om jag försöker:
ffmpeg -i data/input-%4d.png -r 1 data/output.mp4
Jag får något som VLC inte vill spela 🙂
Nu, om jag tar den första videon (FF-en) och använder ett filter för att sakta ner det (t.ex. -filter:v "setpts=24.0*PTS"
), jag kan få den att spela som en 1 FPS-video, men naturligtvis är priset filstorlek. Det genererar en massa upprepade bilder antar jag.
Så, frågan är hur jag skapar en video som har exakt 1 FPS och faktiskt spelar med den hastigheten? Utdataformatet, btw, är inte ” t som är viktigt för mig.
Kommentarer
Svar
Om du vill ha en one-liner för FFMPEG som genererar en video som spelas upp med 1 bildruta per sekund, vad du vill göra är att ange ramar för både in- och utgång, så här:
ffmpeg -r 1 -i data / input-% 4d.png -pix_fmt yuv420p -r 10 data / output.mp4
-r 1
betyder att videon spelas upp med en av originalbilderna per sekund.
-r 10
betyder att videon spelas upp med 10 bilder per sekund.
(-pix_fmt yuv420p
är precis där för att säkerställa kompatibilitet med ett brett utbud av uppspelningsprogram. Här krävs till exempel att videon ska kunna spelas upp av Windows Media Player.)
Jag testade många olika utmatningsramar och 10 verkar vara det lägsta antalet du kan använda som fortfarande ger en video som VLC kommer att spela.
Naturligtvis betyder kommandot ovan att varje originalbild multipliceras, men det är en enklare metod än den ”sakta ner” den du nämnde, och beroende på codec den kanske inte producerar en video som är mycket större än en äkta 1-FPS-video.
För att testa detta producerade jag bara en riktig 1-FPS-video, som blev 2,24 kiB. Jag producerade sedan en video med samma ingångsbilder men utdata vid 24 FPS, och det kom till 5,76 kiB. Det är drygt dubbelt så stort och inte i närheten av 24 gånger storleken. 🙂
Kommentarer
- +1 på -pix_fmt. Lätt att glöm vissa människor insisterar på att använda WMP 🙂
- varför vill du att utdataformatet ska vara 10 fps medan ingången bara är 1? Skulle ’ inte det skapa 90% redundanta ramar som är exakt samma?
- @ Herbert skapar det redundanta ramar så att du kan få bildfrekvensen upp till 10, vilket görs bara så VLC inte ’ t klagar , och det ändrar visuellt inte ’ videon. Kodaren är tillräckligt smart för att se att ramarna är identiska så du slutar inte ’ med en mycket större fil
- @chiliNUT klar, keyframe-saken, som inte alla format, men de mest förnuftiga format kommer att göra. Tack !
Svar
Använd båda -framerate
och -r
Till exempel att ha en slutlig video som ser ut som 1FPS:
ffmpeg -framerate 1 -pattern_type glob -i "*.png" \ -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
Detta liknar vad Konvertera PNG-ramar till video vid 1 FPS | Unix & Linux Stack Exchange säger, men jag behövde -framerate
istället för -r
för att det ska fungera.
Detta nämns på wiki: http://trac.ffmpeg.org/wiki/Slideshow#Framerates
Det sätter utmatningsramen till 30
, som VLC kan hantera, och kopierar varje bild 30 gånger, så att utdatavideoen verkar vara vid 1 FPS. Se även: Uppspelningsproblem i VLC med låg fps-video från bilder med ffmpeg | Stack Overflow
VLC kan sedan spela upp videon normalt.
Testad på Ubuntu 16.10, VLC 2.2.4, ffmpeg
3.0.5, i en katalog med 10 PNG.
Kommentarer
- Vad ’ är skillnaden mellan
-r
och-framerate
? - @Royi Jag vet inte ’, förutom att det är det enda som fungerade för mig 🙂 Men om du lyckades extrahera det från
man
-sidorna, låt mig veta 😉 Ett meningsfullt citat är ” -r Som ett inmatningsalternativ, ignorera alla tidsstämplar lagrade i filen och genererar istället tidsstämplar förutsatt konstant bildhastighet fps. Detta är inte detsamma som -frame-alternativet som används för vissa ingångsformat som image2 eller v4l2 (det brukade vara detsamma i äldre versioner av FFmpeg). Om du är osäker, använd -framerate istället för inmatningsalternativet -r. ”
Svar
Vad händer om du förstärker ditt andra exempel på följande sätt:
$ ffmpeg -r 1 -i data/input-%4d.png -c:v libx264 out.mp4
-r 1
måste komma före .png-filerna, inte efter.
Från FFmpeg-dokumentation :
Som en allmän regel tillämpas alternativ på nästa angivna fil. Därför är ordning viktig och du kan ha samma alternativ på kommandoraden flera gånger. Varje förekomst tillämpas sedan på nästa in- eller utdatafil.
Kommentarer
- Tyvärr är detta fungerar inte. Att nämna att beställningen är viktig sparade mig dock mycket tid. Tack.
Svar
Detta är ett fel i VLC (som fortfarande finns i version 3.0.6). Efter några experiment insåg jag att VLC kraschar för videor med FPS mindre än 10 . Så alla videor med 10 FPS eller mer borde inte vara ett problem. Det finns för närvarande inget rent sätt att få en video med 1 FPS som kan spelas i VLC ( don ”t ge upp, fortsätt läsa ).
En lösning visas -som visas i svaret ovan- för att fejka effekten av 1 FPS genom att duplicera bilderna (när vi har faktiskt en FPS som är lika med 10 eller mer, vilket är ok för VLC).
Exempel: om du har en mapp med 12 bilder och vill skapa en video med 1 FPS (som kan spelas i VLC), måste du duplicera varje bild flera gånger (låt oss säga 10 gånger) och sedan berätta FFMPEG för att generera en 10 FPS-video. På detta sätt får vi en video med totalt 120 bilder, där varje bild spelas upp i 1 sekund (eftersom den dupliceras 10 gånger), vilket helt enkelt är en falsk för 1 FPS.
Jag föredrar att använder fps
-parametern snarare än
(vilket visas i ett annat svar) vilket i vissa fall kan vara problematiskt (enligt officiell dokumentation ).
ffmpeg -framerate 1 -i "img (%d).jpg" -c:v libvpx-vp9 -vf "fps=10,format=yuv420p" out.mkv
Eftersom ingången -framerate
är lägre än utdata fps
, FFMPEG duplicerar ramar för att nå önskad utmatningshastighet (vilket är 10 enligt kommandot ovan).
Det är också viktigt att märka att ordningen på -framerate
och -vf fps
är viktigt , eftersom denna konfiguration kommer att tillämpas på nästa nämnda video (in- eller utgång). Enligt officiella dokument :
alternativen tillämpas på nästa specificerade fil. Därför är ordning viktig …
ffmpeg
är smart nog att räkna ut videokodeken bara från filtillägget containerformat,.mp4
. Försök lägga till-vcodec libx264 -vpre hq
till kommandoraden, för att berätta kodec- och kodningsparametrarna.-r 1
.