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.