Récupérer le nombre d'images avec ffmpeg

112

Est-ce que quelqu'un sait comment récupérer le nombre total d'images à partir d'un fichier vidéo en utilisant ffmpeg? La sortie de rendu de ffmpeg montre l'image actuelle et j'ai besoin du nombre d'images pour calculer la progression en pourcentage.

Hansl
la source
1
superuser.com/questions/84631/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

158

Remarque: la présence d'une liste de montage dans MP4 / M4V / M4A / MOV peut affecter votre numéro d'image. Voir Modifier les listes ci - dessous.


ffprobe: interroger le conteneur

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • C'est une méthode rapide.
  • Tous les formats (tels que Matroska) ne rapporteront pas le nombre d'images résultant de la sortie de N/A. Consultez les autres méthodes répertoriées ci-dessous.

ffprobe: compte le nombre d'images

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • C'est une méthode lente.
  • Ajoutez l' -skip_frame nokeyoption permettant de ne compter que les images clés.

ffmpeg: compte le nombre d'images

Si vous n'en avez pas, ffprobevous pouvez utiliser à la ffmpegplace:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • C'est une méthode un peu rapide.
  • Reportez-vous à frame=la fin de la sortie de la console.
  • Ajoutez l' -discard nokeyoption d'entrée (avant -i) pour ne compter que les images clés.

Modifier les listes

Ignorez la liste d'édition MP4 / M4V / M4A / MOV avec l' -ignore_editlist 1option d'entrée. La valeur par défaut est de ne pas ignorer la liste d'édition.

Ce que signifient les options ffprobe

  • -v error Cela masque la sortie "info" (informations de version, etc.), ce qui facilite l'analyse.

  • -count_frames Comptez le nombre d'images par flux et signalez-le dans la section de flux correspondante.

  • -select_streams v:0 Sélectionnez uniquement le flux vidéo.

  • -show_entries stream=nb_framesou -show_entries stream=nb_read_framesAfficher uniquement l'entrée pour nb_framesou nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Définissez le format de sortie (alias le "rédacteur") sur default, n'imprimez pas la clé de chaque champ ( nokey=1) et n'imprimez pas l'en-tête et le pied de page de la section ( noprint_wrappers=1). Il existe des alternatives plus courtes telles que -of csv=p=0.

Regarde aussi


mediainfo

L' mediainfooutil bien connu peut afficher le nombre d'images:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4Box

Pour les fichiers MP4 / M4V / M4A.

MP4Box de gpac peut afficher le nombre d'images:

MP4Box -info input.mp4

Reportez-vous à la Media Infoligne dans la sortie pour le flux vidéo en question:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

Dans cet exemple, le flux vidéo a 2525 images.


boxdumper

Pour les fichiers MP4 / M4V / M4A / MOV.

boxdumperest un outil simple de l-smash. Il produira une grande quantité d'informations. Dans la stszsection de la zone de taille de l' échantillon, reportez-vous au sample_countnombre de cadres. Dans cet exemple, l'entrée a 1900 images vidéo:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Sachez qu'un fichier peut avoir plus d'un stszatome.
llogan
la source
5
Ou, si vous voulez plus de vitesse et si nb_frames est suffisamment fiable, simplifiez-vous comme ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
suit
Cela génère la réponse deux fois pour moi (c'est-à-dire 2600 \ n 2600). Une raison particulière qui se produirait?
jbodily
@jbodily Mon exemple ou celui de juanitogan? Je ne peux pas le dupliquer en utilisant non plus. Pas grand chose avec quoi travailler ici.
llogan
+1, notamment parce que, contrairement à trop d'autres réponses sur n'importe quel outil de ligne de commande, celui-ci explique en fait toutes les options de ligne de commande. Je vous remercie.
Ray
1
Notez que la première option, interroger le conteneur, traite en fait le fichier en raison de count_frames. Voir le commentaire de @ juanitogan.
aggieNick02
24

Sous Unix, cela fonctionne comme du charme:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
ataraxique
la source
3
Vraiment sympa. Vous n'avez simplement pas besoin de copier le flux audio. Vous pouvez utiliser -an instat.
rekire le
1
@PrakharMohanSrivastava Cochez cette réponse
Antonio
4
En fait, cela semble rapide et fiable:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Timothy Zorn
1
@Michael merci pour le sourire avec mon café du matin :-)
Lloyd Moore
1
@TimothyZorn Vous avez fait ma journée!
Mladen Danic le
13

Calculez-le plutôt en fonction du temps.

C'est ce que je fais et cela fonctionne très bien pour moi, et bien d'autres.) Tout d'abord, recherchez la longueur de la vidéo dans l'extrait ci-dessous:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

Vous devriez être en mesure de trouver de manière cohérente et sûre Duration: hh:mm:ss.nnla taille du clip vidéo source. Ensuite, pour chaque ligne de mise à jour (CR, pas de LF), vous pouvez analyser le texte pour la marque d'heure actuelle où il se trouve:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

Veillez simplement à ne pas toujours vous attendre à une sortie parfaite de ces lignes d'état. Ils peuvent inclure des messages d'erreur comme ici:

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

Une fois que vous avez le temps, il est mathématique simple: time / durration * 100 = % done.

