Skip to content

Instantly share code, notes, and snippets.

@ecker00
Last active November 9, 2019 20:27
Show Gist options
  • Save ecker00/4f2477afde8ce301eab68f870902b352 to your computer and use it in GitHub Desktop.
Save ecker00/4f2477afde8ce301eab68f870902b352 to your computer and use it in GitHub Desktop.
PowerShell batch timelapses with FFmpeg
# 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
}
@ecker00
Copy link
Author

ecker00 commented Oct 25, 2019

Did a recent update to this script to simplyfiy the required folder structure, and give preemptive warnings when overwriting files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment