How to get video duration in seconds?

18,107

Solution 1

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

Solution 2

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

mediainfo --Inform="General;%Duration%" input.m4v

Solution 3

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

Solution 4

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;

Solution 5

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.

Share:
18,107
user2783132
Author by

user2783132

Updated on June 12, 2022

Comments

  • user2783132
    user2783132 almost 2 years

    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
    
  • Ilia
    Ilia about 10 years
    Thanks Jotne, just what I was looking for!
  • Ilia
    Ilia about 10 years
    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.
  • Jotne
    Jotne about 10 years
    @IliaRostovtsev are you the same person as the poster of the question user2783132?
  • Ilia
    Ilia about 10 years
    No! :) He had the same issue, I can tell now..
  • Jotne
    Jotne about 10 years
    @IliaRostovtsev see my updated post
  • ubiquibacon
    ubiquibacon almost 10 years
    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
  • trs
    trs over 5 years
    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
    trs over 5 years
    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.
  • Ilia
    Ilia over 5 years
    @trs Agree. I didn't like my own, old answer, so I've edited it.