Pregunta Combina una imagen + un archivo de audio para hacer un video usando FFmpeg


Esto debería ser bastante trivial, pero no puedo encontrar la manera de hacerlo funcionar.

Quiero que FFmpeg tome una imagen JPEG y un archivo de audio como entrada y genere un archivo de video de la misma duración que el archivo de audio (estirando la imagen fija durante toda la duración).

No me importa mucho qué códec de video se utiliza para la salida, pero es vital que pueda usar "copiar" como el códec de audio (es decir, copiar el flujo de audio sin transcodificarlo).

¿Cuál es la línea de comando correcta que haría eso?

Lo intenté:

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

e intenté muchas combinaciones con y sin -s 640x360, -loop_input, -shortest, -t xxx, -r 0.1 (tasa de cuadros artificialmente baja con la esperanza de que el video sea más largo) y -f image2

O recibo errores o recibo un archivo de video de la duración de un fotograma.

Busqué en Google y encontré una docena de soluciones propuestas (supuestamente para esta misma pregunta), ninguna funciona.

¿Alguien puede sugerir un comando de trabajo y explicar la razón detrás de esto?


151


origen


Acabo de probar tu línea de comandos y funcionó como se esperaba. Su problema podría estar en el formato de sonido. ¿La transcodificación del sonido funciona? - Captain Giraffe
Por "como se esperaba", ¿quiere decir que el video resultante tiene la misma duración que la entrada de audio? ¿Lo has jugado? ¿No es de un solo cuadro? - matteo
El formato de sonido no es el problema, la transcodificación del sonido funciona - matteo
También tuve un pedido de params y ¡me costó horas! Lástima que este tipo de problemas no están cubiertos en la ayuda. gregoire.org/2009/12/05/fun-with-ffmpeg - Paul Gregoire
esto es mejor que la respuesta elegida, experimenté y es rápido y el tamaño del archivo es pequeño ...ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.avi - Muhammad Umer


Respuestas:


El orden de las opciones en la línea de comando importa. Lo siguiente funciona para mi caso:

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

En un caso más general, donde image.jpg y audio.wav son su entrada, puede usar el siguiente comando, adaptado de el wiki de 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

Esto usaría el libx264 codificador y le proporciona una mejor compresión que el códec MJPEG utilizado anteriormente. El audio es AAC, con el built-in ffmpeg Codificador AAC.


117



¿Cómo es que los archivos terminan mucho más grandes que [tamaño de la imagen] + [tamaño del archivo de audio]? ¿Esperaría que la compresión de video se volviera loca con un marco constante? - Alec Jacobson
Depende del códec de video que use. Si está copiando los comandos en mis ejemplos, estoy usando mjpeg como el códec, que comprime cada fotograma por separado, por lo que no aprovecha el hecho de que todos los fotogramas son iguales. Además, creo que incluso otros códecs recodificarían todo el fotograma de vez en cuando, es decir, cada N-ésimo fotograma, por lo que obtendría un archivo mucho más pequeño, pero aún mucho más grande que el tamaño del sonido de imagen +. Lo hacen porque (a) de lo contrario, el decodificador tendría que leer todo el archivo desde el principio, incluso si solo quiere saltar al último cuadro, y - matteo
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. - wim
Esta respuesta está siendo actualmente discutido en meta - DavidPostill♦
@matteo haz clic en "editar" debajo de la respuesta, y en la esquina inferior derecha aparecerá un botón con la etiqueta "comunidad cualquiera" y podrás alternar y guardar - TankorSmash


Lo estás haciendo camino Más fuerte de lo que tiene que ser. FFmpeg es mucho más inteligente de lo que crees: sabe que quieres que el video tenga la misma duración que tu pista de audio.

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

pause

Los únicos atributos tú tener para especificar son los input filenames, el output codecs, y el output filename (cual eo ipso incluye el output container,).

