Question Des vignettes significatives pour une vidéo en utilisant FFmpeg


FFmpeg peut capturer des images à partir de vidéos pouvant être utilisées comme vignettes pour représenter la vidéo. Les manières les plus courantes de le faire sont capturées dans Wiki FFmpeg.

Mais, je ne veux pas choisir des trames 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 essaie 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 qui ont plus de 40% de modifications par rapport aux précédentes (et qui sont probablement des changements de scène) et génère une séquence de 5 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 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 approfondie m'a amené à:

ffmpeg -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr  out%02d.png

-vsync vfr s'assure que vous obtenez des images différentes. Cela sélectionne toujours la première image de la vidéo, dans la plupart des cas, la première image est un crédit / logo et non significative, alors j'ai ajouté une -ss 3 pour éliminer les 3 premières secondes de la vidéo.

Ma commande finale 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 meilleur que je pouvais faire. J'ai remarqué que depuis que je ne choisis que 5 vidéos, toutes sont pour la plupart à partir du début de la vidéo et peuvent manquer des scènes importantes survenant plus tard dans la vidéo.

Je voudrais choisir votre cerveau pour toute autre meilleure option.


68
2018-01-18 08:35


origine


Bons exemples de commandes. FWIW, je n'ai rencontré aucun problème avec les images JPEG générées par FFmpeg sous OS X (10.8, FFmpeg 1.1 et versions ultérieures). Votre dernière commande fonctionne parfaitement pour moi, tout comme le dernier, et aucun de ces fichiers ne génère des fichiers JPG vierges. J'ai compilé avec libopenjpeg.. pas sûr si cela fait une différence. - slhck
Merci slhck. Édité la question avec les détails de configuration / version de ffmpeg. Je n'ai pas mis à niveau vers 1.1 sur cette machine. Je vais le faire et voir si cela change des résultats. - d33pika
Donc, vous êtes sur Ubuntu? Pouvez-vous essayer la dernière version de Git Master d'un construction statique ou vous compiler et courir à nouveau? Ou la dernière écurie. Je viens de vérifier, il utilise le mjpeg encodeur pour moi aussi, et j'ai aussi vérifié jpegoptim et exiv2, qui fonctionnent bien pour moi avec tous les résultats JPG de vos exemples de commandes. - slhck
J'ai mis à jour et ça marche maintenant! Je suppose que la version précédente avait des bugs. - d33pika
Pouvez-vous aller de l'avant et publier la nouvelle version de la solution, de préférence avec un lien vers le journal des modifications montrant le bogue que vous avez rencontré et ensuite corrigé avec la nouvelle version? - Lizz


Réponses:


Que diriez-vous de rechercher, idéalement, la première trame à plus de 40% dans chacune des 5 périodes où les durées sont les 1 er, 2 e, 3 e, 4 e et 5 e 20% de la vidéo.

Vous pouvez également le diviser en 6 temps et ne pas tenir compte du 1er pour éviter les crédits.

En pratique, cela signifierait que le nombre d'images par seconde est faible tout en appliquant la vérification du changement de scène et votre argument pour lancer 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

22
2018-06-15 21:35



Oui, cela aide à choisir les vignettes des différentes sections de la vidéo. Merci! - d33pika
Les images complètement noires ou blanches sont captées. Comment les éviter? - d33pika
En ce qui concerne les cadres blancs, eh bien, ça devient compliqué, mais on dirait qu'il y a un moyen: 1. de supprimer les cadres noirs; 2. de nier (le blanc devient noir); (Si vous parvenez à supprimer les cadres noirs ou blancs, en particulier sur une seule ligne, pouvez-vous les poster ici? Je peux les ajouter à la réponse pour les futurs lecteurs. Je le reverrais certainement.) - A.M.
Pour éviter d’ennuyer les images telles que le noir et blanc ordinaire: générez plus de vignettes que vous n’avez besoin, compressez-les avec jpeg et choisissez les images avec une taille de fichier plus grande. Cela fonctionne étonnamment bien en soi pour obtenir des vignettes décentes. - Sam Watkins
Cette commande ne fonctionnait pas, j'ai eu l'erreur Unable to find a suitable output format for 'fps=fps=1/600'. La solution est d'ajouter -vf avant cet argument (voir stackoverflow.com/questions/28519403/ffmpeg-command-issue) - John Wiseman


Définir significatif est difficile, mais si vous voulez créer efficacement des vignettes couvrant tout le fichier vidéo, c'est ce que j'utilise pour générer des vignettes lors de la production avec du contenu téléchargé par l'utilisateur.

