La manière la plus rapide d'extraire des cadres à l'aide de ffmpeg?

Salut je dois extraire des cadres de vidéos en utilisant ffmpeg.. Est-il un moyen plus rapide de faire que cela:

ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg

?

66
demandé sur Stpn 2012-06-09 04:20:26

4 réponses

si L'étape D'encodage JPEG est trop exigeante en termes de performances, vous pouvez toujours stocker les cadres non compressés en tant qu'images BMP:

ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp

cela a aussi l'avantage de ne pas subir plus de perte de qualité par quantification en transcodant en JPEG. (PNG est également sans perte mais prend généralement beaucoup plus de temps que JPEG pour encoder.)

83
répondu Multimedia Mike 2012-06-09 18:28:47

est tombé sur cette question, donc voici une comparaison rapide. Comparez ces deux façons différentes d'extraire une image par minute d'une vidéo de 38m07s de long:

time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp

1m36.029s

cela prend du temps parce que ffmpeg analyse le fichier vidéo entier pour obtenir les images désirées.

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.689

C'est environ 20 fois plus rapide. Nous employons la recherche rapide pour aller à l'index de temps désiré et extraire un cadre, puis appeler ffmpeg plusieurs fois pour chaque index de temps. Notez que -accurate_seek est la valeur par défaut et assurez-vous d'ajouter -ss avant l'entrée vidéo -i option.

notez qu'il est préférable d'utiliser -filter:v -fps=fps=... au lieu de -r comme ce dernier peut être inexact. bien que le billet est marqué comme fixe , j'ai quand même fait l'expérience de certains problèmes, donc mieux jouer sûr.

43
répondu blutorange 2015-02-04 12:56:41

si vous savez exactement quels cadres extraire, par exemple 1, 200, 400, 600, 800, 1000, essayez d'utiliser:

select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
       -vsync vfr -q:v 2

j'utilise ceci avec un tuyau pour Imagemagick's montage pour obtenir 10 images de prévisualisation de toutes les vidéos. Évidemment, les numéros de trame que vous aurez besoin de comprendre en utilisant ffprobe

ffmpeg -i myVideo.mov -vf \
    select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,100)',scale=320:-1 \
    -vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
  | montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png

.

petite explication:

  1. dans les expressions ffmpeg + signifie Ou et * pour et
  2. \, échappe tout simplement au caractère , 1519200920"
  3. sans -vsync vfr -q:v 2 ça ne semble pas marcher mais je ne sais pas pourquoi-quelqu'un?
6
répondu Voy 2018-01-29 17:25:35

dans mon cas, j'ai besoin de cadres au moins chaque seconde. J'ai utilisé l'approche "chercher à" ci-dessus, mais je me suis demandé si je pouvais faire un parallèle avec la tâche. J'ai utilisé la méthode n Avec L'approche FIFO ici: https://unix.stackexchange.com/questions/103920/parallelize-a-bash-for-loop/216475#216475

open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=
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

essentiellement j'ai bifurqué le processus avec & mais limité le nombre de threads concurrents à N.

cela a amélioré le "chercher à" approche de 26 secondes à 16 secondes dans mon cas. Le seul problème est que le thread principal ne sort pas proprement de nouveau vers le terminal puisque stdout est inondé.

0
répondu Tycon 2018-02-15 15:10:38