Comment puis-je obtenir le nombre d'images d'une vidéo sur la ligne de commande linux?

29

J'ai un fichier vidéo et je veux obtenir le nombre d'images vidéo qu'il contient. Je peux utiliser ffmpegpour obtenir la longueur de la vidéo et du FPS. Cependant, je ne vois rien d’évident pour le nombre total de cadres.

En théorie, on devrait pouvoir multiplier la longueur (en secondes) par le FPS pour obtenir le nombre d'images, mais dans ce cas, la longueur (34,43 secondes) et le nombre d'images par seconde (29,97 ips) donnent un nombre non entier, ce qui me rend pense que je fais quelque chose de mal.

Je dois pouvoir le faire en ligne de commande de manière totalement automatisée et non graphique. J'ai également besoin que cela soit assez exact et non une estimation (si c'est même possible avec des fichiers vidéo)

J'ai essayé d'utiliser tcprobesur certains fichiers. Cela fonctionne pour certains fichiers AVI, mais pour certains fichiers VOB, la sortie de tcprobe n'a pas le nombre d'images. Je reçois cette sortie:

[tcprobe] MPEG program stream (PS)
[tcprobe] summary for myfile.vob, (*) = not default, 0 = not detected
import frame size: -g 720x480 [720x576] (*)
     aspect ratio: 4:3 (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
                   PTS=2199.3972, frame_time=33ms bitrate=7000 kbps
      audio track: -a 0 [0] -e 48000,16,5 [48000,16,2] -n 0x2000 [0x2000] (*)
                   PTS=2199.2763, bitrate=192 kbps
                   -D 3 --av_fine_ms 20 (frames & ms) [0] [0]
Rory
la source
votre équation vous donnera une bonne estimation approximative; juste autour du résultat flottant-up. Si vous avez besoin d'un nombre exact d'images, vous devrez examiner le fichier directement. Votre estimation peut être décalée d'un ou deux dans les deux sens, en raison des particularités du codec vidéo.
Quack Quichote
sont ces VOB tout-en-un-fichier ou VOB de type DVD divisés en plusieurs fichiers?
Quack Quichotte
1
stackoverflow.com/questions/2017843/…
Ciro Santilli a déclaré 996ICU le

Réponses:

15

C'est horrible et stupide et lent, mais semble fonctionner:

ffmpeg -i foo.avi -vcodec copy -f rawvideo -y /dev/null 2>&1 | tr ^M '\n' | awk '/^frame=/ {print $2}'|tail -n 1

Cela fonctionnera également sur les fichiers tronqués et les flux bruts (c’est pourquoi vous n’obtenez rien pour les fichiers .vob)

utilisateur23307
la source
C'est plutôt bien. D'après mon expérience, cela ne prend pas si longtemps. Un fichier de 40 minutes prend environ <3 secondes à s'exécuter. Rappelez-vous que le "^ M" n'est pas les 2 caractères ^ et M, vous devez appuyer sur Control-V, puis entrer. Au lieu de votre commande, j’ai utilisé: ffmpeg -i un_fichier.avi -vcodec copie -f rawvideo -y / dev / null 2> & 1 | tr "^ M" '\ n' | grep '^ frame =' | perl -pe's / ^ cadre = \ s * ([0-9] +) \ s. * $ / \ 1 / '| tail -n 1 Votre commande échoue s'il n'y a pas d'espace après le "frames ="
Rory
1
Dans Ubuntu 12.04, version de ffmpeg git-2013-04-15-a4f03f0, vous pouvez omettre les deux | tr ^M '\n'et |tail -n 1. En outre, aucun espace après frames=n'échoue. (Peut-être que quelque chose a changé au cours des quatre dernières années.)
Camille Goudeseune
pour moi ce retour à chaque fois des valeurs différentes
CAMOBAP
1
La solution Mediainfo fonctionne avec VOB. Je le recommanderais plutôt. root @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count Nombre de cadres: 175715 Nombre de cadres: 183218
kevinf
31

ffprobe peut être utilisé pour obtenir des informations sur un fichier multimédia:

ffprobe -select_streams v -show_streams input.avi

Vous obtiendrez des détails sur le flux:

nb_frames=159697

Rechercher nb_framesavec grep:

ffprobe -select_streams v -show_streams input.avi 2>/dev/null | grep nb_frames | sed -e 's/nb_frames=//'

Cela fonctionne pour avi, mp4, etc. Pour certains conteneurs, il n'affiche pas de valeur valide, par exemple, mpeg.

Dans ce cas, cela fonctionne ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l

Réplique
la source
Bonne idée. J'ai un peu modifié la commande pour ne sélectionner que le flux vidéo et filtrer la sortie. Cela vous donne juste le nombre d'images.
Slhck
1
Félicitations pour votre deuxième solution qui fonctionne avec MPEG-2!
Malat
1
Cela ne fonctionne pas avec les conteneurs MKV.
Cenk Alti
1
nb_frames = N / A sur ce fichier: web.archive.org/web/20180117220713/http://techslides.com/demos/…
Ciro Santilli a déclaré 996ICU le
Il semble que la première approche échoue sur les fichiers encodés en VBR. La deuxième approche est plus fiable.
Elder Geek
16

J'ai posté ceci sur une autre question . En utilisant l' tcprobeoutil (à partir du transcodepackage), le nombre d'images est inclus dans les informations. Utilisez le -icommutateur pour obtenir un vidage d’informations à partir du fichier:

$ tcprobe -i foo.avi
[tcprobe] RIFF data, AVI video
[avilib] V: 29.970 fps, codec=XVID, frames=38630, width=512, height=384
[avilib] A: 48000 Hz, format=0x55, bits=16, channels=2, bitrate=128 kbps,
[avilib]    53707 chunks, 21768720 bytes, VBR
[tcprobe] summary for foo.avi, (*) = not default, 0 = not detected
import frame size: -g 512x384 [720x576] (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
      audio track: -a 0 [0] -e 48000,16,2 [48000,16,2] -n 0x55 [0x2000] (*)
                   bitrate=128 kbps
           length: 38630 frames, frame_time=33 msec, duration=0:21:28.954

Notez que le nombre d'images est donné sur deux lignes ici (2ème ligne de sortie et dernière ligne de sortie).

Quack Quack
la source
Cela semble être une bonne réponse et fonctionne pour certains fichiers, mais pour certains fichiers VOB, je n'ai pas ces données dans la sortie. J'ai mis à jour la question avec la sortie que je reçois
Rory
Je suppose (mais je ne sais pas avec certitude) que tcprobe examine les en-têtes de fichiers pour obtenir ces informations. s'il n'est pas inclus dans l'en-tête, tcprobe ne peut pas tenter un calcul pour cela. bonne question; J'aimerais avoir une bonne réponse pour vous.
Quack Quichotte
Cela ne semble pas fonctionner sur les fichiers encodés en VBR. Je n'obtiens aucune sortie en nombre d'images. J'obtiens la résolution, le format et la fréquence d'images.
Elder Geek
7

J'ai trouvé que cela mediainfo --fullscan inputfile | grep "Frame count"fonctionne bien pour la plupart des fichiers.

Les systèmes Debian peuvent l’installer avec apt-get install mediainfo

Si vous obtenez 2 lignes plutôt que l'une des sorties, la première ligne est la piste vidéo et la deuxième ligne est la piste audio. Il semble que cela se produise sur des fichiers avec de l’audio à débit binaire variable.

Testé sur les échantillons .mkv, .m4v, .mp4, flv, vob et .avi à la date de l'édition.

Sources: Comment récupérer des informations sur les fichiers vidéo à partir de la ligne de commande sous Linux? et tester sous les goûts Ubuntu.

Vous pouvez trouver mediainfo disponible pour votre système d'exploitation ici.

Elder Geek
la source
4

ffprobe -select_streams v -show_frames -count_frames INPUT_FILE | grep pkt_duration_time =

Additionnez la durée. Pourrait être amateur avec sed / awk et ce qui ne l'est pas.

D'après nos tests, je peux dire que pour l'instant, il s'est révélé le meilleur, le plus fiable. Vous obtenez un compte rendu précis et une durée exacte. Même avec un framerate variable auquel tous les autres outils, comme mediainfo, semblent aller gaga.

Guillaume Blain
la source
3

J'ai constaté que le nombre d'images est en réalité le double de la durée en fps * (je ne sais pas pourquoi, je serais heureux de le savoir).

Dans un de mes scripts, j'ai:

# Get duration and fps
duration=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Duration: \([^,]*\), start: .*/\1/p")
fps=$($FFMPEG -i $input 2>&1 | sed -n "s/.*, \(.*\) tb.*/\1/p")

hours=$(echo $duration | cut -d":" -f1)
minutes=$(echo $duration | cut -d":" -f2)
seconds=$(echo $duration | cut -d":" -f3)
# For some reason, we have to multiply by two (no idea why...)
# Get the integer part with cut
frames=$(echo "($hours*3600+$minutes*60+$seconds)*$fps*2" | bc | cut -d"." -f1)

Et oui, pour une raison quelconque, je dois en obtenir la partie entière. Cela n’a aucun sens, mais ce script a toujours réussi à convertir mes vidéos correctement jusqu’à présent.

Inkaphink
la source
Parce que FPS signifie Frames Per Second (ou jeu de tir à la première personne: D) et s’il ya 30 FPS, il suffit de le multiplier par le nombre de secondes de la vidéo.
John T
Oui John, je pourrais le comprendre, mais cela n’explique pas pourquoi je dois le multiplier par 2 pour obtenir la bonne quantité d’images ... Dans mon cas, après avoir calculé le nombre d’images, j’ai lancé ffmpeg dans le dossier arrière-plan et analysé les journaux pour créer une barre de progression. Les journaux indiquent combien de trames ont été converties. Une fois que la vidéo entière a été convertie, l'image # était int (secondes * fps * 2), d'où mon code, mais j'aimerais savoir pourquoi ;-)
mercredi
c'est curieux; la tcprobesortie dans ma réponse donne le nombre d'images comme exactement secondes * fps (arrondi supérieur). Je suppose que vous voyez une bizarrerie de ffmpeg. avez-vous essayé d'analyser le fichier avec d'autres outils pour voir s'ils affichent le même nombre d'images?
Quack Quichote
Hmmm ... Intéressant. J'ai essayé une vidéo et j'ai seconds*fps=1001.59et tcprobe=1002. Alors évidemment, tcprobeme dit que je n'ai pas besoin de multiplier par deux. Pourquoi alors ffmpeg me donne-t-il un nombre deux fois plus grand dans les journaux lors de la conversion?
aphink
2
s'agit-il de métrage entrelacé? Si tel est le cas, il y a deux champs par image et cela pourrait vous donner le nombre de champs.
Stib
3

Testé sur Ubuntu.

melt icecap.mp4 -consumer xml
  • melt- melt était conçu comme un outil de test pour le framework MLT, mais c'est aussi un puissant éditeur vidéo multipiste orienté ligne de commande. Il pourrait également être utilisé comme lecteur multimédia minimaliste pour les fichiers audio et vidéo.

  • -consumerid [: arg] [nom = valeur] *
    Définir le consommateur (récepteur)

  • xml - Définir le consommateur (récepteur) sur une sortie au format XML

  • <property name="length">nnnn</property>- montre le nombre d'images, où nnnnest remplacé par un nombre entier égal au nombre d'images

Si vous n’avez pas fondu, vous pouvez l’installer sur Ubuntu et d’autres systèmes basés sur Debian avec sudo apt-get install melt

neoneye
la source
1
C'est très court, voulez-vous développer ce qu'il fait, pourquoi ça marche, etc.?
David
Cela fonctionne bien sur les fichiers h264 mp4 qui ne fournissent pas le nombre de fichiers via mediainfo -fullscan filename.
Elder Geek
3

Directement avec mediainfo, pas de grep, pas d'attente, pas de rien:

mediainfo --Inform='Video;%FrameCount%' $the_file

Pour d'autres informations, voir mediainfo --info-parameters

xénoïde
la source
0

Vous pouvez le faire en ajoutant et en multipliant les valeurs que vous obtenez de ffprobe.

Remarque: ffprobe fait partie de libav (avconv) - la version linux de ffmpeg.

#your command -
 ffprobe man.avi

Lorsque vous faites cela, vous obtiendrez le nombre d'images par seconde et la durée du clip.

Convertissez la durée du clip en secondes et multipliez cette valeur par le nombre d'images par seconde.

N'oubliez pas d'arrondir le nombre au plus proche.

JJAtairu
la source
Sur Ubuntu 14.04, LTS ffproben'est pas disponible, mais il y a quelque chose appelé avprobedans libav-tools(qui fournit également avconv). Mais à mes côtés, il n’imprime aucun nombre d’images, du moins pas pour les formats que j’ai essayés. Il imprime juste, ce qui est avprobe -iimprimé aussi, et ce n’est malheureusement que quelques petits détails sur le format. Même avec -v debugcela, il ne me dit que quelques propriétés intéressantes de mon matériel et de mes logiciels installés, mais pas une seule information intéressante sur le fichier / flux à analyser. Cela cache peut-être certaines des myriades d’options disponibles. Qui sait?
Tino
@Tino ffprobe est en effet disponible dans le package ffmpeg. avconv est un fork de ffmpeg et a semé la confusion. Voir: stackoverflow.com/questions/9477115/…
Elder Geek
@ElderGeek Pour Ubuntu 14.04 LTS, il n'y ffmpegen a pas dans les dépôts officiels. Le lien que vous avez correctement indiqué le dit: FFmpeg est revenu dans Ubuntu 15.04 "Vivid Vervet". . Cependant, la situation a maintenant changé et 16.04 LTS est sorti.
Tino
@Tino C'est effectivement un fait. Cependant, je ne dirais pas que indisponible n'existe pas dans les référentiels. Vous noterez qu'il est disponible pour Trusty (14.04) ici: ffmpeg.org/download.html
Elder Geek
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 Maluk
la source
-2

Meilleure méthode: (Directe en calculant les bons paramètres, confirmée par ffmpeg)

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"

Résultat ->

r_frame_rate=24000/1001
duration=8177.794625

Calcul ->

Frames=24000/1001*8177.794625=196071 (exactly... ;P)

Preuve ->

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

Ici

frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x

Sortie

video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
shareeditdeleteflag
Gerard Wensink
la source
Je reçois r_frame_rate = 25/1 duration = N / A
Elder Geek