Stu Thompson
la source
1
Excusez-moi d'être stupide mais comment puis-je faire l'heure / la durée lorsque la durée est au format hh: mm: ss.nn et que l'heure est toujours au format xx.yy?
Omar Ali
2
@Omar, En tant que développeur .NET, ce que je fais est de créer un à TimeSpanpartir de celui-ci, puis de l'utiliser currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). Le TimeSpan fournit également une fonction d'analyse puissante, vérifiez-le
Shimmy Weitzhandler
excellente solution, mon temps est en hh: mm: ss: ms donc je suppose que dans ces 3 ans FFMPEG a amélioré le format de l'heure de sortie.
ElektroStudios
1
Notez que la sortie de la console peut indiquer 29,97, mais c'est l'abréviation de 30000/1001. Idem pour 23,98 qui est 24000/1001 et 59,94 est 60000/1001.
llogan
À noter, cela ne fonctionne pas pour les vidéos à fréquence d'images variable (évidemment).
Timothy Zorn
8

Tous les formats ne stockent pas leur nombre d'images ou leur durée totale - et même s'ils le font, le fichier peut être incomplet - donc ffmpeg ne détecte aucun d'eux avec précision par défaut.

Au lieu de cela, essayez de chercher jusqu'à la fin du fichier et lisez l'heure, puis comptez l'heure actuelle pendant que vous y allez.

Alternativement, vous pouvez essayer AVFormatContext->nb_index_entriesla durée détectée, qui devrait fonctionner correctement au moins en bon état AVI / MOV, ou la bibliothèque FFMS2, qui est probablement trop lente à déranger pour une barre de progression.

Alex étrange
la source
8

Essayez quelque chose comme:

ffmpeg -i "path to file" -f null /dev/null

Il écrit le numéro de l'image dans stderr, vous pouvez donc récupérer la dernière image à partir de celui-ci.

a1kmm
la source
8

Vous pouvez utiliser ffprobe pour obtenir le numéro d'image avec les commandes suivantes

  1. première méthode

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

qui disent d'imprimer les données au jsonformat

select_streams vvous dira ffprobede nous donner simplement des videodonnées de flux et si vous les supprimez, cela vous donnera également des audioinformations

et la sortie sera comme

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2. vous pouvez utiliser

ffprobe -v error -show_format -show_streams video_name

qui vous donnera des données de flux, si vous voulez des informations sélectionnées comme la fréquence d'images, utilisez la commande suivante

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

qui donnent une base numérique sur les informations de votre vidéo, le problème est que lorsque vous utilisez cette méthode, il est possible que vous obteniez un N/A sortie.

pour plus d'informations, consultez cette page Conseils FFProbe

Hadi Rasekh
la source
4

essaye ça:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Julien
la source
Ne fonctionne pas avec le *.ts. La sortie est une ligne vide.
Victor Polevoy
3

Étant donné que mon commentaire a reçu quelques votes positifs, j'ai pensé que je le laisserais comme réponse:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

Cela devrait être rapide, car aucun encodage n'est effectué. ffmpegdémultiplexera simplement le fichier et lira (décodera) le premier flux vidéo aussi rapidement que possible. La première grepcommande saisira le texte qui montre le cadre. La deuxième grepcommande ne prendra que le nombre de cela. La tailcommande affichera simplement la dernière ligne (décompte final des images).

Timothy Zorn
la source
2

pour construire sur la réponse de stu. voici comment j'ai trouvé la fréquence d'images d'une vidéo à partir de mon téléphone portable. j'ai exécuté la commande suivante pendant un moment. Je laisse le nombre d'images atteindre environ ~ 10000 avant de m'impatienter et d'appuyer sur ^ C:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

puis, j'ai attrapé deux informations de cette ligne qui commence par "frame =", le nombre d'images, 7989, et l'heure, 00: 04: 26.30. Vous devez d'abord convertir le temps en secondes, puis diviser le nombre d'images par secondes pour obtenir des «images par seconde». "images par seconde" est votre fréquence d'images.

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

le framerate pour ma vidéo est de 30 fps.

margaret
la source
2

La seule précision que j'ai pu faire est la suivante:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

Pour vous assurer que cela fonctionne avec la vidéo:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Lloyd Moore
la source
J'ai voté pour votre réponse, mais cela ne fonctionnera que si la vidéo ne contient pas d'audio. S'il contient, celui-ci fonctionnera:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

Désolé pour la réponse necro, mais peut-être en aura-t-il besoin (car je n'ai pas trouvé de solution pour les dernières versions de ffmpeg.

Avec ffmpeg 3.3.4, j'en ai trouvé un avec ce qui suit:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

À la fin, il affichera le nombre de trames. Cela a fonctionné pour moi sur des vidéos avec audio. Cela donne deux fois une ligne "nb_frames", cependant, mais la première ligne était le nombre réel d'images sur les vidéos que j'ai testées.

acidrums4
la source
Merci @ acidrums4. Vérifié que cette méthode fonctionne avec la dernière version de github que j'ai construite aujourd'hui.
Paul J
1

J'utilise le php_ffmpeg alors je peux obtenir toutes les heures et toutes les images d'un film. Comme belows

$input_file='/home/strone/workspace/play/CI/abc.rmvb';
$ffmpegObj = new ffmpeg_movie($input_file);
echo $ffmpegObj->getDuration();
    echo $ffmpegObj->getFrameCount();

Et puis le détail est sur la page.

http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

xingyue
la source
1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Gérard Wensink
la source
La fréquence d'images est normalement calculée à partir de deux paramètres. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Arrondi par ffmpeg à: 23,98 Durée = heures * 3600 + minutes * 60 + secondes.roulement = 8177,91 Alors que paramètre de durée = 8177,794625 Mais cadres = 24000/1001 * 8177,794625 = 196071 donne le nombre exact d'images. (Sans blague).
Gerard Wensink
0

Linux

ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null

rubis

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
Yaroslav Malyk
la source