FFmpeg peut capturer des images à partir de vidéos qui peuvent être utilisées en tant que vignettes pour représenter la vidéo. La plupart des manières de le faire sont décrites dans FFmpeg Wiki .
Mais, je ne veux pas choisir des images aléatoires à certains intervalles. J'ai trouvé quelques options en utilisant des filtres sur FFmpeg pour capturer les changements de scène:
Le filtre thumbnail
tente de trouver les images les plus représentatives de la vidéo:
ffmpeg -i input.mp4 -vf "thumbnail,scale=640:360" -frames:v 1 thumb.png
et la commande suivante sélectionne uniquement les images contenant plus de 40% de modifications par rapport aux précédentes (et donc probablement des modifications de scènes) et génère une séquence de 5 fichiers PNG.
ffmpeg -i input.mp4 -vf "select=gt(scene\,0.4),scale=640:360" -frames:v 5 thumb%03d.png
Crédit d'information pour les commandes ci-dessus à Fabio Sonnati . La seconde me semblait meilleure car je pouvais obtenir n images et choisir le meilleur. Je l'ai essayé et il a généré la même image 5 fois.
Une enquête plus poussée m'a amené à:
ffmpeg -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr out%02d.png
-vsync vfr
veille à ce que vous obteniez des images différentes. Cela choisit toujours toujours la première image de la vidéo. Dans la plupart des cas, la première image est un générique/logo et n'a pas de sens. J'ai donc ajouté un -ss
3 pour supprimer les 3 premières secondes de la vidéo.
Ma dernière commande ressemble à ceci:
ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr out%02d.jpg
C'était le mieux que je puisse faire. J'ai remarqué que, puisque je ne sélectionne que 5 vidéos, toutes datent pour la plupart du début de la vidéo et risquent de manquer des scènes importantes qui se produisent plus tard dans la vidéo.
Je voudrais choisir votre cerveau pour toute autre meilleure option.
Que diriez-vous de rechercher, idéalement, la première trame> 40% de changement dans chacun des 5 intervalles de temps, où les intervalles de temps sont les 1ère, 2ème, 3ème, 4ème et 20ème parties de la vidéo.
Vous pouvez également le diviser en 6 périodes et ignorer le premier pour éviter les crédits.
En pratique, cela signifie que vous devez définir un nombre faible de fps tout en appliquant votre contrôle de changement de scène et votre argument pour rejeter le premier bit de la vidéo.
...quelque chose comme:
ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.4)" -frames:v 5 -vsync vfr -vf fps=fps=1/600 out%02d.jpg
Définir significatif est difficile, mais si vous voulez que N vignettes recouvre efficacement l’ensemble du fichier vidéo, c’est ce que j’utilise pour générer des vignettes sur la production avec le contenu téléchargé par l’utilisateur.
for X in 1..N
T = integer( (X - 0.5) * D / N )
run `ffmpeg -ss <T> -i <movie>
-vf select="eq(pict_type\,I)" -vframes 1 image<X>.jpg`
Où:
ffmpeg -i <movie>
seul ou de ffprobe
qui a un Nice writer de sortie JSON btwSimplement ce qui précède écrit l'image-clé centrale de chaque partition du film. Par exemple. Si le film dure 300 secondes et que vous souhaitez 3 vignettes, il faut une image clé après 50, 150 et 250. Pour 5 vignettes, il s'agirait de 30, 90, 150, 210, 270. Vous pouvez ajuster N en fonction de la durée de la vidéo D, par ex. Un film de 5 minutes aura 3 vignettes mais plus d'une heure aura 20 vignettes.
Chaque appel de la commande ffmpeg
ci-dessus prend une fraction de seconde (!) Pour environ 1 Go H.264. En effet, il passe instantanément à la position <time>
(esprit -ss
avant -i
) et prend la première image clé qui est pratiquement complète au format JPEG. Il n'y a pas de temps perdu pour rendre le film pour correspondre à la position exacte du temps.
Vous pouvez mélanger ci-dessus avec scale
ou toute autre méthode de redimensionnement. Vous pouvez également supprimer les cadres de couleur unie ou essayer de le mélanger à d’autres filtres tels que thumbnail
.
J'ai déjà fait quelque chose de similaire, mais j'ai exporté toutes les images de la vidéo (en 1 ips) et les ai comparées à un utilitaire Perl que j'ai trouvé, qui calcule la différence entre les images. J'ai comparé chaque image aux vignettes précédentes, et si elle était différente de toutes les vignettes, je l'ai ajoutée à la collection de vignettes. L’avantage ici est que si votre vidéo passe de la scène A à B et qu’elle revient à A, ffmpeg exporte 2 images de A.
Essaye ça
ffmpeg -i input.mp4 -vf fps= no_of_thumbs_req/total_video_time out%d.png
En utilisant cette commande, je peux générer le nombre requis de vignettes qui sont représentatives de la vidéo entière.
Voici ce que je fais pour générer une vignette périodique des flux m3u8 en direct à utiliser comme affiche. J'ai découvert qu'exécuter une tâche ffmpeg continue juste pour générer des vignettes mange tout mon processeur, alors je lance un cronjob toutes les 60 secondes qui génère toutes les vignettes de mes flux.
#!/usr/bin/env bash
## this is slow but gives better thumbnails (takes about 1+ minutes for 20 files)
#-vf thumbnail,scale=640:360 -frames:v 1 poster.png
## this is faster but thumbnails are random (takes about 8 seconds for 20 files)
#-vf scale=640:360 -frames:v 1 poster.png
cd ~/path/to/streams
find . -type f \
-name "*.m3u8" \
-execdir sh -c 'ffmpeg -y -i "$0" -vf scale=640:360 -frames:v 1 "poster.png"' \
{} \;
Si vous devez effectuer plus de 60 secondes (limitation de cronjob), vous pouvez créer une boucle while
dans votre script, qui s'exécutera à jamais. Ajoutez simplement un sleep 30
pour changer la fréquence à 30 secondes. Je ne recommande toutefois pas de faire cela avec un grand nombre de vidéos, car la précédente exécution risque de ne pas s'achever avant le début de la suivante.
Idéalement avec cronjob je le lance juste toutes les 5 minutes.