Last active
November 9, 2019 20:27
-
-
Save ecker00/4f2477afde8ce301eab68f870902b352 to your computer and use it in GitHub Desktop.
PowerShell batch timelapses with FFmpeg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Batch process timelapses | |
# | |
### About | |
# | |
# This script will find all .mp4 files in the given directory and create an | |
# ./ffmpeg directory with the outputs. You can decide speed multiplier and to | |
# queue all files or just a few. | |
# | |
### Setup | |
# | |
# 1. Add to profile: | |
# We use this script as part of our "PowerShell profile", so we can access it | |
# as 'lapse' from any powershell window. Like this: | |
# https://www.howtogeek.com/50236/customizing-your-powershell-profile/ | |
# | |
# 2. Add 'ffmpeg' to path | |
# Also important to setup 'ffmpeg' as an enviroment variable, like this: | |
# https://windowsloop.com/install-ffmpeg-windows-10/ | |
# | |
### How to use | |
# | |
# In PowerShell just type "lapse" and drag in the file or directory and press enter | |
# Example: lapse "C:\myTimelapses\" | |
# | |
function lapse($baseDir) { | |
# Validation | |
if (-not (Test-Path -Path $baseDir)) { echoColor "Red" "Path does not exist."; return; } | |
if (Test-Path -Path $baseDir -PathType Leaf) { $baseDir = split-path $baseDir; } # Convert file path to base dir | |
if (-not (Test-Path -Path $baseDir -PathType Container)) { echoColor "Red" "This does not seem to be a directory."; return; } | |
$numFiles = (Get-ChildItem $baseDir -Filter *.mp4 | measure).Count; | |
if ($numFiles -Eq 0) { echoColor "Red" "Found no .mp4 files in this directory."; return; } | |
$outDirName = "\ffmpeg\" | |
# Set speed | |
$speed = 1; | |
while (-not ($speed -ge 2 -and $speed -le 500)) { | |
$speed = askColor "Green" 'Speed multiplier? (2-500)'; | |
if (-not ($speed -ge 2 -and $speed -le 500)) { | |
echoColor "Red" "Invalid speed, must be a value between 2 and 500."; | |
} | |
} | |
# Queue all files? | |
$queueAll = askColor "Green" ('Queue all ' + $numFiles + ' files at x' + $speed + '? (y/n)'); | |
if ($queueAll.tolower() -Eq 'y') { | |
#echoColor "Green" ("Queueing " + $numFiles + " files"); | |
} elseif (-not ($queueAll.tolower() -Eq 'n')) { | |
echoColor "Yellow" "Not a valid choice, defaulting to 'no'"; | |
$queueAll = 'n'; | |
} | |
# Queue individual files | |
$queue = @(); | |
Get-ChildItem $baseDir -Filter *.mp4 | Foreach-Object { | |
$queueThis = 'y'; | |
if ($queueAll.tolower() -Eq 'n') { | |
# Test if file exsists | |
$outName = $_.BaseName + ' x' + $speed + '.mp4'; | |
$outFile = ($baseDir + $outDirName + $outName); | |
if (Test-Path -Path $outFile -PathType Leaf) { | |
$queueThis = askColor "Yellow" ('Queue file "' + $_.BaseName + '" (Warning: Output file already exists) (y/n)') | |
} else { | |
$queueThis = askColor "Cyan" ('Queue file "' + $_.BaseName + '" (y/n)'); | |
} | |
} | |
if ($queueThis.tolower() -Eq 'y') { | |
$queue += $_.BaseName; | |
} elseif (-not ($queueThis.tolower() -Eq 'n')) { | |
echoColor "Yellow" "Not a valid choice, defaulting to 'no'"; | |
} | |
} | |
# Check queued files | |
echoColor "Green" "Queued files:"; | |
foreach ($name in $queue) { | |
$outName = $name + ' x' + $speed + '.mp4'; | |
$outFile = ($baseDir + $outDirName + $outName); | |
if (Test-Path -Path $outFile -PathType Leaf) { | |
echoColor "Yellow" ("." + $outDirName + $outName + " (Warning: Output file already exists, will be overwritten)"); | |
} else { | |
echoColor "Cyan" ("." + $outDirName + $outName); | |
} | |
} | |
askColor "Green" 'Ready to process. Press enter to continue, ctrl+c to cancel'; | |
# Make output directory | |
mkdir ($baseDir + $outDirName) > $null | |
# Process files | |
echoColor "Green" "Processing files..."; | |
foreach ($name in $queue){ | |
$outName = $name + ' x' + $speed + '.mp4'; | |
$rawFile = ($baseDir + '\' + $name + '.mp4'); | |
$outFile = ($baseDir + $outDirName + $outName); | |
ffmpeg -y -hide_banner -loglevel warning -stats -i $rawFile -filter:v "setpts=PTS/$speed" -an $outFile | |
} | |
echoColor "Green" "Done!"; | |
} | |
# Echo in color | |
# Example: echoColor "Red" "This text is read" | |
function echoColor($color, $str) { | |
$tmp = $host.ui.RawUI.ForegroundColor | |
$host.ui.RawUI.ForegroundColor = $color | |
Write-Output $str | |
$host.ui.RawUI.ForegroundColor = $tmp | |
} | |
# Question in color | |
# Example: askColor "Red" "Do you want to continue? (y/n)" | |
function askColor($color, $str) { | |
$tmp = $host.ui.RawUI.ForegroundColor | |
$host.ui.RawUI.ForegroundColor = $color | |
$answer = Read-Host $str | |
$host.ui.RawUI.ForegroundColor = $tmp | |
return $answer | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Did a recent update to this script to simplyfiy the required folder structure, and give preemptive warnings when overwriting files.