Combina un'immagine + un file audio per creare un video usando FFmpeg


184

Questo dovrebbe essere piuttosto banale, ma non riesco a trovare un modo per farlo funzionare.

Voglio che FFmpeg acquisisca un'immagine JPEG e un file audio come input e generi un file video della stessa durata del file audio (allungando l'immagine fissa per l'intera durata).

Non mi interessa molto di quale codec video viene utilizzato per l'output, ma è fondamentale poter usare "copia" come codec audio (ovvero copiare il flusso audio senza transcodificarlo).

Qual è la riga di comando giusta che lo farebbe?

Provai:

ffmpeg -i image8.jpg -i sound11.amr -acodec copy test.avi

e provato molte combinazioni con e senza -s 640x360, -loop_input, -shortest, -t xxx, -r 0.1(rate artificialmente basso fotogramma nella speranza che il video sarebbe più lungo) e-f image2

O ottengo errori o ottengo un file video della durata di un fotogramma.

Ho cercato su Google e ho trovato una dozzina di soluzioni proposte (presumibilmente a questa stessa domanda) nessuna delle quali funziona.

Qualcuno può suggerire un comando funzionante e spiegare la logica alla base?


Ho appena provato la tua riga di comando e ha funzionato come previsto. Il tuo problema potrebbe risiedere nel formato audio. La transcodifica del suono funziona?
Capitan Giraffe

Per "come previsto" intendi che il video risultante ha la stessa durata dell'ingresso audio? Ci hai giocato? Non è lungo un fotogramma?
matteo,

Il formato audio non è il problema, transcodificare il suono funziona
Matteo

Ho avuto anche un problema con i parametri e mi è costato ore! Peccato che questo tipo di problemi non siano coperti dall'aiuto. gregoire.org/2009/12/05/fun-with-ffmpeg
Paul Gregoire,

3
questa è meglio della risposta scelta, ho sperimentato ed è veloce e la dimensione del file è piccola ..ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.avi
Muhammad Umer

Risposte:


146

L'ordine delle opzioni nella riga di comando è importante. Quanto segue funziona per il mio caso:

ffmpeg -loop 1 -y -i image8.jpg -i sound11.amr -shortest -acodec copy -vcodec mjpeg result.avi

In un caso più generale, dove image.jpge audio.wavsono i tuoi input, puoi usare il seguente comando, adattato dal wiki di FFmpeg :

ffmpeg -loop 1 -i image.jpg -i audio.wav -c:v libx264 -tune stillimage -c:a aac -b:a 192k -pix_fmt yuv420p -shortest out.mp4

Questo userebbe l' libx264encoder e ti fornirebbe una compressione migliore rispetto al codec MJPEG usato sopra. L'audio è AAC, con l' ffmpegencoder AAC incorporato .


