Se você tem ciclos de CPU de sobra, pode extrair de vários vídeos em paralelo:parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Ole Tange
Respostas:
156
Se a etapa de codificação JPEG exigir muito desempenho, você sempre poderá armazenar os quadros descompactados como imagens BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Isso também tem a vantagem de não incorrer em mais perda de qualidade por meio da quantização por transcodificação para JPEG. (PNG também não tem perdas, mas tende a demorar muito mais do que JPEG para codificar.)
Isso resulta em muitas quedas de quadros na minha máquina. Posso dizer ao ffmpeg para renderizar tudo?
Evi1M4chine
45
@ Evi1M4chine basta remover o parâmetro -r para extrair todos os frames
studioj
14
Eu gostaria de acrescentar que, embora JPEG não seja realmente difícil para a CPU, os bitmaps descompactados são realmente difíceis para o armazenamento, então duvido que você obtenha uma taxa de transferência maior com BMP em comparação com JPEG.
Marcus Müller,
4
Para extrair todos os frames:ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
Encontrei esta questão, então aqui está uma comparação rápida Compare essas duas maneiras diferentes de extrair um quadro por minuto de um vídeo de 38m07s:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029s
Isso leva muito tempo porque o ffmpeg analisa todo o arquivo de vídeo para obter os quadros desejados.
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0m4.689s
Isso é cerca de 20 vezes mais rápido. Usamos a busca rápida para ir ao índice de tempo desejado e extrair um quadro, então chamamos ffmpeg várias vezes para cada índice de tempo. Observe que este -accurate_seeké o padrão
e certifique-se de adicionar -ssantes da -iopção de entrada de vídeo .
bcnão é um pacote nativo Ubuntu, em vez pode-se usar bash: let "i = $i * 60". BTW - excelente ideia
gilad mayani
3
Boa dica adicionando -ssantes -i. Caso contrário, todo o vídeo será decodificado e os frames desnecessários serão descartados
MoustafaAAtta
2
Por ser o top do google, gostaria de ressaltar que em 2018 ainda é uma abordagem que rende dividendos. O melhor resultado parece estar executando um ffmpegpor núcleo do seu host - o que (para bmp) produz melhorias quase lineares na velocidade (até que você encontre algum outro gargalo, como o disco).
Knetic,
Essa deve ser a resposta aceita, já que a pergunta é sobre o 'caminho mais rápido'. Obviamente, você precisa saber a variável de saída para o 'for loop' usando ffprobe, que eu acho que ainda é mais rápido em comparação com os outros métodos.
iamprem
9
Se você sabe exatamente quais frames extrair, por exemplo, 1, 200, 400, 600, 800, 1000, tente usar:
Estou usando isso com um tubo para a montagem de Imagemagick para obter uma visualização de 10 quadros de todos os vídeos. Obviamente, os números dos quadros que você precisa descobrir usandoffprobe
Estou tentando ffmpeg -i "input URL" -vf fps=1/5 out%d.png onde o URL de entrada deve ser um link https.
x2212
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Kishan Vaghela
1
No meu caso, preciso de quadros pelo menos a cada segundo. Usei a abordagem 'buscar' acima, mas me perguntei se poderia paralelizar a tarefa. Usei os processos N com abordagem FIFO aqui:
/unix/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
Essencialmente eu bifurquei o processo com &, mas limitei o número de threads simultâneos a N.
Isso melhorou a abordagem de 'buscar' de 26 segundos para 16 segundos no meu caso. O único problema é que o thread principal não sai de forma limpa de volta para o terminal, pois o stdout é inundado.
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Respostas:
Se a etapa de codificação JPEG exigir muito desempenho, você sempre poderá armazenar os quadros descompactados como imagens BMP:
Isso também tem a vantagem de não incorrer em mais perda de qualidade por meio da quantização por transcodificação para JPEG. (PNG também não tem perdas, mas tende a demorar muito mais do que JPEG para codificar.)
fonte
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, certo? (estava faltando o-i
)Encontrei esta questão, então aqui está uma comparação rápida Compare essas duas maneiras diferentes de extrair um quadro por minuto de um vídeo de 38m07s:
1m36.029s
Isso leva muito tempo porque o ffmpeg analisa todo o arquivo de vídeo para obter os quadros desejados.
0m4.689s
Isso é cerca de 20 vezes mais rápido. Usamos a busca rápida para ir ao índice de tempo desejado e extrair um quadro, então chamamos ffmpeg várias vezes para cada índice de tempo. Observe que este
-accurate_seek
é o padrão e certifique-se de adicionar-ss
antes da-i
opção de entrada de vídeo .Observe que é melhor usar em
-filter:v -fps=fps=...
vez de,-r
pois o último pode ser impreciso. Embora o tíquete esteja marcado como corrigido , ainda tive alguns problemas, então é melhor prevenir.fonte
bc
não é um pacote nativo Ubuntu, em vez pode-se usar bash:let "i = $i * 60"
. BTW - excelente ideia-ss
antes-i
. Caso contrário, todo o vídeo será decodificado e os frames desnecessários serão descartadosffmpeg
por núcleo do seu host - o que (para bmp) produz melhorias quase lineares na velocidade (até que você encontre algum outro gargalo, como o disco).Se você sabe exatamente quais frames extrair, por exemplo, 1, 200, 400, 600, 800, 1000, tente usar:
Estou usando isso com um tubo para a montagem de Imagemagick para obter uma visualização de 10 quadros de todos os vídeos. Obviamente, os números dos quadros que você precisa descobrir usando
ffprobe
.
Pequena explicação:
+
significam OR e*
AND\,
é simplesmente escapar do,
personagem-vsync vfr -q:v 2
ele não parece funcionar, mas não sei por que - alguém?fonte
Eu tentei. 3600 quadros em 32 segundos. seu método é muito lento. Você deveria tentar isso.
fonte
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
onde o URL de entrada deve ser um link https.ffmpeg -i file.mpg -vf fps=1 %d.jpg
No meu caso, preciso de quadros pelo menos a cada segundo. Usei a abordagem 'buscar' acima, mas me perguntei se poderia paralelizar a tarefa. Usei os processos N com abordagem FIFO aqui: /unix/103920/parallelize-a-bash-for-loop/216475#216475
Essencialmente eu bifurquei o processo com &, mas limitei o número de threads simultâneos a N.
Isso melhorou a abordagem de 'buscar' de 26 segundos para 16 segundos no meu caso. O único problema é que o thread principal não sai de forma limpa de volta para o terminal, pois o stdout é inundado.
fonte
Isso funcionou para mim
ffmpeg -i file.mp4 -vf fps=1 %d.jpg
fonte