Por supuesto, tiene sentido comenzar con una imagen fija que comparte las mismas dimensiones que su video eventual; Si está usando un editor de imágenes dedicado en lugar de especificar las dimensiones de salida para que FFmpeg se encuentre, necesita asegúrese de que sus dimensiones de entrada sean números pares.

El tamaño de salida es uno de los complejos más comunes de FFmpeg; algunos códecs son más restringidos en las dimensiones de salida que otros, pero ninguna salida puede tener atributos de altura o ancho de número impar.

los pause mando al final del archivo de proceso por lotes mantiene abierta la CLI, la La mejor manera de depurar su línea de comando es leyendo los mensajes de error genera Son extremadamente específicos, y la mejor documentación que tiene FFmpeg, pero el trabajo duro de los desarrolladores se desperdicia si permite que la ventana se cierre antes de poder leerlos.

El shell del comando tiene un interruptor cmd /k que mantiene una ventana abierta donde puede ejecutar las mismas instrucciones de su secuencia de comandos por lotes en el símbolo del sistema.

FFmpeg y avconv ambos te harán usar -c:apara -acodec y -c:vpara -vcodec eventualmente, pero las viejas instrucciones funcionan bien en las compilaciones que uso.

Nota Bene: Cada commit tiene idiosincracias. Si su línea de comando está fallando sin razón aparente, a menudo es útil probar otra compilación, o seguir el tenedor a libav, donde los desarrolladores más activos de FFmpeg han estado durante los últimos años. Su herramienta de transcodificación ha cambiado de nombre avconv pero sus archivos por lotes deberían funcionar con cualquiera de ellos.


32



Debo estar usando una versión diferente a la suya (si ha probado su comando y funciona como usted lo describe), porque, como ya mencioné en la pregunta, ya había intentado con su mismo comando y obtuve un video de la duración de 1 fotograma (una fracción de segundo), NO la duración del archivo de audio. Esperaba que fuera inteligente, pero (en mi versión) resultó ser no. - matteo
Hola MatteoSí, ejecuté ese código, y sí, funciona según lo anunciado. Estoy seguro de que hay un montón de imbéciles que serían tan descuidados como para hacer tales afirmaciones sin probarlas, así que trataré de no ofenderme :) En una publicación completa a continuación, proporcionaré enlaces de Pastebin a la salida de la consola FFmpeg y MediaInfo datos en archivos de entrada y archivo de salida final. Mis archivos de entrada, mi archivo por lotes, mi archivo de salida están en GoogleDrive donde están libremente descargable, si desea probarlos contra su compilación FFmpeg.
@ShinMuraoka Mine is a win-64 ffmpeg build compiled on: Jan 6 2013, at: 16:16:53 Ni su solución ni la solución @matteo funcionaron para mí. Además, descargué sus archivos de Google Drive, pero no dio el resultado esperado (el archivo de salida era negro y solo contenía audio). Por favor, ayúdame a encontrar el comando correcto para ser utilizado. - coding_idiot
"ninguna salida puede tener atributos de alto o ancho de número impar" No es verdadero. Establezca pix_fmt en algo que no tenga submuestreo de crominancia, como rgb24 o yuv444p, luego asegúrese de que el códec y el contenedor lo admiten y no tienen más restricciones. Con respecto a pix_fmt, FFmpeg es menos que inteligente; asume yuv420p (que tiene submuestreo de crominancia) a menos que le indique lo contrario. - Jonathan Baldwin
¿Qué hay de las imágenes múltiples? Necesito que la imagen cambie en algún momento específico a otra imagen. Me gustaría poder especificarlos en la línea de comando con un parámetro de tiempo para cada uno.


Aún más fácil:

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

FFmpeg intentará elegir el mejor códec automáticamente, dependiendo de la extensión de su archivo de salida.

Actualización: Noté que YouTube tiene dificultades para procesar el video (se bloquea al 95%), porque creo que solo hay un fotograma. La solución que encontré para hacer feliz a YouTube: agregar más marcos. Además, agregué-acodec copy para preservar la calidad del audio Necesitas -shortest o se repite para siempre (Se detiene al final del flujo más corto, que es el audio, porque el ciclo de la imagen es infinito). El orden de sus opciones es muy importante para la velocidad, ya que los filtros (y similares) se procesan en el orden que usted especifique. Si cambia el orden de estos parámetros, los resultados son dramáticamente diferentes. 

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