5
Come mai i file finiscono per essere molto più grandi di [dimensione dell'immagine] + [dimensione del file audio]? Mi aspetto che la compressione video impazzisca con un frame costante?
Alec Jacobson,

2
Dipende dal codec video che usi. Se stai copiando i comandi nei miei esempi, sto usando mjpeg come codec, che comprime ciascun frame separatamente, quindi non sfrutta il fatto che tutti i frame sono uguali. Inoltre, penso che anche altri codec ricodifichino l'intero fotogramma ogni tanto, ovvero ogni fotogramma N-esimo, in modo da ottenere un file molto più piccolo ma comunque molto più grande della dimensione dell'immagine + del suono. Lo fanno perché (a) altrimenti il ​​decodificatore avrebbe bisogno di leggere l'intero file dall'inizio anche se si desidera saltare all'ultimo fotogramma e
matteo,

2
Option shortest (finish encoding within shortest input) cannot be applied to input file image.jpg -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
mercoledì

2
usare ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.aviquesto funziona meglio !!!?! ??!?!
Muhammad Umer,

2
Questa risposta è attualmente in discussione su meta.
David Post

41

Si sta facendo strada più difficile di quanto non lo deve essere. FFmpeg è molto più intelligente di quanto tu gli accrediti - sa che vuoi che il video abbia la stessa lunghezza della tua traccia audio.

ffmpeg -i still.png -i narrate.wav -acodec libvo_aacenc -vcodec libx264 final.flv

pause

Gli unici attributi che si dovete specificare sono il input filenames, il output codecse il output filename(che eo ipso include il output container,).

Naturalmente, ha senso iniziare con un'immagine fissa che condivide le stesse dimensioni del tuo video finale; se stai utilizzando un editor di immagini dedicato invece di specificare le dimensioni di output affinché FFmpeg sia conforme, devi assicurarti che le dimensioni di input siano numeri pari .

La dimensione dell'output è uno dei riattaccamenti più comuni di FFmpeg; alcuni codec sono più limitati nelle dimensioni di output rispetto ad altri, ma nessun output può avere attributi di numero dispari in altezza o larghezza.

Il pausecomando alla fine del file batch mantiene aperta la CLI: il modo migliore per eseguire il debug della riga di comando è leggere i messaggi di errore che genera. Sono estremamente specifici - e la migliore documentazione di FFmpeg - ma il duro lavoro degli sviluppatori è sprecato se si consente alla finestra di chiudersi prima di poterle leggere.

La shell dei comandi ha un'opzione cmd /kche mantiene una finestra aperta in cui è possibile eseguire le stesse istruzioni dallo script batch al prompt dei comandi.

FFmpeg e avconv ti faranno utilizzare -c:aper -acodece -c:valla -vcodecfine, ma le vecchie istruzioni funzionano bene nelle build che uso.

Nota Bene: ogni commit ha idiosincrasie. Se la tua riga di comando non funziona senza una ragione apparente, è spesso utile provare un'altra build o seguire il fork su libav , dove gli sviluppatori più attivi di FFmpeg sono stati negli ultimi due anni. Il loro strumento di transcodifica è stato rinominato avconv ma i file batch dovrebbero funzionare con uno dei due.


Devo usare una versione diversa dalla tua (se hai provato il tuo comando e funziona come descrivi), perché, come ho già detto nella domanda, avevo già provato il tuo stesso identico comando e ricevo un video della durata di 1 fotogramma (una frazione di secondo), NON la durata del file audio. Mi aspettavo che fosse intelligente, ma (nella mia versione) non si è rivelato.
matteo,

2
Ehi Matteo , sì, ho eseguito quel codice e sì, funziona come pubblicizzato. Sono sicuro che ci sono un sacco di mezzi testardi che sarebbero così incuranti da presentare tali affermazioni senza testarli, quindi cercherò di non essere offeso :) In un post completo di seguito fornirò i collegamenti Pastebin all'output della console FFmpeg e MediaInfo dati su file di input e file di output finale. I miei file di input, il mio file batch, il mio file di output sono su un Google Drive dove sono liberamente scaricabili , se si desidera testarli con la build di FFmpeg.

@ShinMuraoka Mine is a win-64 ffmpeg build compiled on: Jan 6 2013, at: 16:16:53Né la tua soluzione né la soluzione @matteo hanno funzionato per me. Inoltre, ho scaricato i tuoi file da Google Drive, ma non ha prodotto l'output previsto (il file di output era nero e conteneva solo l'audio). Ti prego, aiutami a capire il comando giusto da usare.
coding_idiot

2
"nessun output può avere attributi di altezza o larghezza di numero dispari" Non vero. Imposta pix_fmt su qualcosa che non ha il sottocampionamento di chroma, come rgb24 o yuv444p, quindi assicurati che il codec e il contenitore lo supportino e non abbiano ulteriori restrizioni. Per quanto riguarda pix_fmt, FFmpeg è tutt'altro che intelligente; assume yuv420p (che ha un sottocampionamento cromatico) a meno che non lo dica diversamente.
Jonathan Baldwin,

che dire di più immagini? Ho bisogno che l'immagine cambi in un determinato momento in un'altra immagine. Vorrei poterli specificare sulla riga di comando con un parametro time per ognuno.

36

Ancora più semplice:

ffmpeg -i ep1.png -i ep1.wav ep1.flv

FFmpeg proverà a scegliere automaticamente il miglior codec, a seconda dell'estensione del file di output.

Aggiornamento: ho notato che YouTube ha difficoltà a elaborare il video (si blocca al 95%) Penso che ci sia solo un fotogramma. La soluzione che ho trovato per rendere felice YouTube: aggiungere più frame. Inoltre, ho aggiunto -acodec copyper preservare la qualità audio. Hai bisogno -shortesto si avvolge per sempre. (Si interrompe alla fine del flusso più breve, che è l'audio, perché il loop di immagini è infinito.) L'ordine delle opzioni è molto importante per la velocità, poiché i filtri (e simili) vengono elaborati nell'ordine specificato. Se si modifica l'ordine di questi parametri, i risultati sono notevolmente diversi.

ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:720 ep1.flv

Nota anche che ho impostato il frame rate due volte, non è un caso: il primo frame rate è per l'input, il secondo è per l'output. Se lo fai correttamente, dovrebbe esserci solo un fotogramma al secondo del video, il che significa che codifica relativamente velocemente. Inoltre ho impostato la risoluzione su 720p qui, il che significa che dovresti ottenere audio HD su YouTube :-)


Inoltre è possibile che il tuo file audio non sia compatibile con il tuo contenitore .flv. In tal caso, dovresti semplicemente provare un altro contenitore (output), come .webm, .avi o qualsiasi altro formato, fino a trovare un formato contenitore compatibile con il tuo file audio.
PJ Brunet,

