Alistair Colling
Alistair Colling

Reputation: 1563

Recursively list video duration for all files in a directory

I want to list all the filenames and durations for each video in a folder. Currently I can only target files individually:

ffmpeg -i intro_vid001.mp4 2>&1 | grep Duration

Could someone suggest how I can print this out in the terminal or to a text file for every video file within a folder ?

I have tried with a shell script but am very new to shell scripts.

if [ -z $1 ];then echo Give target directory; exit 0;fi

find "$1" -depth -name ‘*’ | while read file ; do
directory=$(dirname "$file")
oldfilename=$(basename "$file")


echo oldfilename
#ffmpeg -i $directory/$oldfilename” -ab 320k “$directory/$newfilename.mp3″ </dev/null
ffmpeg -i "$directory/$oldfilename" 2>&1 | grep Duration | echo
#rm “$directory/$oldfilename”

done

Upvotes: 0

Views: 4205

Answers (2)

Matthias
Matthias

Reputation: 21

How to create a filelist of all video files in a directory containing their duration (length) in h:mm:ss?

After looking at several hints in the web, which all did not work for me, I finally was able to create this script, which works on my side under Windows 11 using power shell. Perhaps you can benefit from it as well.

How to use:

  • Make sure that ffmpeg is installed
  • Make sure that the path to ffprobe.exe (part of ffmpeg) is correctly set in the .ps1 file
  • Make sure that the working directory is mentioned correctly in the .ps1 file
  • Then run powershell as administrator
  • Navigate to target dir
  • Execute .\CreateFileListWithDuration.ps1

It should create a file VideoFileListWithDurations.txt as output with the desired data, that you can easily copy to Excel.

Enjoy!

Save this script in the directory with your videos - as "CreateFileListWithDuration.ps1":

# Set the path to the directory you want to list files from
$directoryPath = "[enter your dir path here where video files are located]"

# Set the path to the output file
$outputFilePath = "$directoryPath\VideoFileListWithDurations.txt"

try {
    # Get all video files in the specified directory
    $videoFiles = Get-ChildItem -Path $directoryPath | Where-Object {
        !$_.PSIsContainer -and $_.Extension -match '\.(mp4|avi|mkv|wmv)$'
    }

    # Initialize an array to store file information strings
    $fileInfoStrings = @()

    # Add headers to the array
    $fileInfoStrings += "FileName`tFileSize (MB)`tFileType`tCreated`tLastModified`tDuration"



    # Loop through each video file and retrieve its information
    foreach ($file in $videoFiles) {
        $fileInfo = @{
            FileName = $file.Name
            FileSize = "{0:N3}" -f ($file.Length / 1MB) # Format in megabytes with 3 decimal places
            FileType = $file.Extension
            Created = $file.CreationTime
            LastModified = $file.LastWriteTime
            Duration = "N/A"
        }

        try {
            Write-Host "Getting duration for $($file.Name)"
            $ffprobeOutput = & [enter path to ffprobe.exe file here - without ""] -i $($file.FullName) -show_entries format=duration -v quiet -of csv="p=0"
            Write-Host "ffprobe output: $ffprobeOutput"
            $duration = [double]$ffprobeOutput.Trim()
            $timeSpan = [TimeSpan]::FromSeconds($duration)
            $fileInfo.Duration = $timeSpan.ToString("h\:mm\:ss")
        } catch {
            $fileInfo.Duration = "Error getting duration"
        }

        $fileInfoStrings += "$($fileInfo.FileName)`t$($fileInfo.Duration)`t$($fileInfo.FileSize)"
    }

    # Export the file information strings to the output file
    $fileInfoStrings | Out-File -FilePath $outputFilePath -Append

    Write-Host "File information exported to $outputFilePath"
} catch {
    Write-Host "An error occurred: $_"
    Read-Host "Press Enter to exit"
}

Upvotes: 1

mcoolive
mcoolive

Reputation: 4205

  1. I forgot a dollar in front of one 'oldfilename'
  2. grep writes on its stdout, you must NOT pipe with echo that do not use its stdin.

I suggest the following script:

find "$1" -type f | while read videoPath ; do
    videoFile=$(basename "$videoPath")
    duration=$(ffmpeg -i "$videoPath" 2>&1 | grep Duration)

    echo "$videoFile: $duration"
done

Upvotes: 1

Related Questions