How to extract duration time from ffmpeg output?

LinuxBashFfmpeg

Linux Problem Overview


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?

Linux Solutions


Solution 1 - Linux

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 2 - Linux

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 3 - Linux

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 - Linux

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 - Linux

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

Solution 6 - Linux

If you want to retrieve the length (and possibly all other metadata) from your media file with ffmpeg by using a python script you could try this:

import subprocess
import json

input_file  = "< path to your input file here >"

metadata = subprocess.check_output(f"ffprobe -i {input_file} -v quiet -print_format json -show_format -hide_banner".split(" "))

metadata = json.loads(metadata)
print(f"Length of file is: {float(metadata['format']['duration'])}")
print(metadata)

Output:

Length of file is: 7579.977143

{
  "streams": [
    {
      "index": 0,
      "codec_name": "mp3",
      "codec_long_name": "MP3 (MPEG audio layer 3)",
      "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/14112000",
      "start_pts": 353600,
      "start_time": "0.025057",
      "duration_ts": 106968637440,
      "duration": "7579.977143",
      "bit_rate": "320000",
      ...
      ...

Solution 7 - Linux

For those who want to perform the same calculations with no additional software in Windows, here is the script for command line script:

set input=video.ts

ffmpeg -i "%input%" 2> output.tmp

rem search "  Duration: HH:MM:SS.mm, start: NNNN.NNNN, bitrate: xxxx kb/s"
for /F "tokens=1,2,3,4,5,6 delims=:., " %%i in (output.tmp) do (
    if "%%i"=="Duration" call :calcLength %%j %%k %%l %%m
)
goto :EOF

:calcLength
set /A s=%3
set /A s=s+%2*60
set /A s=s+%1*60*60
set /A VIDEO_LENGTH_S = s
set /A VIDEO_LENGTH_MS = s*1000 + %4
echo Video duration %1:%2:%3.%4 = %VIDEO_LENGTH_MS%ms = %VIDEO_LENGTH_S%s

Same answer posted here: https://stackoverflow.com/questions/20502298/how-to-crop-last-n-seconds-from-a-ts-video/20551848#20551848

Solution 8 - Linux

ffmpeg -i abc.mp4 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//

gives output

HH:MM:SS.milisecs

Solution 9 - Linux

# 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")

Solution 10 - Linux

This is my really simple solution using ffmpeg and awk. The output of ffmpeg -i file.mp3 contain a string Duration: 00:00:04.80, bitrate: 352 kb/s. Just simply using awk:

ffmpeg -i file.mp3 |& awk '/Duration:/ {print $2}'

I can print the expected result: 00:00:04.80

Solution 11 - Linux

use ffprobe which is used to extract metadata from media files

install ffprobe with pip

pip install ffprobe-python

`from subprocess import check_output

file_name = "video1.mp4"

command = str(check_output('ffprobe -i "'+file_name+'" 2>&1 |grep "Duration"',shell=True))
#output: b' Duration: 00:17:56.62, start: 0.000000, bitrate: 397 kb/s\n'

#split the duration in hh:mm:ss format co = a.split(",")[0].split("Duration:")[1].strip()

h, m, s = a.split(':') duration = int(h) * 3600 + int(m) * 60 + float(s)

print(duration)`

Solution 12 - Linux

I would just do this in C++ with a text file and extract the tokens. Why? I am not a linux terminal expert like the others.

To set it up I would do this in Linux

ffmpeg -i <file> 2>&1 | grep "" > mytext.txt

and then run some C++ app to get the data needed. Maybe extract all the important values and reformat it for further processing by using tokens. I will just have to work on my own solution and people will just make fun of me because I am a Linux newbie and I do not like scripting too much.

Solution 13 - Linux

Argh. Forget that. It looks like I have to get the cobwebs out of my C and C++ programming and use that instead. I do not know all the shell tricks to get it to work.

This is how far I got.

ffmpeg -i myfile 2>&1 | grep "" > textdump.txt

and then I would probably extract the duration with a C++ app instead by extracting tokens.

I am not posting the solution because I am not a nice person right now


Update - I have my approach to getting that duration time stamp

Step 1 - Get the media information on to a text file

ffprobe -i myfile 2>&1 | grep "" > textdump.txt

OR

ffprobe -i myfile 2>&1 | awk '{ print }' > textdump.txt

Step 2 - Home in on the information needed and extract it

cat textdump.txt |  grep "Duration" | awk '{ print $2 }' | ./a.out

Notice the a.out. That is my C code to chop off the resulting comma because the output is something like 00:00:01.331,

Here is the C code that takes stdin and outputs the correct information needed. I had to take the greater and less than signs out for viewing.

#include stdio.h
#include string.h
void main()
{
//by Admiral Smith Nov 3. 2016
char time[80];
int len;
char *correct;
scanf("%s", &time);
correct = (char *)malloc(strlen(time));
if (!correct)
{
	printf("\nmemory error");
	return;
}
memcpy(correct,&time,strlen(time)-1);
correct[strlen(time)]='/0';
printf("%s", correct);
free(correct);
}

Now the output formats correctly like 00:00:01.33

Solution 14 - Linux

Best Solution: cut the export do get something like 00:05:03.22

ffmpeg -i input 2>&1 | grep Duration | cut -c 13-23

Solution 15 - Linux

You could try this:

/*
* Determine video duration with ffmpeg
* ffmpeg should be installed on your server.
*/
function mbmGetFLVDuration($file){

  //$time = 00:00:00.000 format
  $time =  exec("ffmpeg -i ".$file." 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//");

  $duration = explode(":",$time);
  $duration_in_seconds = $duration[0]*3600 + $duration[1]*60+ round($duration[2]);

  return $duration_in_seconds;

}

$duration = mbmGetFLVDuration('/home/username/webdir/video/file.mov');
echo $duration;

Solution 16 - Linux

ffmpeg has been substituted by avconv: just substitute avconb to Louis Marascio's answer.

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

Note: the aditional .* after start to get the time alone !!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLouiseView Question on Stackoverflow
Solution 1 - LinuxIvan NeesonView Answer on Stackoverflow
Solution 2 - LinuxLouis MarascioView Answer on Stackoverflow
Solution 3 - LinuxSaucierView Answer on Stackoverflow
Solution 4 - LinuxgemelenView Answer on Stackoverflow
Solution 5 - LinuxvivisideaView Answer on Stackoverflow
Solution 6 - LinuxpetezurichView Answer on Stackoverflow
Solution 7 - LinuxdigitalfootmarkView Answer on Stackoverflow
Solution 8 - Linuxsparsh turkaneView Answer on Stackoverflow
Solution 9 - LinuxMuhammad AbdullahView Answer on Stackoverflow
Solution 10 - LinuxMario SantoroView Answer on Stackoverflow
Solution 11 - LinuxSadhana SinghView Answer on Stackoverflow
Solution 12 - LinuxAdmiralSmithView Answer on Stackoverflow
Solution 13 - LinuxAdmiralSmithView Answer on Stackoverflow
Solution 14 - LinuxMikeView Answer on Stackoverflow
Solution 15 - LinuxManawatuHonkyView Answer on Stackoverflow
Solution 16 - LinuxmuraliscView Answer on Stackoverflow