También tenga en cuenta que configuro la velocidad de cuadros dos veces, eso no es un accidente: la primera velocidad de cuadro es para la entrada, la segunda es para la salida. Si haces esto correctamente, solo debería haber un fotograma por segundo de video, lo que significa que codifica relativamente rápido. También establecí la resolución en 720p aquí, lo que significa que debe obtener audio HD en YouTube :-)


28



También es posible que su archivo de audio no sea compatible con su contenedor .flv. En ese caso, solo debe intentar con un contenedor diferente (de salida), como .webm, .avi o el formato que sea, hasta que encuentre un formato de contenedor que sea compatible con su archivo de audio. - PJ Brunet
Usé esto para .JPG y .MP3 para hacer un MP4 - funcionó perfectamente. El FLV que creé a partir de JPG / MP3 no parecía funcionar, lo cual puede ser de acuerdo con la advertencia de comentarios anterior.
La versión actualizada funciona, para Youtube. Pensé que estaba estancado al 95% pero finalmente funcionó. - Basj
tengo esto: 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) ... esto funciona: ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:-2 video.mp4 - NineCattoRules
¿Qué hay de las imágenes múltiples? Necesito que la imagen cambie en algún momento específico a otra imagen. Me gustaría poder especificarlos en la línea de comando con un parámetro de tiempo para cada uno.


La versión que funcionó para mí:

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

Verifica la opción -shortest debe estar en frente del archivo de salida si no aparece el siguiente error:

La opción más corta (finalizar la codificación dentro de la entrada más corta) no se puede aplicar al archivo de entrada pic.jpg; está intentando aplicar una opción de entrada a un archivo de salida o viceversa. Mueva esta opción antes del archivo al que pertenece. Error al analizar las opciones para el archivo de entrada pic.jpg.


13



Gracias por esto. La mayoría de las otras respuestas no me funcionaron (usando ffmpeg en Alpine linux). Esta respuesta tiene el comando más corto que funcionó perfectamente para mí. - DannyB


Desde la página de manual de ffmpeg:

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

Como descubriste, las opciones de infile deben venir antes del infile al que se aplican.

Sin embargo, esto no es un error, solo es un mecanismo por el cual se puede especificar a qué argumentos de infile se aplican.


7



¿Qué hay de las imágenes múltiples? Necesito que la imagen cambie en algún momento específico a otra imagen. Me gustaría poder especificarlos en la línea de comando con un parámetro de tiempo para cada uno.


Esto funcionó para mí

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

Encontré vcodec libx264 creado archivos mucho más pequeños que mpjeg (10 MB en lugar de 100 MB).


4



-shortest es una opción de salida y puede ser ignorada como una opción de entrada mientras la está usando. - LordNeckbeard


Estaba tratando de hacer lo @matteo, pero sin el audio, y @Colonel PanicLa solución funcionó mejor:

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

Solo tuve que agregar un argumento de duración en segundos (-t 10)


1



-shortest es una opción de salida, pero la está usando como una opción de entrada. Moverlo antes del archivo de salida y puede eliminar el -t 10, pero entonces tu respuesta será más o menos la misma que las demás. - LordNeckbeard


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


0



¿Puedes explicar cómo funciona el comando que agregaste? - neelsg
Esta respuesta no es muy diferente a las otras simples "respuestas de comentario" aquí. - LordNeckbeard


En caso de que alguien quiera convertirlos por lotes, intente esto.

Puede configurar la carpeta de entrada y salida, y también el formato en el que desea que esté el video. En este caso, lo configuré en AVI.

Esta respuesta Combina una imagen + un archivo de audio para hacer un video usando FFmpeg me ayudo mucho.

 @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

0