Total video time in a Directory

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 .


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)}'

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