129

How can I get video duration in seconds?

What I've tried:

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

This what close, but it's not so accurate, 2383 is 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
0

10 Answers 10

65

To get minutes, you have to divide 2383 seconds by 60.

39.7167

and then multiply the fractional part .7167 by 60 to get the remaining seconds.

43.002

So it's 39 minutes, 43 seconds. The application appears to be giving you an accurate value.

1
  • 4
    Best answer because you identified the problem in the given solution. Most people would suggest a new solution. Apr 25, 2020 at 14:51
217

Just use ffprobe directly. No need for sed, grep, etc. There are several "durations" you can acquire (depending on your input).

Format (container) duration

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

Result:

30.024000

Adding the -sexagesimal option will use the HOURS:MM:SS.MICROSECONDS time unit format:

0:00:30.024000

Video stream duration

If you want the duration of a particular video or audio stream:

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

Result:

30.000000

The above commands are from FFmpeg Wiki: FFprobe Tips.

With ffmpeg

You can use ffmpeg to get duration by decoding the input:

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 this example time=00:01:03.48 is the duration.

This may take a long time depending on your input file.

8
  • These do not work for .m2v files do you have a solution for them aswell
    – utdev
    Jan 5, 2017 at 9:47
  • @utdev See the "With ffmpeg" section.
    – llogan
    Jan 5, 2017 at 18:39
  • Your third solution gives me a wrong time, my video has a length of 01:19:00 but the command returns me time=01:09:15.32, do you have a guess why this is happening
    – utdev
    Feb 15, 2017 at 10:59
  • Very useful the media stream duration. Thank you. Apr 20, 2018 at 9:40
  • 1
    For anyone using avprobe, the parameters are slightly different: avprobe -v error -show_format_entry duration .\Sample.mp4
    – Brad
    Jun 18, 2019 at 22:25
39

If you have ffmpeg, you should also have ffprobe:

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

This will also give fractions of seconds, if that's a problem you can further process that away with sed.

3
  • how can I remove the fraction part of seconds?
    – Tina J
    Aug 18, 2017 at 13:42
  • @TinaJ Just pipe it with printf, like | xargs printf %.0f - this will return an integer value.
    – Ilia
    Aug 14, 2018 at 9:21
  • @TinaJ Also if you don't want to round value mathematically but want just to remove decimal part you can assign the duration to a variable duration=$(ffprobe -i input.file -show_format -v quiet | sed -n 's/duration=//p') And remove decimal part echo ${duration%.*}
    – C0DEF52
    May 18, 2020 at 11:18
9
mediainfo --Output='General;%Duration%' file.flv

This outputs the duration in milliseconds as a single integer value. No need for grep/cut/sed/...

1
  • Thanks - this was just what I was looking for. Can be installed on MacOS with brew install mediainfo
    – Alex K
    Nov 22, 2018 at 17:32
3

Solution with mplayer that gives seconds directly:

mplayer -identify -frames 0 -vo null -nosound file.flv 2>&1 | awk -F= '/LENGTH/{print $2}'
0
2

For my ffmpeg-0.6.5-1.el6.rf.x86_64, to get just the second, ffprobe command format is:

ffprobe <file> -show_format 2>&1 | sed -n 's/duration=//p' 
2
  • 1
    how can I remove the fraction part of seconds?
    – Tina J
    Aug 18, 2017 at 13:42
  • To remove fraction part, use: sed -n -E 's/duration=([0-9]+).*/\1/p which extracts the first matching numbers (discarding anything after a non-numeric symbol) using a backreference (\1, which only works with the -E option).
    – Yeti
    Jul 16, 2020 at 12:46
1

Python

You can extract streams using following code

import json

infile = "<path to your file>"
command = "ffprobe -v quiet -print_format json -show_format  -show_streams {}".format(infile)
res = json.loads(subprocess.check_output(command, shell=True))
streams = res.get('streams')

Each stream would have a field duration.

Special case of Webm

If your input file is webm, Your method of extracting stream duration is going to be different, since the standard store it in a different location. In each stream you would see a field 'tags'

"tags": {
                "language": "eng",
                "HANDLER_NAME": "ISO Media file produced by Google Inc. Created on: 12/09/2019.",
                "VENDOR_ID": "[0][0][0][0]",
                "ENCODER": "Lavc59.4.101 libvorbis",
                "DURATION": "00:03:14.703000000"
            }

You would have to convert this human readable time format into seconds. Which you can easily do with following utility function.

def convert_secs(text):
    if isinstance(text, float):
        num = str(text)
        nums = num.split('.')
    else:
        nums = text.split(':')
    if len(nums) == 2:
        st_sn = int(nums[0]) * 60 + float(nums[1])
        return st_sn
    elif len(nums) == 3:
        st_sn = int(nums[0]) * 3600 + int(nums[1]) * 60 + float(nums[2])
        return st_sn
    else:
        raise ValueError("Not correct time")
0

I came across the issue of getting some strange and incorrect metadata from some video files I was working with and I couldn't succeed on finding a pattern or any type of handling using code and tools like ffmpeg, mp4box, ffprobe, mediainfo, mplayer, to get the real duration of the video.

Identifying the real duration of the video was a requirement for a project I was working and the only way I found to get it always right was to reencode the video file using ffmpeg and forcing encoded files to ignore original file's metadata, like:

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

(This might run faster than you expect. I got surprised, for the type of content and on the environment I was using, average time was 2 seconds)

... and then get duration using a tool at your choice. I like mediainfo, btw: - "mediainfo FILE --Inform="Video;%Duration%" gives you duration in miliseconds.

1
  • You did not provide more information or better solution than other answers
    – Sam
    Jun 1, 2017 at 7:36
0

If you only need to query metadata:

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

[...]

streams.stream.0.duration="5221.146009"

[...]

So you can parse it:

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)

But if you want to get the effective container's duration, you need to decode it:

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

It will take some CPU time to decode it, until:

[...]

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

Then, you can parse it:

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
# Returns duration (in seconds) of a video $1 (uses ffmpeg).
get_video_duration() {
  OUTPUT=$(ffmpeg -i "$1" -vframes 1 -f rawvideo -y /dev/null 2>&1) ||
    { debug -e "get_video_duration: error running ffmpeg:\n$OUTPUT"; return 1; }
  DURATION=$(echo "$OUTPUT" | grep -m1 "^[[:space:]]*Duration:" |
    cut -d":" -f2- | cut -d"," -f1 | sed "s/[:\.]/ /g") || 
    { debug -e "get_video_duration: error parsing duration:\n$OUTPUT"; return 1; }
  read HOURS MINUTES SECONDS DECISECONDS <<< "$DURATION"
  echo $((10#$HOURS * 3600 + 10#$MINUTES * 60 + 10#$SECONDS))      
}

Usage:DURATION=$(get_video_duration "$VIDEO")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.