ffmpeg -pattern_type glob - não carregando arquivos na ordem correta

4

Eu tenho um dilema .. Eu já tinha um roteiro há algum tempo, que baixa fotos de uma webcam a cada poucos minutos. A convenção de nomenclatura só faz new_image((len(files(dir))+1) + '.jpg') e está tudo bem .. até hoje ..

Eu tive um script Python que carrega as imagens com base na data de criação e as renderiza e eu pego os dados do OpenGL e os despejo em um filme, o que não é difícil e está tudo ok .. Exceto agora eu tenho alguns milhares de imagens e é bastante ineficaz para continuar sobre isso dessa maneira (mesmo tho é legal porque eu posso construir meu próprio GUI e sobreposição etc) .. de qualquer maneira, eu estou usando ffmpeg para combinar as imagens em um slideshow, assim:

ffmpeg -f image2 -r 25 -pattern_type glob -i '*.jpg' -qscale 3 -s 1920x1080 -c:v wmv1 video.wmv

O ffmpeg funciona bem, exceto pelo fato de -pattern_type glob ter as imagens em ordem de nomenclatura que não funcionam porque a maneira como os arquivos são alimentados é semelhante, se não a mesma, como ls , que se parece com:

user@host:/storage/photos$ ls
0.jpg     1362.jpg  1724.jpg  2086.jpg  2448.jpg  280.jpg   3171.jpg  3533.jpg  3896.jpg  4257.jpg  4619.jpg  4981.jpg  5342.jpg  5704.jpg  6066.jpg  650.jpg
1000.jpg  1363.jpg  1725.jpg  2087.jpg  2449.jpg  2810.jpg  3172.jpg  3534.jpg  3897.jpg  4258.jpg  461.jpg   4982.jpg  5343.jpg  5705.jpg  6067.jpg  651.jpg

0, 1000, 1, 2000, 2 ... essa é a lógica de ls , então a sequência da imagem (timelapse) será toda refeita ..

Alguma idéia de como usar o ffmpeg para carregar as imagens de maneira mais ordenada?

    
por Torxed 24.05.2013 / 22:56

3 respostas

3

ffmpeg concatem os mesmos tipos de arquivo

Você pode usar um comando como este para concatenar a lista de arquivos da maneira que quiser:

ffmpeg -f concat -i <( for f in *.wav; do echo "file '$(pwd)/$f'"; done ) \
         output.wav

Os itens acima só podem funcionar se os arquivos que você está concatenando forem todos os mesmos codecs. Então todos eles teriam que ser .wav ou .mpg por exemplo.

OBSERVAÇÃO: você precisa ter o ffmpeg v1.1 ou superior para usar o demuxer de concat, você pode ler mais sobre o exemplo acima e também como concatenar codecs diferentes usando esta técnica no site ffmpeg .

ffmpeg usando formatadores printf

O Ffmpeg também pode receber informações usando os formatadores printf, como %d . Isso corresponde a dígitos começando em 0 e indo de lá em ordem. Se os números fossem estruturados assim, 000 - 099, você poderia usar este formatador, %03d , que significa uma série de 3 dígitos, zero preenchido.

Então você poderia fazer algo assim:

ffmpeg -r 25 -i %d.png -qscale 3 -s 1920x1080 -c:v wmv1 video.wmv

O acima não funcionou bem para mim, ffmpeg estava reclamando sobre a opção -c:v . Eu simplesmente omiti essa opção e esta versão do comando funcionou como esperado.

ffmpeg -r 25 -i %d.png -qscale 3 -s 1920x1080 video.wmv
    
por 25.05.2013 / 01:01
4

A maneira mais simples seria renomear o nome do arquivo curto para ter zeros à esquerda, usando a ferramenta rename . No entanto, existem duas ferramentas de renomeação padrão - a que estou descrevendo é descrita pelo Guia de Referência de Programadores Perl na página man. Esta é a versão no Debian e distribuições derivadas.

rename 's/^/000/' [0-9].jpg
rename 's/^/00/' [0-9][0-9].jpg
rename 's/^/0/' [0-9][0-9][0-9].jpg

Os nomes dos arquivos devem então agrupar corretamente usando globs.

No entanto, se você não quiser renomear os arquivos, não poderá usar globs, como a expansão em ordem lexicográfica, não numérica.

Então, não use globs. Livre-se de -pattern_type glob e use -i %d.jpg em vez de -i *.jpg . Isso usa um padrão numérico e no meu teste rápido faz o que você quer.

    
por 25.05.2013 / 01:00
0

A melhor maneira é renomear o arquivo para que todos tenham o mesmo número de dígitos. Com zsh ( 4 é o número máximo de dígitos):

autoload zmv     # put this in your ~/.zshrc
zmv '(<->).jpg' '${(l:4::0:)1}.jpg'

Com outros shells (continue e adicione 0 , se necessário, se houver nomes de arquivo com mais de 4 dígitos):

for x in [0-9].jpg; do mv "$x" "000$x"; done
for x in [0-9][0-9].jpg; do mv "$x" "00$x"; done
for x in [0-9][0-9][0-9].jpg; do mv "$x" "0$x"; done

Se você não pode renomear os arquivos, outra opção é criar links simbólicos em algum outro diretório. Com zsh:

zmv -Ls '$PWD/(<->).jpg' '/somewhere/writable/${(l:4::0:)1}.jpg'

Com qualquer shell:

for x in [0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/000$x"; done
for x in [0-9][0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/00$x"; done
for x in [0-9][0-9][0-9].jpg; do ln -s "$PWD/$x" "/somewhere/writable/0$x"; done

Uma abordagem alternativa é fornecer aos números simbólicos links consecutivos. Essa abordagem generaliza para outras situações em que a ordem dos arquivos originais não está correta, desde que você crie os links simbólicos na ordem desejada. Iniciar o contador em 10000 e remover o% principal1 é uma maneira conveniente de obter um contador com zeros à esquerda.

i=10000
for x in [0-9].jpg [0-9][0-9].jpg [0-9][0-9][0-9].jpg; do
  ln -s "$PWD/$x" /somewhere/writable/${i#1}.jpg
  i=$((i+1))
done

Se você realmente não quer escrever, você pode passar sucessivas opções de -i com o aumento da duração dos nomes dos arquivos.

ffmpeg -pattern_type glob -i '[0-9].jpg' -i '[1-9][0-9].jpg' -i '[1-9][0-9][0-9].jpg' -i '[1-9][0-9][0-9][0-9].jpg' …
    
por 26.05.2013 / 01:23