Como criar um vídeo a partir de imagens usando o FFmpeg?

86

É possível usar ffmpegcriar um vídeo a partir de um conjunto de seqüências, onde o número não começa do zero?

Por exemplo, tenho algumas imagens [test_100.jpg, test_101.jpg, test_102.jpg, ..., test_200.jpg] e desejo convertê-las em um vídeo. Tentei o seguinte comando, mas não funcionou (parece que o número deve começar do zero):

ffmpeg -i test_% d.jpg -vcodec mpeg4 test.avi

Algum conselho?

JakeGould
fonte
Já faz um tempo desde que você perguntou isso, mas se você ainda está interessado na pergunta, a resposta é SIM - eu publiquei os detalhes e um exemplo abaixo: stackoverflow.com/a/12160155/181638
Assad Ebrahim
O @casperOne seria útil para ter uma idéia de por que isso está fora de tópico. Parece um problema de programação específico. A tag FFmpeg tem 3.7k seguidores, e com 27k vistas claramente as pessoas acham útil ..
geotheory
2
@geotheory As estatísticas da tag são irrelevantes. O ffmpeg é um programa muito parecido com o WinRar. Embora você possa programar nas bibliotecas do ffmpeg , essa pergunta não é sobre isso. O uso do ffmpeg na linha de comando deve ser solicitado no Superusuário , onde está o tópico.
casperOne

Respostas:

81

Não há necessidade de renomear arquivos se usar o -start_numbercomutador da seguinte maneira:

ffmpeg -start_number n -i test_%d.jpg -vcodec mpeg4 test.avi

onde né o início da sequência de fotos.

Observe que isso funcionará desde que a sequência seja ininterrupta quando for iniciada. Se houver lacunas e você desejar incluir todas as imagens estáticas, poderá ser necessário renumerar para preencher as lacunas.

Existem outras opções que você pode achar úteis.

Uso a seguinte linha para obter uma taxa de quadros mais lenta, compactar as imagens e obter um vídeo resultante menor:

ffmpeg.exe -f image2 -framerate 25 -pattern_type sequence -start_number 1234 -r 3 -i Imgp%04d.jpg -s 720x480 test.avi

A -r 3opção define a taxa de quadros do vídeo resultante como 3 quadros por segundo, para que eu possa ver cada um deles por um curto período de tempo. A -sopção redimensiona as imagens para a resolução desejada para gerenciar o tamanho do vídeo resultante.

