Salut, j'ai besoin d'extraire des cadres de vidéos en utilisant ffmpeg .. Y a-t-il un moyen plus rapide de le faire que ceci:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Salut, j'ai besoin d'extraire des cadres de vidéos en utilisant ffmpeg .. Y a-t-il un moyen plus rapide de le faire que ceci:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Réponses:
Si l'étape de codage JPEG est trop gourmande en performances, vous pouvez toujours stocker les images non compressées sous forme d'images BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Cela présente également l'avantage de ne pas entraîner davantage de perte de qualité grâce à la quantification par transcodage au format JPEG. (PNG est également sans perte mais a tendance à prendre beaucoup plus de temps que JPEG à encoder.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, non? (il vous manquait le -i
)
Je suis tombé sur cette question, alors voici une comparaison rapide. Comparez ces deux façons différentes d'extraire une image par minute d'une vidéo de 38 min 07 s:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029s
Cela prend du temps car ffmpeg analyse l'intégralité du fichier vidéo pour obtenir les images souhaité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.689s
C'est environ 20 fois plus rapide. Nous utilisons la recherche rapide pour accéder à l'index temporel souhaité et extraire une image, puis appelons ffmpeg plusieurs fois pour chaque index temporel. Notez qu'il -accurate_seek
s'agit de la valeur par défaut
et assurez-vous d'ajouter -ss
avant l' -i
option d' entrée vidéo .
Notez qu'il est préférable d'utiliser -filter:v -fps=fps=...
au lieu de -r
car ce dernier peut être inexact. Bien que le ticket soit marqué comme corrigé , j'ai toujours rencontré des problèmes, alors mieux vaut jouer en toute sécurité.
bc
n'est pas un paquet Ubuntu, on peut utiliser au lieu bash: let "i = $i * 60"
. BTW - excellente idée
-ss
avant -i
. Sinon, toute la vidéo sera décodée et les images non requises seront supprimées
ffmpeg
par cœur de votre hôte - ce qui (pour bmp) produit des améliorations presque linéaires de la vitesse (jusqu'à ce que vous rencontriez un autre goulot d'étranglement, comme le disque).
Si vous savez exactement quelles images 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 vers le montage d'Imagemagick pour obtenir un aperçu de 10 images de toutes les vidéos. De toute évidence, les numéros de cadre que vous devrez déterminer en utilisantffprobe
ffmpeg -i myVideo.mov -vf \
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',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:
+
signifie OR et *
AND\,
échappe simplement au ,
personnage-vsync vfr -q:v 2
cela ne semble pas fonctionner mais je ne sais pas pourquoi - n'importe qui?Je l'ai essayé. 3600 images en 32 secondes. votre méthode est vraiment lente. Vous devriez essayer ceci.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
où l'URL d'entrée doit être un lien https.
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Dans mon cas, j'ai besoin de cadres au moins toutes les secondes. J'ai utilisé l'approche «chercher» ci-dessus, mais je me suis demandé si je pouvais paralléliser la tâche. J'ai utilisé les processus N avec l'approche FIFO ici: /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
Essentiellement, j'ai bifurqué le processus avec & mais j'ai limité le nombre de threads simultanés à N.
Cela a amélioré l'approche «chercher à» de 26 secondes à 16 secondes dans mon cas. Le seul problème est que le thread principal ne revient pas proprement vers le terminal car stdout est noyé.
Cela a fonctionné pour moi
ffmpeg -i file.mp4 -vf fps=1 %d.jpg