9

Is there a script(bash, python etc.) that outputs the total duration time of all video files in a Directory(recursively) ?

For e.g on executing the following :

script mypath

it gives x minutes/hours .

2 Answers2

14

First install mediainfo with:

sudo apt-get install mediainfo

You can now use the following oneliner to get the total video time of a directory:

find . -type f -exec mediainfo --Inform="General;%Duration%" "{}" \; 2>/dev/null | awk '{s+=$1/1000} END {h=s/3600; s=s%3600; printf "%.2d:%.2d\n", int(h), int(s/60)}'

The find command will call mediainfo for every files recursively and get the video duration in ms.

Then the awk part will sum those values and return the total time in the HH:MM format.


Update: avprobe is indeed faster than mediainfo (thanks @souravc)

For better results please use the command below instead (you'll need to sudo apt-get install libav-tools first)

find . -type f -exec avprobe -v quiet -show_format_entry duration "{}" \; | awk '{s+=$1} END {h=s/3600; s=s%3600; printf "%.2d:%.2d\n", int(h), int(s/60)}'
  • 1
    No.It works for small directory but gives some 2hours for large directory. Before installing gawk, I was getting a error like : "strftime : function not defined in awk ". @SylvainPineau may be the hours overflow ?(guessing) – PleaseHelp Mar 23 '15 at 17:40
  • 1
    @AtulGangwar Please try my updated version – Sylvain Pineau Mar 23 '15 at 18:20
  • 1
    @SylvainPineau Thanks. I added this as a function in my ~/.bashrc and passed the path as argument :) – PleaseHelp Mar 23 '15 at 18:31
  • 1
    @SylvainPineau I am getting E: File read error while executing in a directory (have other files apart from video files). IMHO mediainfo is comparatively slow than avprobe. It is taking time more than twice than that of avprobe. – sourav c. Mar 23 '15 at 19:45
  • @souravc I've updated my answer with avprobe as it's indeed much faster than mediainfo (I've also fixed the first version read error msg) – Sylvain Pineau Mar 23 '15 at 20:26
6

You can use the following script to know Total Duration of all video files in a Directory recursively. I have used avprobe in the following script which comes with libav-tools

Install libav-tools as,

sudo apt-get install libav-tools

Save the script as get_video_duration.sh(say). Give it execution permission from a terminal as

chmod u+x get_video_duration.sh

How to run the script

To know total video duration of the directory /full/path/to/videodir, run with argument as

./get_video_duration.sh /full/path/to/videodir

Or to know total video duration of current directory run without any argument as

./get_video_duration.sh .

For Recursion append -R or -r or -recursive or --recursive after the directory path. For example to know total video duration of the directory /full/path/to/videodir recursively (also search all folders inside /full/path/to/videodir)

./get_video_duration.sh /full/path/to/videodir -R

The script is as following:

#!/bin/bash
mysep="======================================================================================"
mysmallsep="--------------------------------------------------------------------------------------"
if [ -n "$1" ];then
    mypath="$1"
else
    mypath="$(pwd)"
fi
declare -a my_path_array
get_duration(){
    /usr/bin/avprobe "$1" 2>&1 | grep Duration | awk -F[:,] '{print int($2*3600+$3*60+$4)}'
}
print_duration(){
    awk -v var="$1" 'BEGIN {print int(var/3600)"Hr "int((var%3600)/60)"Min "int(var%60)"Sec "}'
}
execute_it_now(){
    echo -e "Video File\t\tVideo Duration"
    echo $mysep
    echo "$1"
    echo $mysmallsep
    j=0
    for i in "$1"/{*.mp4,*.mkv,*.avi,*.flv} ## Put the existing video file extension you have
    do
        if [[ "$(get_duration "$i")" -ne "0" ]];then
            echo -e "$(basename "$i")\t$(tput setaf 2)$(print_duration $(get_duration "$i"))$(tput sgr0)"
        fi
        let j=j+$(get_duration "$i") 2>/dev/null
    done
    echo $mysep
    echo "Total Duration $(tput setaf 1)$(print_duration $j)$(tput sgr0)"
}
execute_these_now(){
    for i in "$1"/{*.mp4,*.mkv,*.avi,*.flv} ## Put the existing video file extension you have
    do
        if [[ "$(get_duration "$i")" -ne "0" ]];then
            echo -e "$(basename "$i")\t$(tput setaf 2)$(print_duration $(get_duration "$i"))$(tput sgr0)"
        fi
    done
}
add_these_now(){
    j=0;
    for i in "$1"/{*.mp4,*.mkv,*.avi,*.flv} ## Put the existing video file extension you have
    do
        let j=j+$(get_duration "$i") 2>/dev/null
    done
    echo $j
}
case "$2" in
        -R|-r|-recursive|--recursive) 
        tmp=$(find $mypath -type d | xargs)
        my_path_array=( $tmp )
        echo -e "Video File\t\tVideo Duration"
        echo $mysep
        k=0;
        for indx in $(seq ${#my_path_array[@]})
    do
            echo ${my_path_array[$(($indx-1))]}
            echo $mysmallsep
            execute_these_now ${my_path_array[$(($indx-1))]}
            let k=k+$(add_these_now ${my_path_array[$(($indx-1))]})
    done
        echo $mysep
        echo "Total Duration $(tput setaf 1)$(print_duration $k)$(tput sgr0)"
           ;;
        *) 
            execute_it_now $mypath
           ;;
esac

Screen shot of execution of the script

enter image description here

Note: As I don't have any .mkv or .avi file in my home directory last two lines in the screen shot appeared with duration 0Hr 0Min 0Sec

sourav c.
  • 44,715
  • will this work if the files do not have extensions(but are still video files)? – PleaseHelp Mar 23 '15 at 18:32
  • 1
    just use for i in $mypath/* in stead of for i in $mypath/{*.mp4,*.mkv,*.avi} – sourav c. Mar 23 '15 at 18:36
  • Nice script. It lists all files with duration and total duration only in the current directory but doesn't go recursive. Also, when i use for i in $mypath/* it lists other files with 0 duration. So, the application is different from SylvainPineau's answer but nonetheless useful :) – PleaseHelp Mar 24 '15 at 06:08
  • May be add an option like "-R" to handle both cases, since only searching current dir can be useful too . – PleaseHelp Mar 24 '15 at 09:56
  • 1
    @AtulGangwar just see the revised code. hope this will serve your purpose. :) – sourav c. Mar 24 '15 at 15:14
  • Seems to work great provided that the folder names do not contain spaces.... – Ananda Mahto May 17 '17 at 05:00
  • Hello, newer ubuntu versions switched to ffprobe (package ffmpeg) instead of avprobe. Just switching the name in the script suffice (but attenction to the problem of spaces in the directory names.. can this be sorted?) – Antonello Nov 29 '18 at 11:08