(No shell do Windows, substitua -i Imgp%04d.jpgpor -i "Imgp%%04d.jpg". Crédito para Mike Fitzpatrick https://superuser.com/a/344178/153054 )

Assad Ebrahim
fonte
4
qual é a diferença entre -r e -framerate?
1
eles são o mesmo IIRC
rogerdpack
22
Não há necessidade de numerar bobagens, contanto que você esteja feliz em aceitar a ordem em que elas aparecem (digamos) 'ls' ... basta usar: ffmpeg -pattern_type glob -i '* .jpg' movie.mp4
Orwellophile
2
Existe alguma opção para controlar o intervalo de tempo entre as imagens, por exemplo, eu gostaria de mostrar a primeira imagem 13s, a segunda 15s, 24s para a terceira, o intervalo de tempo é definido pelo usuário, isso é possível?
zionpi 26/02
2
veja também trac.ffmpeg.org/wiki/…
david.libremone 20/04/16
38

você pode usar este trecho de código abaixo:

 cat *.jpg | ffmpeg -f image2pipe -r 1 -vcodec mjpeg -i - -vcodec libx264 out.mp4

fonte
Isso não gira JPGs para a rotação indicada nos metadados.
Erik Johansson
17

Você pode encontrar um exemplo de script na documentação do ffmpeg :

3.2 Como codifico imagens únicas em filmes?

Se você tiver um grande número de fotos para renomear, poderá usar o seguinte comando para aliviar a carga. O comando, usando a sintaxe bourne shell, vincula simbolicamente todos os arquivos no diretório atual que correspondem * jpg aos /tmp' directory in the sequence ofarquivos img001.jpg ', `img002.jpg' e assim por diante.

x=1; for i in *jpg; do counter=$(printf %03d $x); ln "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done

Então corra:

ffmpeg -f image2 -i /tmp/img%03d.jpg /tmp/a.mpg
gaizka
fonte
2
É melhor criar x = 0 para iniciar, de modo que o nome da imagem comece img000.jpg, pois é isso que o ffmpeg espera. Também o link simbólico não funcionou para mim, pois o ffmpeg não conseguiu encontrar os arquivos, então eu tive que usar o cp (velocidade óbvia e espaço, mas eu os recomendo depois). O mv também funcionaria se você não se importar em perder os originais.
Observe que nesta resposta, o comando fornecido cria links físicos, não links simbólicos. Quanto ao uso de cpse a vinculação não funcionar, se o seu sistema de arquivos suportar, cp --reflink=autoobterá uma velocidade / espaço muito melhores.
Félix Saparelli
12

Dos documentos de ffmpeg:

Usando um padrão glob

O ffmpeg também suporta globbing no estilo bash (* representa qualquer número de caracteres).

Isso é útil se suas imagens forem seqüenciais, mas não necessariamente em uma ordem numericamente sequencial, como nos exemplos anteriores.

ffmpeg -r 1 -pattern_type glob -i 'test_*.jpg' -c:v libx264 out.mp4

Portanto, desde que seus arquivos sejam classificados, o uso do -pattern_type globcomutador deve funcionar para você.

Nevin Williams
fonte
Observe que este glob é mais limitado que os globos comuns do shell: trac.ffmpeg.org/ticket/3620 aparentemente porque o tipo de imagem é deduzido da extensão.
Ciro Santilli resolveu
11

Até onde eu sei, você não pode iniciar a sequência em números aleatórios (não me lembro se você deve iniciá-la em 0 ou 1), além disso, ele não pode ter lacunas; caso isso ocorra, o ffmpeg assumirá que a sequência terminou e pare de adicionar mais imagens.

Além disso, conforme declarado nos comentários da minha resposta, lembre-se de que você precisa especificar a largura do seu índice. Gostar:

imagem% 03d.jpg

E se você usar um tipo de índice% 03d, precisará preencher seus nomes de arquivo com 0, como:

image001.jpg image002.jpg image003.jpg

etc.

Francisco Soto
fonte
1
Se os nomes dos arquivos de imagem tiverem zeros à esquerda, a sequência de formatação também deverá especificar a largura como "% 03d".
1
Se esse for o único obstáculo, você pode escrever um script para renomear ou vincular suas imagens a um conjunto adequadamente reindexado.
Cascabel
1
Sim, eu já trabalhei com isso antes, escrevi um wrapper em Ruby há algum tempo atrás, onde você chamava instance.addImage (), instance.processVideo () e ele criava um diretório temporal, copiava / renomeia as imagens com índices adequados e crie o vídeo. É bem fácil
@ Jeffefi eu criei um link simbólico, mas como faço para fornecer o caminho do arquivo de link simbólico para ffmpeg? Apenas assume que o arquivo de link simbólico é a imagem que estou tentando converter? Estou no win7 btw
A sequência pode começar de 0 a 4, inclusive.
Assad Ebrahim
5

Eu concordo com o Francisco, mas como solução alternativa, você pode simplesmente escrever um script rápido para mover ou criar links simbólicos para os arquivos com os números de sequência que o ffmpeg precisa. O script pode então chamar ffmpeg e remover os links ou mover os arquivos de volta aos seus locais originais.

Jason B
fonte
1

olho para cima

x=1; for i in *jpg; do counter=$(printf %03d $x); ln "$i"
/tmp/img"$counter".jpg; x=$(($x+1)); done

fonte
1

Sei que essa é uma pergunta antiga, mas me deparei com ela no Google, procurando a mesma resposta. Nenhuma das respostas aqui me satisfez completamente, então pesquisei e li mais, e esse é um comando que eu criei para o meu próprio problema.

cat {0032..1501}*.png | ffmpeg -f image2pipe -framerate 5 -i - -s 720x480 test2.avi

A razão pela qual eu usaria um comando como este é ...

  1. O gato e -f image2pipe oferecem controle mais preciso sobre as imagens que você usa. Por exemplo, ele permite que você use recursos do bash, como expansão de colchetes, e outros comandos, como grep, para ajustar seus resultados, se desejar.
  2. Menos opções para lembrar.
  3. Eu recomendo NÃO usar -r e apenas usar -framerate. Na minha experiência, -r tende a soltar quadros com mais frequência.
  4. Menos complexo, sem opções desnecessárias em uso e ele funcionará como está. Você pode adicionar mais complexidade (por exemplo, especificar o codificador) e ajustar para atender às suas necessidades.
David Bobb
fonte
Para a pergunta do OP, -start_numberé tudo o que é necessário.
Gyan
0

Eu usei o codificador flv desde que meu vídeo estava indo em um flash player (Jwplayer)

ffmpeg -i% d.jpg -vcodec flv test.flv


fonte
0

A partir da documentação , parece que você pode simplesmente usar *

For example, for creating a video from filenames matching the glob pattern foo-*.jpeg:

ffmpeg -f image2 -pattern_type glob -framerate 12 -i 'foo-*.jpeg' -s WxH foo.avi

Como uma observação, para melhorar a qualidade, as taxas / qps podem ser importantes (por exemplo, primeiro especificando a taxa de quadros muito baixa / alta e depois passar de um segundo filtro que normalizará o vídeo em câmera lenta?)

ntg
fonte
0

No meu caso, foi um pouco mais complicado por causa dos números nos arquivos. Veja como minhas imagens se parecem:

$ ls | head -5
2014_aq_unprocessed 001.jpg
2014_aq_unprocessed 002.jpg
2014_aq_unprocessed 003.jpg
2014_aq_unprocessed 004.jpg
2014_aq_unprocessed 005.jpg

e aqui está o comando que eu usei:

ffmpeg -i 2014_aq_unprocessed\ %3d.jpg  -vcodec mpeg4 test.avi
Mona Jalal
fonte
0

Você pode fazer isso com convert -morph:

convert *.jpg -delay 10 -morph 10 %05d.jpg

Se você quer usar ffmpeg, eu usei

ffmpeg -pattern_type glob -i '*.jpg' -vf "setpts=10*PTS" movie.mp4

onde 10*PTSdiz ao ffmpeg para abrandá-lo 10 vezes. Você também pode ter frações para acelerar.

Martin Thoma
fonte
Isso está apenas interpolando sua sequência de imagens original para um novo espaço, não cria um arquivo de vídeo como o OP pediu.
F0ster 18/03/16
0

-pattern_type glob exemplos concretos com áudio

Esta opção foi mencionada em: https://superuser.com/a/782520/128124, mas aqui estão alguns exemplos concretos de seu uso, incluindo a adição de áudio ao vídeo de saída.

Vídeo de apresentação de slides com uma imagem por segundo

ffmpeg -framerate 1 -pattern_type glob -i '*.png' \
  -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

Adicione um pouco de música, corte quando o áudio quando as imagens terminarem:

ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
  -c:a copy -shortest -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4

Aqui estão duas demos no YouTube:

Seja um hippie e use o formato de vídeo livre de patente Theora :

ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
  -c:a copy -shortest -c:v libtheora -r 30 -pix_fmt yuv420p out.ogg

Suas imagens devem, obviamente, ser classificadas em ordem alfabética, geralmente como:

0001-first-thing.jpg
0002-second-thing.jpg
0003-and-third.jpg

e assim por diante.

Consulte também: http://unix.stackexchange.com/questions/68770/converting-png-frames-to-video-at-1-fps/339399#339399

Vídeo em velocidade normal com uma imagem por quadro a 30 FPS

ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
  -c:v libx264 -pix_fmt yuv420p out.mp4

Aqui está o que parece:

GIF gerado com: https://askubuntu.com/questions/648603/how-to-create-an-animated-gif-from-mp4-video-via-command-line/837574#837574

Adicione um pouco de áudio a ele:

ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
  -i audio.ogg -c:a copy -shortest -c:v libx264 -pix_fmt yuv420p out.mp4

Resultado: https://www.youtube.com/watch?v=HG7c7lldhM4

Converta um arquivo de música em um vídeo com uma imagem fixa para upload do YouTube

Respondida em: Como converter MP3 para o formato de vídeo permitido pelo Youtube?

Obtenha algumas imagens de entrada de teste sintéticas

Estas são as imagens de teste que eu tenho usado nesta resposta:

wget -O opengl-rotating-triangle.zip https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.zip?raw=true
unzip opengl-rotating-triangle.zip
cd opengl-rotating-triangle
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/7/74/Alnitaque_%26_Moon_Shot_-_EURO_%28Extended_Mix%29.ogg

Imagens geradas com: https://stackoverflow.com/questions/3191978/how-to-use-glut-opengl-to-render-to-a-file/14324292#14324292

É legal observar o quanto o vídeo compacta a sequência de imagens muito melhor do que o ZIP, pois é capaz de comprimir quadros através de algoritmos especializados:

  • opengl-rotating-triangle.mp4: 340K
  • opengl-rotating-triangle.zip: 7.3M

Sobre as opções da CLI

Observe no entanto que, apesar do nome, -globisso não é tão geral quanto os padrões do shell Glob, por exemplo: -i '*'falha: https://trac.ffmpeg.org/ticket/3620 (aparentemente porque o tipo de arquivo é deduzido da extensão).

-r 30faz o -framerate 1vídeo 30 FPS para superar bugs em players como o VLC para taxas de quadros baixas: https://stackoverflow.com/questions/19267443/playback-issues-in-vlc-with-low-fps-video-from-images-using- ffmpeg / 41797724 # 41797724 Portanto, repete cada quadro 30 vezes para manter o efeito de 1 imagem por segundo desejado.

Próximos passos

Você também vai querer:

TODO: aprenda a cortar e concatenar vários arquivos de áudio no vídeo na linha de comando:

Testado em

ffmpeg 3.4.4, vlc 3.0.3, Ubuntu 18.04.

Bibliografia

Ciro Santilli adicionou uma nova foto
fonte