How to extract duration time from ffmpeg output?

122,675

Solution 1

ffmpeg is writing that information to stderr, not stdout. Try this:

ffmpeg -i file.mp4 2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'

Notice the redirection of stderr to stdout: 2>&1

EDIT:

Your sed statement isn't working either. Try this:

ffmpeg -i file.mp4 2>&1 | grep Duration | awk '{print $2}' | tr -d ,

Solution 2

You can use ffprobe:

ffprobe -i <file> -show_entries format=duration -v quiet -of csv="p=0"

It will output the duration in seconds, such as:

154.12

Adding the -sexagesimal option will output duration as hours:minutes:seconds.microseconds:

00:02:34.12

Solution 3

From my experience many tools offer the desired data in some kind of a table/ordered structure and also offer parameters to gather specific parts of that data. This applies to e.g. smartctl, nvidia-smi and ffmpeg/ffprobe, too. Simply speaking - often there's no need to pipe data around or to open subshells for such a task.

As a consequence I'd use the right tool for the job - in that case ffprobe would return the raw duration value in seconds, afterwards one could create the desired time format on his own:

$ ffmpeg --version
ffmpeg version 2.2.3 ...

The command may vary dependent on the version you are using.

#!/usr/bin/env bash
input_file="/path/to/media/file"

# Get raw duration value
ffprobe -v quiet -print_format compact=print_section=0:nokey=1:escape=csv -show_entries format=duration "$input_file"

An explanation:

"-v quiet": Don't output anything else but the desired raw data value

"-print_format": Use a certain format to print out the data

"compact=": Use a compact output format

"print_section=0": Do not print the section name

":nokey=1": do not print the key of the key:value pair

":escape=csv": escape the value

"-show_entries format=duration": Get entries of a field named duration inside a section named format

Reference: ffprobe man pages

Solution 4

In case of one request parameter it is simplier to use mediainfo and its output formatting like this (for duration; answer in milliseconds)

mediainfo --Output="General;%Duration%" ~/work/files/testfiles/+h263_aac.avi 

outputs

24840

Solution 5

I recommend using json format, it's easier for parsing

ffprobe -i your-input-file.mp4 -v quiet -print_format json -show_format -show_streams -hide_banner

{
    "streams": [
        {
            "index": 0,
            "codec_name": "aac",
            "codec_long_name": "AAC (Advanced Audio Coding)",
            "profile": "HE-AACv2",
            "codec_type": "audio",
            "codec_time_base": "1/44100",
            "codec_tag_string": "[0][0][0][0]",
            "codec_tag": "0x0000",
            "sample_fmt": "fltp",
            "sample_rate": "44100",
            "channels": 2,
            "channel_layout": "stereo",
            "bits_per_sample": 0,
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/28224000",
            "duration_ts": 305349201,
            "duration": "10.818778",
            "bit_rate": "27734",
            "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
            }
        }
    ],
    "format": {
        "filename": "your-input-file.mp4",
        "nb_streams": 1,
        "nb_programs": 0,
        "format_name": "aac",
        "format_long_name": "raw ADTS AAC (Advanced Audio Coding)",
        "duration": "10.818778",
        "size": "37506",
        "bit_rate": "27734",
        "probe_score": 51
    }
}

you can find the duration information in format section, works both for video and audio

Share:
122,675
Louise
Author by

Louise

Updated on July 08, 2022

