4 votes

FFmpeg obtient la durée d'un fichier vidéo sans les méta-données

J'ai un fichier vidéo qui n'a pas de méta-données.

Si je fais ça par exemple :

ffmpeg -i test.m2v

J'obtiens ces valeurs :

Duration: N/A, bitrate: N/A

Existe-t-il encore un moyen d'obtenir la durée de la vidéo / du fichier .m2v ?

Editar:

La sortie complète de la console :

ffmpeg version 2.8.4 Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 5.2.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libdcadec --enable-libfr
eetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enab
le-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink
--enable-zlib
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mpegvideo, from '.\Test.m2v':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], max. 7000 kb/s, 25 fps, 25 tbr, 1200k tbn, 50 tbc

5voto

Gyan Points 29437

Pour un flux binaire brut, ffprobe peut être utilisé.

ffprobe -show_entries stream=r_frame_rate,nb_read_frames -select_streams v -count_frames -of compact=p=0:nk=1 -v 0 in.m2v

Cela produit

30/1|120

où la première entrée est la fréquence d'images sous forme de nombre rationnel, et la seconde est le nombre d'images comptées. La durée est 120 / (30/1) = 4.00s

1voto

LSerni Points 8163

Si vous no ont des métadonnées, alors vous devez construire ces métadonnées en lisant et en analysant l'ensemble du fichier (c'est ce qui ffprobe ), et obtenir une réponse correcte basée sur le contenu réel du fichier.

Il n'y a pas plus précis réponse. Il existe cependant un plus rapide réponse. Comme on l'a remarqué, " Si vous ouvrez ces vidéos dans VLC, la durée de la vidéo s'affiche immédiatement. ". À plusieurs endroits, VLC (et d'autres outils également) semble faire une erreur d'affichage. estimation au lieu de lire et d'analyser l'ensemble du fichier (ce que vous ne pouvez ou ne voulez pas faire) :

/* try to calculate movie time */
if( p_sys->p_fp->i_data_packets_count > 0 )
{
    uint64_t i_count;
    uint64_t i_size = stream_Size( p_demux->s );

    if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
    {
        i_size = p_sys->i_data_end;
    }

    /* real number of packets */
    i_count = ( i_size - p_sys->i_data_begin ) /
              p_sys->p_fp->i_min_data_packet_size;

    /* calculate the time duration in micro-s */
    p_sys->i_length = VLC_TICK_FROM_MSFTIME(p_sys->p_fp->i_play_duration) *
               (vlc_tick_t)i_count /
               (vlc_tick_t)p_sys->p_fp->i_data_packets_count;
    if( p_sys->i_length <= p_sys->p_fp->i_preroll )
        p_sys->i_length = 0;
    else
    {
        p_sys->i_length  -= p_sys->p_fp->i_preroll;
        p_sys->i_bitrate = 8 * i_size * CLOCK_FREQ / p_sys->i_length;
    }
}

Dans ce cas,

Flux #0:0 : Vidéo : mpeg2video (Main), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], max. 7000 kb/s, 25 fps, 25 tbr, 1200k tbn, 50 tbc

Sachant que la vitesse du flux est de 7000 kb/s et la taille du fichier, diviser la taille du fichier par 7000 kbit et multiplier par 8 donne immédiatement la durée probable en secondes.

Par exemple avec un fichier que j'ai ici (durée réelle du fichier 02:32:19, taille du fichier 733,802,496)

Stream #0:0: Video: ... 562 kb/s, 25 fps ...
Stream #0:1: Audio: ... 54 kb/s

562+54 est 616 kbits, soit 77 kbytes. 733 802 496 divisé par (77*1024) est 9306, et 9306 secondes sont 2 heures, 35 minutes, 6 secondes, ce qui n'est pas exactement correct, mais assez proche.

La précision réelle peut varier en fonction du codec utilisé, de la méthode d'entrelacement audio/vidéo, de l'éventuel remplissage et du fait qu'il s'agisse de CBR ou de VBR.

En l'absence de métadonnées fiables, si vous privilégiez la rapidité à la précision, je crains que l'estimation ne soit la voie à suivre.

Dans certains scénarios, vous pourriez être en mesure de faire les deux (fournir une estimation immédiate basée sur l'en-tête et la taille du fichier, puis commencer à lire lorsque l'interface utilisateur/le programme n'a rien de mieux à faire et affiner la réponse. Vous pourriez même sauvegarder les métadonnées nouvellement calculées quelque part, pour les récupérer si nécessaire par la suite - dans une base de données, un fichier de vignettes, un flux de données alternatif, ou même proposer de mettre à jour/"réparer" le fichier vidéo si possible).

Ligne de commande

Depuis la ligne de commande, en utilisant ffmpeg :

 #!/bin/bash

 if [ ! -r "$1" ]; then
     echo "File '$1' not found"
     exit 1
 fi
 FILESIZE=$( stat -c "%s" "$1" )
 STREAMS=$( 
      ffmpeg -i "$1" 2>&1 \
      | grep 'Stream #' \
      | tr "," "\n" \
      | grep "kb/s" \
      | tr " " "\n" \
      | grep "^[1-9][0-9]*$" )
 RATE=0
 for r in $STREAMS; do
     RATE=$[ $RATE + $r ]
 done
 # I don't think that bash has decimal support, so we use bc
 SECONDS=$( echo "$FILESIZE / $RATE" | bc )
 # To get seconds in HH:MM:SS format we use 'date'
 DURATION=$( TZ=UTC date +"%H:%M:%S" -d @$SECONDS )

Cela devrait être précis même si vous avez plusieurs flux audio dans un fichier vidéo. Je ne suis pas sûr de ce qui se passe s'il y a un flux de données tel que des sous-titres. La taille d'un tel flux ne devrait pas être très importante, donc il ne devrait pas interférer, mais là encore, cela pourrait être le cas.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X