2013-09-25 19:35:33 +0000 2013-09-25 19:35:33 +0000
75
75

Comment obtenir la durée d'une vidéo en quelques secondes ?

Comment puis-je obtenir la durée d'une vidéo en quelques secondes ?

Ce que j'ai essayé :

ffmpeg -i file.flv 2>&1 | grep "Duration"
  Duration: 00:39:43.08, start: 0.040000, bitrate: 386 kb/s

mediainfo file.flv | grep Duration
Duration : 39mn 43s

C'est ce qui se rapproche, mais ce n'est pas aussi précis, 2383 est de 39,71 minutes

ffmpeg -i file.flv 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }'
2383

Réponses (9)

105
105
105
2015-07-26 22:07:37 +0000

Il suffit d'utiliser ffprobe directement. Pas besoin de sed, grep, etc. Il existe plusieurs “durées” que vous pouvez acquérir (en fonction de votre saisie).

Format (conteneur) durée

$ ffprobe -v error -show_entries format=duration \
  -of default=noprint_wrappers=1:nokey=1 input.mp4

30.024000

L'ajout de l'option -sexagesimal utilisera le format d'unité de temps HOURS:MM:SS.MICROSECONDS :

0:00:30.024000

Durée du flux vidéo

$ ffprobe -v error -select_streams v:0 -show_entries stream=duration \
  -of default=noprint_wrappers=1:nokey=1 input.mp4
30.000000

Les commandes ci-dessus proviennent de FFmpeg Wiki : FFprobe Tips .

Avec ffmpeg

Vous devrez peut-être décoder complètement l'entrée si vous trouvez que le conteneur ou la durée du flux est manquant ou inexact (peut-être à cause d'un fichier endommagé ou tronqué).

$ ffmpeg -i input.mp4 -f null -
  …
  frame= 1587 fps=0.0 q=0.0 Lsize=N/A time=00:01:03.48 bitrate=N/A

Dans cet exemple, time=00:01:03.48 est la durée :

La durée dépendra bien sûr de la complexité du décodage et de la durée de votre saisie ainsi que des capacités de votre ordinateur.

35
35
35
2013-09-25 19:41:05 +0000

Pour obtenir des minutes, il faut diviser 2383 secondes par 60.

39.7167

et ensuite multiplier la partie fractionnaire .7167 par 60 pour obtenir les secondes restantes.

43.002

Donc, c'est 39 minutes, 43 secondes. L'application semble vous donner une valeur précise.

34
34
34
2013-09-25 21:10:07 +0000

Si vous avez ffmpeg, vous devriez aussi avoir ffprobe :

ffprobe -i input.file -show_format | grep duration
ffprobe -i input.file -show_format -v quiet | sed -n 's/duration=//p'

Cela donne aussi des fractions de secondes, si c'est un problème, vous pouvez continuer à traiter cela avec sed.

3
3
3
2018-05-05 08:00:38 +0000
mediainfo --Output='General;%Duration%' file.flv

Cela donne la durée en millisecondes comme une seule valeur entière. Pas besoin de grep/cut/sed/…

3
3
3
2013-09-25 19:56:50 +0000

Solution avec mplayer qui donne directement les secondes :

mplayer -identify -frames 0 -vo null -nosound file.flv 2>&1 | awk -F= '/LENGTH/{print $2}'
3
3
3
2014-06-16 22:06:49 +0000

Pour mon ffmpeg-0.6.5-1.el6.rf.x86_64, pour n'obtenir que le second, le format de la commande ffprobe est :

ffprobe <file> -show_format 2>&1 | sed -n 's/duration=//p'
0
0
0
2019-08-30 19:39:55 +0000

Si vous avez seulement besoin d'interroger les métadonnées :

ffprobe -hide_banner -v quiet -show_streams -print_format flat video.mp4

[…]

streams.stream.0.duration="5221.146009"

[…]

Donc vous pouvez l'analyser :

while read -r; do
  if [["$REPLY" =~ ^streams\.stream\.([0-9])+\.duration=\"([^"]+)\"$ ]]; then
    echo -E Duration of stream "${BASH_REMATCH[1]}": "${BASH_REMATCH[2]}"
  fi
done < <(ffprobe -hide_banner -v quiet -show_streams -print_format flat video.mp4)

Mais si vous voulez obtenir la durée effective du conteneur, vous devez le décoder :

AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i video.mp4 -f null -c copy - 2>&1 | tail -n 2

Il faudra un certain temps CPU pour le décoder, jusqu'à :

[…]

frame=130527 fps=53271 q=-1.0 Lsize=N/A time=01:27:01.12 bitrate=N/A speed=2.13e+03x
video:152014kB audio:40790kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Ensuite, vous pouvez l'analyser :

if [["$(AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i video.mp4 -f null -c copy - 2>&1 | tail -n 2 | head -n 1)" =~ \ time=([0-9]+):([0-9]{2}):([0-9]{2})\.([0-9]+) ]]; then
  declare duration=0 us="${BASH_REMATCH[4]}" t
  for t in "${BASH_REMATCH[@]:1:3}"; do
    ((duration *= 60))
    ((duration += ${t#0} ))
  done
  while [${#us} -lt 6]; do us+=0; done
  ((us >= 500000)) && ((duration++))
  ((duration)) || ((duration++))
fi
echo -E Duration: "$duration"
0
0
0
2017-06-01 01:01:24 +0000

Je suis tombé sur le problème de l'obtention de métadonnées étranges et incorrectes à partir de certains fichiers vidéo avec lesquels je travaillais et je n'ai pas réussi à trouver un modèle ou un quelconque type de manipulation en utilisant du code et des outils comme ffmpeg, mp4box, ffprobe, mediainfo, mplayer, pour obtenir la durée réelle de la vidéo.

Identifier la durée réelle de la vidéo était une exigence pour un projet sur lequel je travaillais et la seule façon que j'ai trouvée pour que cela soit toujours correct était de réencoder le fichier vidéo en utilisant ffmpeg et en forçant les fichiers encodés à ignorer les métadonnées du fichier original, par exemple :

ffmpeg -i INPUT_FILENAME -acodec copy -vcodec copy -map_metadata -1 OUTPUT_FILENAME"

(Cela peut être plus rapide que vous ne le pensez. J'ai été surpris, pour le type de contenu et sur l'environnement que j'utilisais, le temps moyen était de 2 secondes)

… et ensuite obtenir la durée en utilisant un outil à votre choix. J'aime bien mediainfo, à propos : - “mediainfo FILE –Inform="Video;%Duration%” vous donne la durée en millisecondes.

-6
-6
-6
2015-04-27 01:59:24 +0000

Si vous voulez une durée PRECISE, oubliez FFmpeg. Il ne donne qu'une estimation basée sur la taille des fichiers et le débit moyen. J'ai trouvé, dans certains cas, l'estimation de la durée 2x plus longue !

Sous Linux, si le fichier est créé et modifié uniquement pendant ledit enregistrement vidéo, une autre solution serait d'utiliser le temps de création et de dernière modification pour calculer la durée, comme dans :

stat -c "%X %Y" video.mpg | awk '{print $2 - $1}'