Comments

  • Louise
    Louise almost 2 years

    To get a lot of information about a media file one can do

    ffmpeg -i <filename>
    

    where it will output a lot of lines, one in particular

    Duration: 00:08:07.98, start: 0.000000, bitrate: 2080 kb/s
    

    I would like to output only 00:08:07.98, so I try

    ffmpeg -i file.mp4 | grep Duration| sed 's/Duration: \(.*\), start/\1/g'
    

    But it prints everything, and not just the length.

    Even ffmpeg -i file.mp4 | grep Duration outputs everything.

    How do I get just the duration length?

  • potong
    potong over 12 years
    Grep is unnecessary,sed -n 's/Duration: \(.*\), start/\1/gp' is suffice.
  • ДМИТРИЙ МАЛИКОВ
    ДМИТРИЙ МАЛИКОВ over 11 years
    Actually, sed is unnecessary: ffmpeg -i file.mp4 2>&1 | grep -o -P "(?<=Duration: ).*?(?=,)"
  • vertigoelectric
    vertigoelectric about 11 years
    What's the context for this if I want to store the duration as a variable to be used within the same PHP script?
  • praxmon
    praxmon over 10 years
    How to do the same thing in Python?
  • Pogrindis
    Pogrindis about 10 years
    This should be 'mediainfo --Inform="General;%Duration%" ~/work/files/testfiles/+h263_aac.avi'
  • Sunry
    Sunry about 10 years
    For my ffmpeg-0.6.5-1.el6.rf.x86_64, the format is: ffprobe <file> -show_format 2>&1 | sed -n 's/duration=//p'
  • Saucier
    Saucier about 10 years
    In my opinion that's the wrong tools for the job. Why pipe the data around if ffmpeg/ffprobe offers tools to access the raw data?
  • nha
    nha almost 10 years
    Is there something I can do when the result is : "Duration: N/A, bitrate: N/A" ? I use this file : media.xiph.org/video/derf/y4m/suzie_qcif.y4m
  • llogan
    llogan almost 10 years
    The counterfeit "ffmpeg" from Libav (a fork of the FFmpeg project) has been replaced by avconv from Libav. ffmpeg from FFmpeg is under very active development.
  • Pirkka Esko
    Pirkka Esko over 9 years
    This is the way to go. ffmpeg -i always wanted to transcode a new file after printing the data. Way cleaner solution right here.
  • Pirkka Esko
    Pirkka Esko over 9 years
    Using ffprobe as instructed in other answers seems a way cleaner and hassle-free-er approach :)
  • bovender
    bovender over 8 years
    Should be the accepted answer, although the output format (seconds) is not quite exactly what was asked for.
  • llogan
    llogan over 8 years
    @bovender Answer updated with option to output desired format.
  • bovender
    bovender over 8 years
    @LordNeckbeard Now it really should be the accepted answer!
  • FtheBuilder
    FtheBuilder almost 8 years
    This helped me a lot man! congrats. I wanted the total amount of seconds...
  • llogan
    llogan over 7 years
    grep, cut, and sed are unecessary. See Ivan's answer.
  • sparsh turkane
    sparsh turkane over 7 years
    why unnecessary i don't understand it gives the result
  • llogan
    llogan over 7 years
    Because you can just use ffprobe alone. Also, the output of ffmpeg is for informational purposes only and not for parsing: it is not guaranteed to always about the same structure, format, and information with various ffmpeg versions and various input formats.
  • Tina J
    Tina J almost 7 years
    @LordNeckbeard what is the edit to get exactly in seconds integer (no float points? e.g. 154
  • gemelen
    gemelen about 6 years
    Both forms work identically within mediainfo v18.05 (and seems to be with previous versions).
  • Alexander Korzhykov
    Alexander Korzhykov over 5 years
    @PirkkaEsko ffmpeg will report the correct duration in some cases when using ffprobe gives you incorrect or missing duration due to corrupt, truncated, or damaged files.
  • petezurich
    petezurich over 5 years
    @PrakharMohanSrivastava See my answer for using a python script to retrieve length and other metadata.
  • Rabindranath Andujar
    Rabindranath Andujar over 4 years
    This code doesn't work: Traceback (most recent call last): File "ffprobe.py", line 9, in <module> print("Length of file is: {}".format(float(length["format"]["duration"]))) NameError: name 'length' is not defined This should do the job: import subprocess import json input_file = "out.mp4" metadata = subprocess.check_output(f"ffprobe -i {input_file} -v quiet -print_format json -show_format -hide_banner".split(" ")) metadata = json.loads(metadata) print("Length of file is: {}".format(float(metadata["format"]["duration"]))) print(metadata)
  • petezurich
    petezurich over 4 years
    @RabindranathAndujar I rechecked. You are right. The code works, but the line for the printout had an error in it. I corrected the code and now it runs fine. Thanks for pointing it out.
  • Matt W
    Matt W over 4 years
    Thank you! This is exactly what I needed!
  • agarg
    agarg about 4 years
    This script will fail for filenames with special characters on both linux and windows
  • Ray Woodcock
    Ray Woodcock almost 4 years
    Alternately ffprobe -i "input.mp4" -show_entries format=duration -v quiet -of csv="p=0" -sexagesimal
  • Tovi Newman
    Tovi Newman almost 4 years
    Careful though. ffprobe reads metadata. Depending on the file source this could be inaccurate.
  • phuclv
    phuclv over 3 years
    calling strlen everytime is a bad idea, and correct[strlen(time)]='/0'; is definitely wrong. It should be '\0' instead of '/0'
  • ychaouche
    ychaouche about 3 years
    Actually, both grep and sed are unnecessary : awk '/Duration/ {print $2}'
  • Alexander C
    Alexander C over 2 years
    Excellent. Machine readable answer!
  • jarno
    jarno about 2 years
    Very fast compared to ffmpeg or ffprobe.
  • jarno
    jarno about 2 years
    --Inform is the way told in the manual page.