1
Utilizzato questo per un .JPG e .MP3 per fare un MP4 - ha funzionato perfettamente. Il FLV che ho creato da JPG / MP3 non sembra funzionare, il che potrebbe essere come da avviso dei commenti precedenti.

2
La versione aggiornata funziona, per Youtube. Ho pensato che fosse bloccato al 95% ma alla fine ha funzionato.
Basj,

ottenuto questo: No pixel format specified, yuvj420p for H.264 encoding chosen. Use -pix_fmt yuv420p for compatibility with outdated media players. [libx264 @ 0x2b5c940] height not divisible by 2 (700x457)... funziona:ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:-2 video.mp4
NineCattoRules

che dire di più immagini? Ho bisogno che l'immagine cambi in un determinato momento in un'altra immagine. Vorrei poterli specificare sulla riga di comando con un parametro time per ognuno.

14

La versione che ha funzionato per me:

 ffmpeg -loop 1 -y -i pic.jpg -i sound.amr -shortest video.mp4

Verifica l'opzione -shortestdeve essere davanti al file di output, in caso contrario ottengo l'errore di seguito:

L'opzione più breve (finitura della codifica all'interno dell'input più breve) non può essere applicata al file di input pic.jpg: si sta tentando di applicare un'opzione di input a un file di output o viceversa. Sposta questa opzione prima del file a cui appartiene. Errore durante l'analisi delle opzioni per il file di input pic.jpg.


Grazie per questo. La maggior parte delle altre risposte non ha funzionato per me (usando ffmpeg su Alpine Linux). Questa risposta ha il comando più breve che ha funzionato perfettamente per me.
DannyB,

8

Dalla manpage di ffmpeg:

ffmpeg [[infile options][-i infile]]... {[outfile options] outfile}...

Come hai scoperto, le opzioni di infile devono precedere l'infile a cui si applicano.

Questo non è un bug, tuttavia, è solo un meccanismo attraverso il quale è possibile specificare a quali argomenti di infile applicare.


che dire di più immagini? Ho bisogno che l'immagine cambi in un determinato momento in un'altra immagine. Vorrei poterli specificare sulla riga di comando con un parametro time per ognuno.

4

Questo ha funzionato per me

ffmpeg -loop 1 -shortest -y -i image.jpg -i audio.mp3 -acodec copy -vcodec libx264 video.avi

Ho scoperto che vcodec ha libx264creato file molto più piccoli di mpjeg(10 MB anziché 100 MB).


1
-shortestè un'opzione di output e può essere ignorata come opzione di input mentre la si utilizza.
Llogan,

1

Stavo cercando di fare come @matteo , ma senza l'audio, e la soluzione di @Colonel Panic ha funzionato meglio:

ffmpeg -loop 1 -shortest -y -i still.png -vcodec libx264 -t 10 video.avi

Ho dovuto solo aggiungere un argomento di durata in secondi ( -t 10).


-shortestè un'opzione di output, ma la stai utilizzando come opzione di input. Spostalo prima del file di output e puoi eliminarlo -t 10, ma la tua risposta sarà praticamente la stessa degli altri.
Llogan,

0

ffmpeg -loop 1 -i img.jpg -i audio.wav -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest out.mp4


5
Puoi spiegare come funziona il comando che hai aggiunto?
Neelsg,

Questa risposta non è molto diversa dalle altre semplici "risposte ai commenti" qui.
Llogan,

0

Nel caso qualcuno voglia convertirli in batch, prova questo.

È possibile impostare la cartella di input e output e anche il formato in cui si desidera inserire il video. In questo caso, l'ho impostato su AVI.

Questa risposta Combina un'immagine + un file audio per creare un video usando FFmpeg mi ha aiutato molto.

 @echo off
 set "sourcedir=C:\Users\CodeHard\Desktop\BOX\Newfolder"  
 set "outputdir=C:\Users\CodeHard\Desktop\BOX\Converted" 

 PUSHD "%sourcedir%"

 for %%F in (*.mp3) DO ffmpeg -r 1 -loop 1 -i abc.jpeg -i "%%F" -acodec copy -r 1 -shortest -vf scale=1280:720 "%outputdir%\%%F.avi"  

 POPD

-1

Prova questo comando. Ha funzionato per me.

-y -i /storage/emulated/0/images.jpg -i /storage/emulated/0/audio.wav -acodec aac -vcodec mpeg4 -s 480*320 -f mp4 -r 2 /storage/emulated/0/output.mp4"

2
Questo è un comando incompleto che potrebbe non funzionare. Anche se posso correggere ed eseguire il debug dei tuoi comandi, non farò il tuo lavoro per te, quindi per favore modifica la tua risposta e correggila tu stesso. Ho anche notato che la dimensione del tuo video non è ciò che voleva Matteo.
karel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.