Pseudo-code

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ù:

  • D - durée de la vidéo lue à partir de ffmpeg -i <movie> seul ou ffprobe qui a beau scripteur de sortie JSON btw
  • N - nombre total de vignettes souhaitées
  • X - numéro de vignette, de 1 à N
  • T - point de temps pour tumbnail

Simplement, 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 voulez 3 vignettes, il faut une image clé après les années 50, 150 et 250. Pour 5 vignettes, il s'agirait des 30, 90, 150, 210 et 270. Vous pouvez ajuster N en fonction de la durée du film D, par ex. Le film de 5 minutes aura 3 vignettes, mais plus d'une heure aura 20 vignettes.

Performance

Chaque invocation de ci-dessus ffmpeg la commande prend une fraction de seconde (!) pour ~ 1 Go H.264. C'est parce qu'il saute instantanément à <time> position (esprit -ss avant -i) et prend la première image clé qui est pratiquement complète JPEG. Il n'y a pas de temps perdu à rendre le film pour correspondre à la position exacte de l'heure.

Post-traitement

Vous pouvez mélanger ci-dessus avec scale ou toute autre méthode de redimensionnement. Vous pouvez également supprimer des cadres de couleur unie ou essayer de les mélanger avec d’autres filtres comme thumbnail.


5
2017-10-06 20:21



wow en mouvement -ss N à avant -i est une astuce incroyable Je vous remercie! - apinstein


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 avec un utilitaire perl que j'ai trouvé et qui calcule la différence entre les images. J'ai comparé chaque image aux miniatures précédentes, et si elle était différente de toutes les miniatures, je l'ai ajoutée à la collection de miniatures. L'avantage ici est que si votre vidéo passe de la scène A à B et qu'elle revient à A, ffmpeg exportera 2 images de A.


2
2018-03-17 14:36



Quels facteurs avez-vous utilisés pour comparer 2 images? - d33pika
Malheureusement, je ne me souviens pas, c'était il y a très longtemps. Vous devez d'abord déterminer quelle méthode de comparaison utiliser, puis effectuer des tests pour trouver le facteur correct. Cela ne devrait pas prendre longtemps. - Eran Ben-Natan
Je pense juste à voix haute ici, mais est-ce que cette option n'est pas pire? Lorsque vous comparez 2 images exportées de la vidéo, vous en avez déjà perdu. Je veux dire, il est plus facile de calculer la similarité à partir des informations de codec que de 2 images, n'est-ce pas? Récemment, j'ai étudié certains algorithmes / bibliothèques pour comparer des images et celles-ci ne fonctionnent pas aussi bien qu'on pourrait le souhaiter. - Samuel
Eh bien, avec ffmpeg, vous pouvez extraire des cadres sans perte de qualité en utilisant le drapeau same_quality. Si vous utilisez des informations de codec, vous devez vérifier que vous ne recevez pas simplement les Iframes. Quoi qu’il en soit, cet utilitaire perl fonctionnait très bien pour moi et est très configurable. Regardez ici: search.cpan.org/~avif/Image-Compare-0.3/Compare.pm - Eran Ben-Natan


Essaye ça

 ffmpeg -i input.mp4 -vf fps= no_of_thumbs_req/total_video_time out%d.png

Grâce à cette commande, je peux générer le nombre requis de vignettes représentatives de la vidéo entière.


2
2017-07-31 01:33



Ne serait pas la bonne formule pour fps être (no_of_frames_req * fps_of_vid) / total_video_frames? - flolilolilo
Je suis à la recherche d'une solution opposée: sélectionner plus d'images à des périodes où la caméra est plus stable et ne bouge pas? (où la différence entre les images successives est inférieure, pas supérieure). Y-a-t-il un moyen de faire ça? - Tina J


Voici ce que je fais pour générer une vignette périodique pour les flux m3u8 en direct à utiliser comme affiche. J'ai trouvé que l'exécution d'une tâche ffmpeg continue pour générer des miniatures mange tout mon processeur, alors je lance une tâche toutes les 60 secondes qui génère toutes les miniatures 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 faire plus de 60 secondes (limitation de cronjob), vous pouvez faire une while boucle dans votre script et il s'exécutera pour toujours. Ajoutez simplement un sleep 30 pour changer la fréquence à 30 secondes. Je déconseille toutefois de le faire avec un grand nombre de vidéos, car l'exécution précédente risque de ne pas se terminer avant la suivante.

Idéalement, avec cronjob, je le lance toutes les 5 minutes.


1
2017-12-31 07:03