7

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
William Pursell
  • 204,365
  • 48
  • 270
  • 300
user2783132
  • 225
  • 1
  • 3
  • 16
  • 1
    See also [How to extract duration time from ffmpeg output?](http://stackoverflow.com/questions/6239350/how-to-extract-duration-time-from-ffmpeg-output) – user May 07 '14 at 02:14

8 Answers8

11

There is a better, faster and low CPU/HD footprint solution, just with mediainfo without relying into awk:

mediainfo --Inform="General;%Duration%" input.m4v
Rodrigo Polo
  • 4,314
  • 2
  • 26
  • 32
  • Note this gives you milliseconds and is therefore more accurate than any of the `grep` / `awk` variations. For example: `mediainfo --Inform="General;%Duration%" video.mp4` --> `204466` while `mediainfo video.mp4 | grep '^Duration'` --> `Duration : 3 min 24 s` (= 204000ms) – trs Aug 14 '18 at 04:36
4

2383 is correct. There are 60 seconds in a minute, not 100. 43/60 = .71

https://www.google.com/#q=39+minutes+43.08+seconds+in+seconds

szatmary
  • 29,969
  • 8
  • 44
  • 57
4

Using awk

mediainfo file.flv | awk '/Duration/ {print $3*60+$4}'
2383

ffmpeg -i file.flv 2>&1 | awk '/Duration/ {split($2,a,":");print a[1]*3600+a[2]*60+a[3]}'
2383.08

To handle different formats, use this:

cat file
Duration : 39mn 43s
Duration : 39s 43ms

awk '/Duration/ {for (i=3;i<=NF;i++) if ($i~/[0-9]+mn$/) s+=$i*60; else if ($i~/[0-9]+s$/) s+=$i; else if ($i~/[0-9]+ms$/) s+=$i/10; print s;s=0}'  file
2383
43.3
Jotne
  • 40,548
  • 12
  • 51
  • 55
  • Thanks Jotne, just what I was looking for! – Ilia Ross Apr 16 '14 at 19:28
  • Found a bug. If the video's length is smaller than 1min, then your *mediainfo* example doesn't do it correctly, as the *mediainfo* outputs time in different format, e.g.: `Duration : 36s 360ms` and it results using your code in **2520**. Please fix. – Ilia Ross Apr 16 '14 at 19:35
  • @IliaRostovtsev are you the same person as the poster of the question `user2783132`? – Jotne Apr 18 '14 at 05:18
  • No! :) He had the same issue, I can tell now.. – Ilia Ross Apr 18 '14 at 05:20
3

Its Working for me try it :)

$duration = shell_exec("ffmpeg -i \"". $input . "\" 2>&1");

preg_match("/Duration: (\d{2}:\d{2}:\d{2}\.\d{2})/",$duration,$matches);
$time = explode(':',$matches[1]);
$hour = $time[0];
$minutes = $time[1];
$seconds = round($time[2]);

$total_seconds = 0;
$total_seconds += 60 * 60 * $hour;
$total_seconds += 60 * $minutes;
echo $total_seconds += $seconds;
2

You can use

ffprobe -v quiet -print_format xml -show_format -show_streams inputfile.flv

it will return an xml like this

<?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
    <streams>
        <stream index="0" codec_name="h264" codec_long_name="H.264 / AVC / MPEG-4 AVC / 
    MPEG-4 part 10" profile="High" codec_type="video" codec_time_base="1/50" codec_tag_string="avc1" codec_tag="0x31637661" width="1920" height="1080" has_b_frames="2" sample_aspect_ratio="0:1" display_aspect_ratio="0:1" pix_fmt="yuvj420p" level="40" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/12800" start_pts="0" start_time="0.000000" duration_ts="50176" duration="3.920000" bit_rate="4347640" nb_frames="98">
                <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
                <tag key="language" value="eng"/>
                <tag key="handler_name" value="VideoHandler"/>
            </stream>
        <stream index="1" codec_name="aac" codec_long_name="AAC (Advanced Audio Coding)" codec_type="audi

o" codec_time_base="1/48000" codec_tag_string="mp4a" codec_tag="0x6134706d" sample_fmt="fltp" sample_rate="48000" channels="2" bits_per_sample="0" r_frame_rate="0/0" avg_frame_rate="0/0" time_base="1/48000" start_pts="-1024" start_time="-0.021333" duration_ts="189184" duration="3.941333" bit_rate="122277" nb_frames="185">
            <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
            <tag key="language" value="eng"/>
            <tag key="handler_name" value="SoundHandler"/>
        </stream>
    </streams>

    <format filename="inputfile.flv" nb_streams="2" format_name="mov,mp4,m4a,3gp,3g2,mj2" format_long_name="QuickTime / MOV" start_time="-0.021333" duration="3.942000" size="2194901" bit_rate="4454390">
        <tag key="major_brand" value="isom"/>
        <tag key="minor_version" value="512"/>
        <tag key="compatible_brands" value="isomiso2avc1mp41"/>
        <tag key="encoder" value="Lavf54.63.100"/>
    </format>
</ffprobe>

then filter by the video stream i.e. usually that with attribute index ="0" and get the value of the attribute "duration" which is already in seconds.

Ilia Ross
  • 13,086
  • 11
  • 53
  • 88
athina.bikaki
  • 729
  • 7
  • 5
1

I used this in php:

exec('mediainfo --Inform="General;%Duration%" ' . $filename, $output);
// type 86 sec = 85962.695312
$durationInSec = ceil(ceil($output[0])/1000);
Kristian
  • 2,071
  • 23
  • 15
0

In case you have ffmpeg installed, most likely you would have ffprobe installed too.

ffprobe -i file.mp4 -show_format -v quiet | sed -n 's/duration=//p' | xargs printf %.0f

The command will return an integer value.

Output example:

190

Ilia Ross
  • 13,086
  • 11
  • 53
  • 88
  • 1
    I also wanted an output in the format of hh:mm:ss.ms, but I had to slightly modify the command you suggest to get what I needed. I replaced `Video` with `General` to give the command `--Inform="General;%Duration/String3%"`. MediaInfo version 0.7.69 – ubiquibacon Jun 06 '14 at 04:17
  • You're not converting the value to seconds, you are cutting the ms portion off instead of rounding. So your result is not accurate. You could just as easily cut the last 3 digits of the value given by Rodrigo's answer and leave out the detour through php and string parsing. – trs Aug 14 '18 at 04:40
  • @trs Agree. I didn't like my own, old answer, so I've edited it. – Ilia Ross Aug 14 '18 at 09:20
0

If you have ffmpeg, you should also have ffprobe. It outputs information to STDOUT in a series of key=value pairs, and gives the duration in seconds by default (you have to use the -sexagesimal option if you want hh:mm:ss):

ffprobe -show_format file.mp4 | grep -F duration | cut -d= -f2
evilsoup
  • 236
  • 2
  • 3