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

Hoe krijg ik de duur van een video in seconden?

Hoe krijg ik de video duur in seconden?

Wat ik geprobeerd heb:

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

Dit wat er dichtbij, maar het is niet zo nauwkeurig, 2383 is 39.71 minuten

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

Antwoorden (9)

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

Gebruik gewoon direct ffprobe. Geen behoefte aan sed, grep, enz. Er zijn verschillende “durations” die je kunt verkrijgen (afhankelijk van je invoer).

Formaat (container) duur

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

30.024000

Door de -sexagesimal optie toe te voegen wordt de HOURS:MM:SS.MICROSECONDS tijdseenheid formaat gebruikt:

0:00:30.024000

Video stream duur

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

De bovenstaande commando’s komen uit FFmpeg Wiki: FFprobe Tips .

Met ffmpeg

Het kan nodig zijn om de invoer volledig te decoderen als je merkt dat de container of stream duur ontbreekt of onnauwkeurig is (mogelijk door een beschadigd of afgekapt bestand).

$ 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

In dit voorbeeld is time=00:01:03.48 de duur:

Hoe lang dit zal duren hangt natuurlijk af van de complexiteit van het decoderen en de duur van uw invoer en de mogelijkheden van uw computer.

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

Om minuten te krijgen, moet je 2383 seconden delen door 60.

39.7167

en dan het breukdeel .7167 met 60 vermenigvuldigen om de resterende seconden te krijgen.

43.002

Dus het is 39 minuten, 43 seconden. De applicatie lijkt je een accurate waarde te geven.

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

Als je ffmpeg hebt, zou je ook ffprobe moeten hebben:

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

Dit geeft ook fracties van seconden, als dat een probleem is kun je dat verder wegwerken met sed.

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

Dit geeft de tijdsduur in milliseconden als een enkele gehele waarde. Geen behoefte aan grep/cut/sed/…

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

Oplossing met mplayer die direct seconden geeft:

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

Voor mijn ffmpeg-0.6.5-1.el6.rf.x86_64, om alleen de tweede te krijgen, ffprobe commando formaat is:

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

Als je alleen metadata moet opvragen:

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

[…]

streams.stream.0.duration="5221.146009"

[…]

Dus je kunt het parseren:

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)

Maar als je de effectieve containerduur wilt krijgen, moet je het decoderen:

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

Het zal wat CPU-tijd kosten om het te decoderen, tot:

[…]

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

Dan kun je het ontleden:

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

Ik kwam het probleem tegen van het krijgen van een aantal vreemde en onjuiste metadata van sommige videobestanden waar ik mee werkte en ik kon er niet in slagen om een patroon te vinden of een soort van behandeling met behulp van code en tools zoals ffmpeg, mp4box, ffprobe, mediainfo, mplayer, om de echte duur van de video te krijgen.

Het identificeren van de echte duur van de video was een vereiste voor een project waar ik aan werkte en de enige manier die ik vond om het altijd goed te krijgen was om het videobestand opnieuw te coderen met ffmpeg en gecodeerde bestanden te dwingen de metadata van het originele bestand te negeren, zoals:

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

(Dit kan sneller gaan dan je verwacht. Ik was verrast, dat voor het type inhoud en de omgeving die ik gebruikte, de gemiddelde tijd 2 seconden was)

… en haal dan de duur op met een tool naar keuze. Ik hou van mediainfo, trouwens: - “mediainfo FILE –Inform="Video;%Duration%” geeft je de duur in miliseconden.

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

Als je een ACCURATE tijdsduur wilt, vergeet FFmpeg. Het geeft alleen een schatting op basis van de bestandsgrootte en de gemiddelde bitrate. Ik heb ontdekt, in sommige gevallen, dat de geschatte tijdsduur er 2x naast zit!

Op Linux, als het bestand alleen tijdens de video-opname wordt aangemaakt en gewijzigd, zou een alternatieve oplossing zijn om de aanmaak- en laatste wijzigingstijd te gebruiken om de duur te berekenen, zoals in:

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