Last active
October 12, 2024 09:07
-
-
Save maksii/5d11166c346417459b6b5b350ea6ae0c to your computer and use it in GitHub Desktop.
windows PowerShell scripts to batch(bulk) ffmpeg commands to manipulate media. require ffmpeg installed
This file contains 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
# Check FFmpeg availability | |
$ffmpegPath = "ffmpeg" # Default to ffmpeg in PATH | |
# Check FFprobe availability | |
$ffprobePath = "ffprobe" # Default to ffprobe in PATH | |
# Function to check if ffmpeg exists in PATH | |
function Check-FFmpeg { | |
try { | |
$output = & $ffmpegPath -version 2>&1 | |
if ($output -like "*ffmpeg version*") { | |
return $true | |
} else { | |
Write-Host "FFmpeg output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffmpeg: $_" | |
return $false | |
} | |
} | |
# Function to check if ffprobe exists in PATH | |
function Check-FFprobe { | |
try { | |
$output = & $ffprobePath -version 2>&1 | |
if ($output -like "*ffprobe version*") { | |
return $true | |
} else { | |
Write-Host "FFprobe output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffprobe: $_" | |
return $false | |
} | |
} | |
# Prompt for folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., 'C:\Media\Folder')" | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Validate folder path | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
Read-Host | |
exit | |
} | |
if (-not (Check-FFmpeg)) { | |
Write-Host "FFmpeg is not found in the system PATH." | |
$ffmpegPath = Read-Host "Please specify the full path to the ffmpeg executable (e.g., 'C:\Path\To\ffmpeg.exe')" | |
$ffmpegPath = $ffmpegPath.Trim('"') | |
# Validate FFmpeg path | |
if (-not (Test-Path $ffmpegPath)) { | |
Write-Host "The specified FFmpeg path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
if (-not (Check-FFprobe)) { | |
Write-Host "FFprobe is not found in the system PATH." | |
$ffprobePath = Read-Host "Please specify the full path to the ffprobe executable (e.g., 'C:\Path\To\ffprobe.exe')" | |
$ffprobePath = $ffprobePath.Trim('"') | |
# Validate FFprobe path | |
if (-not (Test-Path $ffprobePath)) { | |
Write-Host "The specified FFprobe path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
Write-Host "Using FFmpeg at path: $ffmpegPath" | |
Write-Host "Using FFprobe at path: $ffprobePath" | |
# Create 'extract' folder if it doesn't exist | |
$extractFolderPath = Join-Path -Path $folderPath -ChildPath "extract" | |
if (-not (Test-Path $extractFolderPath)) { | |
New-Item -Path $extractFolderPath -ItemType Directory | Out-Null | |
} | |
# Get MP4 and AVI files in the folder | |
$mediaFiles = Get-ChildItem -Path $folderPath -File | Where-Object { $_.Extension -eq ".mp4" -or $_.Extension -eq ".avi" } | |
# Define codec to extension mapping | |
$codecExtensions = @{ | |
"aac" = ".aac" | |
"ac3" = ".ac3" | |
"mp3" = ".mp3" | |
"wav" = ".wav" | |
"dts" = ".dts" | |
"flac" = ".flac" | |
"pcm" = ".pcm" | |
"opus" = ".opus" | |
} | |
# Process each media file | |
foreach ($file in $mediaFiles) { | |
$inputFilePath = $file.FullName | |
$fileBaseName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name) | |
# Get FFmpeg output | |
$ffmpegProbeCommand = "$ffmpegPath -i `"$inputFilePath`" -hide_banner" | |
$ffmpegOutput = & cmd /c $ffmpegProbeCommand 2>&1 | |
# Get the number of audio streams | |
$audioStreams = ($ffmpegOutput | Select-String -Pattern "Stream.*Audio").Count | |
# Extract each audio stream | |
for ($i = 0; $i -lt $audioStreams; $i++) { | |
try { | |
# Identify the audio codec | |
$audioCodecLine = ($ffmpegOutput | Select-String -Pattern "Stream.*Audio")[$i].Line | |
$audioCodec = if ($audioCodecLine -match "aac") { "aac" } | |
elseif ($audioCodecLine -match "ac3") { "ac3" } | |
elseif ($audioCodecLine -match "mp3") { "mp3" } | |
elseif ($audioCodecLine -match "wav") { "wav" } | |
elseif ($audioCodecLine -match "dts") { "dts" } | |
elseif ($audioCodecLine -match "flac") { "flac" } | |
elseif ($audioCodecLine -match "pcm") { "pcm" } | |
elseif ($audioCodecLine -match "opus") { "opus" } | |
else { "unknown" } | |
# Determine file extension based on codec | |
$outputExtension = if ($codecExtensions.ContainsKey($audioCodec)) { $codecExtensions[$audioCodec] } else { ".unknown" } | |
$outputFileName = "${fileBaseName}_audio${i}${outputExtension}" | |
$outputFilePath = Join-Path -Path $extractFolderPath -ChildPath $outputFileName | |
# Build FFmpeg command to extract audio | |
$ffmpegCommand = "$ffmpegPath -i `"$inputFilePath`" -map 0:a:$i -vn -acodec copy `"$outputFilePath`"" | |
# Execute FFmpeg command | |
Write-Verbose "Extracting audio stream $i from $($file.Name) as $audioCodec..." | |
Invoke-Expression -Command $ffmpegCommand | |
# Update progress | |
Write-Verbose "Completed processing audio stream $i of $($file.Name)." | |
} catch { | |
Write-Error "Failed to process audio stream $i of $($file.Name): $_" | |
} | |
} | |
} | |
# Completion Message | |
Write-Host "Audio extraction completed for all files. Press Enter to exit." | |
Read-Host |
This file contains 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
# Check FFmpeg availability | |
$ffmpegPath = "ffmpeg" # Default to ffmpeg in PATH | |
# Check FFprobe availability | |
$ffprobePath = "ffprobe" # Default to ffprobe in PATH | |
# Function to check if ffmpeg exists in PATH | |
function Check-FFmpeg { | |
try { | |
$output = & $ffmpegPath -version 2>&1 | |
if ($output -like "*ffmpeg version*") { | |
return $true | |
} else { | |
Write-Host "FFmpeg output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffmpeg: $_" | |
return $false | |
} | |
} | |
# Function to check if ffprobe exists in PATH | |
function Check-FFprobe { | |
try { | |
$output = & $ffprobePath -version 2>&1 | |
if ($output -like "*ffprobe version*") { | |
return $true | |
} else { | |
Write-Host "FFprobe output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffprobe: $_" | |
return $false | |
} | |
} | |
# Prompt for folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., 'C:\Media\Folder')" | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Validate folder path | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
Read-Host | |
exit | |
} | |
if (-not (Check-FFmpeg)) { | |
Write-Host "FFmpeg is not found in the system PATH." | |
$ffmpegPath = Read-Host "Please specify the full path to the ffmpeg executable (e.g., 'C:\Path\To\ffmpeg.exe')" | |
$ffmpegPath = $ffmpegPath.Trim('"') | |
# Validate FFmpeg path | |
if (-not (Test-Path $ffmpegPath)) { | |
Write-Host "The specified FFmpeg path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
if (-not (Check-FFprobe)) { | |
Write-Host "FFprobe is not found in the system PATH." | |
$ffprobePath = Read-Host "Please specify the full path to the ffprobe executable (e.g., 'C:\Path\To\ffprobe.exe')" | |
$ffprobePath = $ffprobePath.Trim('"') | |
# Validate FFprobe path | |
if (-not (Test-Path $ffprobePath)) { | |
Write-Host "The specified FFprobe path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
Write-Host "Using FFmpeg at path: $ffmpegPath" | |
Write-Host "Using FFprobe at path: $ffprobePath" | |
# Create 'channels' folder if it doesn't exist | |
$extractFolderPath = Join-Path -Path $folderPath -ChildPath "channels" | |
if (-not (Test-Path $extractFolderPath)) { | |
New-Item -Path $extractFolderPath -ItemType Directory | Out-Null | |
} | |
function ProcessAudio { | |
param ( | |
[string]$fileFullName, | |
[string]$channelLayout, | |
[array]$channels, | |
[string]$outputFolder | |
) | |
$fileBaseName = [System.IO.Path]::GetFileNameWithoutExtension($fileFullName) | |
Write-Host "Processing file: $($fileBaseName)" | |
# Construct the filter_complex and map options | |
$filterComplex = "channelsplit=channel_layout=$channelLayout" | |
$mapOptions = "" | |
for ($i = 0; $i -lt $channels.Length; $i++) { | |
$channel = $channels[$i] | |
$outputFileName = "${fileBaseName}_${channel}.wav" | |
$outputFilePath = Join-Path -Path $outputFolder -ChildPath $outputFileName | |
$filterComplex += "[$channel]" | |
$mapOptions += "-c pcm_s24le -rf64 auto -map `[$channel`] `"$outputFilePath`" " | |
} | |
$ffmpegCommand = "$ffmpegPath -i `"$fileFullName`" -filter_complex `"$filterComplex`" $mapOptions" | |
Write-Host "Executing command: $ffmpegCommand" | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
} | |
# Get all audio files in the folder | |
$audioFiles = Get-ChildItem -Path $folderPath -Include *.wav, *.mp3, *.aac, *.flac, *.ogg, *.m4a, *.opus, *.ac3, *.eac3, *.ac4, *.dts, *.dtshd, *.truehd, *.mlp -Recurse | |
# Count the number of audio files found | |
$numberOfFiles = $audioFiles.Count | |
# Output the number of files found | |
Write-Output "Number of audio files found: $numberOfFiles" | |
foreach ($file in $audioFiles) { | |
# Create a folder for each file inside 'channels' | |
$outputFolder = Join-Path -Path $extractFolderPath -ChildPath "$($file.BaseName)_channels" | |
if (-not (Test-Path $outputFolder)) { | |
New-Item -Path $outputFolder -ItemType Directory | Out-Null | |
} | |
# Get file information using ffprobe | |
$ffprobeCommand = "$ffprobePath -v error -select_streams a:0 -show_entries stream=channel_layout -of json `"$($file.FullName)`"" | |
$ffprobeOutput = & cmd /c $ffprobeCommand | |
$ffprobeJson = $ffprobeOutput | ConvertFrom-Json | |
#Write-Host "FFprobe JSON output: $($ffprobeJson | ConvertTo-Json -Depth 5)" | |
if ($ffprobeJson.streams.Count -gt 0) { | |
$channelLayout = $ffprobeJson.streams[0].channel_layout | |
# Determine the number of channels and perform splitting | |
switch ($channelLayout) { | |
"mono" { ProcessAudio -fileFullName $file.FullName -channelLayout "mono" -channels @("C") -outputFolder $outputFolder } | |
"1.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "1.0" -channels @("C") -outputFolder $outputFolder } | |
"stereo" { ProcessAudio -fileFullName $file.FullName -channelLayout "stereo" -channels @("L", "R") -outputFolder $outputFolder } | |
"2.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "2.0" -channels @("L", "R") -outputFolder $outputFolder } | |
"2.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "2.1" -channels @("L", "R", "LFE") -outputFolder $outputFolder } | |
"3.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "3.0" -channels @("L", "C", "R") -outputFolder $outputFolder } | |
"3.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "3.1" -channels @("L", "C", "R", "LFE") -outputFolder $outputFolder } | |
"4.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "4.0" -channels @("L", "R", "Ls", "Rs") -outputFolder $outputFolder } | |
"4.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "4.1" -channels @("L", "R", "Ls", "Rs", "LFE") -outputFolder $outputFolder } | |
"5.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "5.0" -channels @("L", "R", "C", "Ls", "Rs") -outputFolder $outputFolder } | |
"5.0(side)" { ProcessAudio -fileFullName $file.FullName -channelLayout "5.0(side)" -channels @("L", "R", "C", "Ls", "Rs") -outputFolder $outputFolder } | |
"5.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "5.1" -channels @("L", "R", "C", "LFE", "Ls", "Rs") -outputFolder $outputFolder } | |
"5.1(side)" { ProcessAudio -fileFullName $file.FullName -channelLayout "5.1(side)" -channels @("L", "R", "C", "LFE", "Ls", "Rs") -outputFolder $outputFolder } | |
"6.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "6.0" -channels @("L", "R", "C", "Ls", "Rs", "Cs") -outputFolder $outputFolder } | |
"6.0(front)" { ProcessAudio -fileFullName $file.FullName -channelLayout "6.0(front)" -channels @("L", "R", "C", "Ls", "Rs", "Cs") -outputFolder $outputFolder } | |
"6.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "6.1" -channels @("L", "R", "C", "LFE", "Ls", "Rs", "Cs") -outputFolder $outputFolder } | |
"7.0" { ProcessAudio -fileFullName $file.FullName -channelLayout "7.0" -channels @("L", "R", "C", "Ls", "Rs", "Lrs", "Rrs") -outputFolder $outputFolder } | |
"7.0(front)" { ProcessAudio -fileFullName $file.FullName -channelLayout "7.0(front)" -channels @("L", "R", "C", "Ls", "Rs", "Lrs", "Rrs") -outputFolder $outputFolder } | |
"7.1" { ProcessAudio -fileFullName $file.FullName -channelLayout "7.1" -channels @("L", "R", "C", "LFE", "Ls", "Rs", "Lrs", "Rrs") -outputFolder $outputFolder } | |
"7.1(wide)" { ProcessAudio -fileFullName $file.FullName -channelLayout "7.1(wide)" -channels @("L", "R", "C", "LFE", "Ls", "Rs", "Lrs", "Rrs") -outputFolder $outputFolder } | |
"7.1(wide-side)" { ProcessAudio -fileFullName $file.FullName -channelLayout "7.1(wide-side)" -channels @("L", "R", "C", "LFE", "Ls", "Rs", "Lrs", "Rrs") -outputFolder $outputFolder } | |
default { Write-Host "Unknown channel layout for file $($file.Name). Channels: $($channelLayout)" } | |
} | |
} else { | |
Write-Host "No audio stream found in file $($file.Name)" | |
} | |
} | |
# Completion Message | |
Write-Host "Channel extraction completed for all files. Press Enter to exit." | |
Read-Host |
This file contains 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
# Check FFmpeg availability | |
$ffmpegPath = "ffmpeg" # Default to ffmpeg in PATH | |
# Check FFprobe availability | |
$ffprobePath = "ffprobe" # Default to ffprobe in PATH | |
# Function to check if ffmpeg exists in PATH | |
function Check-FFmpeg { | |
try { | |
$output = & $ffmpegPath -version 2>&1 | |
if ($output -like "*ffmpeg version*") { | |
return $true | |
} else { | |
Write-Host "FFmpeg output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffmpeg: $_" | |
return $false | |
} | |
} | |
# Function to check if ffprobe exists in PATH | |
function Check-FFprobe { | |
try { | |
$output = & $ffprobePath -version 2>&1 | |
if ($output -like "*ffprobe version*") { | |
return $true | |
} else { | |
Write-Host "FFprobe output did not contain expected version information." | |
return $false | |
} | |
} catch { | |
Write-Host "Error executing ffprobe: $_" | |
return $false | |
} | |
} | |
# Prompt for folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., 'C:\Media\Folder')" | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Validate folder path | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
Read-Host | |
exit | |
} | |
if (-not (Check-FFmpeg)) { | |
Write-Host "FFmpeg is not found in the system PATH." | |
$ffmpegPath = Read-Host "Please specify the full path to the ffmpeg executable (e.g., 'C:\Path\To\ffmpeg.exe')" | |
$ffmpegPath = $ffmpegPath.Trim('"') | |
# Validate FFmpeg path | |
if (-not (Test-Path $ffmpegPath)) { | |
Write-Host "The specified FFmpeg path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
if (-not (Check-FFprobe)) { | |
Write-Host "FFprobe is not found in the system PATH." | |
$ffprobePath = Read-Host "Please specify the full path to the ffprobe executable (e.g., 'C:\Path\To\ffprobe.exe')" | |
$ffprobePath = $ffprobePath.Trim('"') | |
# Validate FFprobe path | |
if (-not (Test-Path $ffprobePath)) { | |
Write-Host "The specified FFprobe path is invalid." | |
Read-Host | |
exit | |
} | |
} | |
Write-Host "Using FFmpeg at path: $ffmpegPath" | |
Write-Host "Using FFprobe at path: $ffprobePath" | |
# Create 'converted' folder if it doesn't exist | |
$convertFolderPath = Join-Path -Path $folderPath -ChildPath "converted" | |
if (-not (Test-Path $convertFolderPath)) { | |
New-Item -Path $convertFolderPath -ItemType Directory | Out-Null | |
} | |
# Function to get the number of audio channels using ffprobe | |
function Get-AudioChannels { | |
param ( | |
[string]$fileFullName | |
) | |
$ffprobeCommand = "$ffprobePath -v error -select_streams a:0 -show_entries stream=channels -of default=noprint_wrappers=1:nokey=1 `"$fileFullName`"" | |
$channels = & cmd.exe /c $ffprobeCommand | |
return [int]$channels.Trim() | |
} | |
# Function to convert audio to 24-bit WAV | |
function ConvertToWav24bit { | |
param ( | |
[string]$fileFullName, | |
[string]$outputFolder | |
) | |
$fileBaseName = [System.IO.Path]::GetFileNameWithoutExtension($fileFullName) | |
$outputFileName = "${fileBaseName}.wav" | |
$outputFilePath = Join-Path -Path $outputFolder -ChildPath $outputFileName | |
$channels = Get-AudioChannels -fileFullName $fileFullName | |
$ffmpegCommand = "$ffmpegPath -i `"$fileFullName`" -c:a pcm_s24le -ac $channels -rf64 auto `"$outputFilePath`"" | |
Write-Host "Executing command: $ffmpegCommand" | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
} | |
# Get all audio files in the folder | |
$audioFiles = Get-ChildItem -Path $folderPath -Include *.wav, *.mp3, *.aac, *.flac, *.ogg, *.m4a, *.opus, *.ac3, *.eac3, *.ac4, *.dts, *.dtshd, *.truehd, *.mlp -Recurse | |
# Count the number of audio files found | |
$numberOfFiles = $audioFiles.Count | |
# Output the number of files found | |
Write-Output "Number of audio files found: $numberOfFiles" | |
foreach ($file in $audioFiles) { | |
ConvertToWav24bit -fileFullName $file.FullName -outputFolder $convertFolderPath | |
} | |
# Completion Message | |
Write-Host "Conversion to 24-bit WAV completed for all files. Press Enter to exit." | |
Read-Host |
This file contains 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
# Ask for the folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing audio files (e.g., 'C:\Media\Folder')" | |
# Ask for the desired audio format | |
$audioFormat = Read-Host "Enter the desired audio format (e.g., 'aac', 'mp3', 'wav')" | |
# Ask for the desired bitrate | |
$bitrate = Read-Host "Enter the desired bitrate (e.g., '192k')" | |
# Ensure FFmpeg is available | |
$ffmpegPath = "ffmpeg" # Assumes FFmpeg is in the system PATH | |
# Validate inputs | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
exit | |
} | |
if (-not $audioFormat) { | |
Write-Host "Please provide a valid audio format." | |
exit | |
} | |
if (-not $bitrate) { | |
Write-Host "Please provide a valid bitrate." | |
exit | |
} | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Create a subfolder named 'converted' if it doesn't exist | |
$convertedFolderPath = Join-Path -Path $folderPath -ChildPath "converted" | |
if (-not (Test-Path $convertedFolderPath)) { | |
New-Item -ItemType Directory -Path $convertedFolderPath | Out-Null | |
} | |
# Supported audio file extensions | |
$audioExtensions = @(".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a") | |
# Get audio files in the folder | |
$audioFiles = Get-ChildItem -Path $folderPath -File | Where-Object { | |
$audioExtensions -contains $_.Extension.ToLower() | |
} | |
# Process each audio file | |
foreach ($file in $audioFiles) { | |
$inputFilePath = $file.FullName | |
$outputFileName = [System.IO.Path]::ChangeExtension($file.Name, $audioFormat) | |
$outputFilePath = Join-Path -Path $convertedFolderPath -ChildPath $outputFileName | |
# Build FFmpeg command to convert audio | |
$ffmpegCommand = "$ffmpegPath -i `"$inputFilePath`" -b:a $bitrate `"$outputFilePath`"" | |
# Execute FFmpeg command | |
Write-Host "Processing $($file.Name)..." | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
# Update progress | |
Write-Host "Completed processing $($file.Name)." | |
} | |
# Completion Message | |
Write-Host "All files converted. Press Enter to exit." | |
Read-Host |
This file contains 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
# Ask for the folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., \"C:\Media\Folder\")" | |
# Ask for start and end times | |
$endTime = Read-Host "Enter the end time for trimming (format HH:MM:SS, e.g., 00:02:30)" | |
# Ensure FFmpeg is available | |
$ffmpegPath = "ffmpeg" # Assumes FFmpeg is in the system PATH | |
# Validate inputs | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
exit | |
} | |
if (-not $endTime) { | |
Write-Host "Please provide the end time in the format HH:MM:SS (e.g., 00:02:30 for 2 minutes and 30 seconds)." | |
exit | |
} | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Create a subfolder named 'trim' if it doesn't exist | |
$trimFolderPath = Join-Path -Path $folderPath -ChildPath "trim" | |
if (-not (Test-Path $trimFolderPath)) { | |
New-Item -ItemType Directory -Path $trimFolderPath | Out-Null | |
} | |
# Supported media file extensions | |
$mediaExtensions = @(".mp4", ".mkv", ".mov", ".avi", ".mp3", ".wav", ".flac") | |
# Get media files in the folder | |
$mediaFiles = Get-ChildItem -Path $folderPath -File | Where-Object { | |
$mediaExtensions -contains $_.Extension.ToLower() | |
} | |
# Process each media file | |
foreach ($file in $mediaFiles) { | |
$inputFilePath = $file.FullName | |
$outputFilePath = Join-Path -Path $trimFolderPath -ChildPath $file.Name | |
# Build FFmpeg command to trim after the end time | |
$ffmpegCommand = "$ffmpegPath -i `"$inputFilePath`" -ss $endTime -c copy `"$outputFilePath`"" | |
# Execute FFmpeg command | |
Write-Host "Processing $($file.Name)..." | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
# Update progress | |
Write-Host "Completed processing $($file.Name)." | |
} | |
# Completion Message | |
Write-Host "All files processed. Press Enter to exit." | |
Read-Host |
This file contains 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
# Ask for the folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., \"C:\Media\Folder\")" | |
# Ask for start and end times | |
$startTime = Read-Host "Enter the start time for trimming (format HH:MM:SS, e.g., 00:00:15)" | |
$endTime = Read-Host "Enter the end time for trimming (format HH:MM:SS, e.g., 00:23:40)" | |
# Ensure FFmpeg is available | |
$ffmpegPath = "ffmpeg" # Assumes FFmpeg is in the system PATH | |
# Validate inputs | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
exit | |
} | |
if (-not $startTime -or -not $endTime) { | |
Write-Host "Please provide both start and end times in the format HH:MM:SS (e.g., 00:01:30 for 1 minute and 30 seconds)." | |
exit | |
} | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Create a subfolder named 'trim' if it doesn't exist | |
$trimFolderPath = Join-Path -Path $folderPath -ChildPath "trim" | |
if (-not (Test-Path $trimFolderPath)) { | |
New-Item -ItemType Directory -Path $trimFolderPath | Out-Null | |
} | |
# Supported media file extensions | |
$mediaExtensions = @(".mp4", ".mkv", ".mov", ".avi", ".mp3", ".wav", ".flac") | |
# Get media files in the folder | |
$mediaFiles = Get-ChildItem -Path $folderPath -File | Where-Object { | |
$mediaExtensions -contains $_.Extension.ToLower() | |
} | |
# Process each media file | |
foreach ($file in $mediaFiles) { | |
$inputFilePath = $file.FullName | |
$outputFilePath = Join-Path -Path $trimFolderPath -ChildPath $file.Name | |
# Build FFmpeg command | |
$ffmpegCommand = "$ffmpegPath -i `"$inputFilePath`" -ss $startTime -to $endTime -c copy `"$outputFilePath`"" | |
# Execute FFmpeg command | |
Write-Host "Processing $($file.Name)..." | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
# Update progress | |
Write-Host "Completed processing $($file.Name)." | |
} | |
# Completion Message | |
Write-Host "All files processed. Press Enter to exit." | |
Read-Host |
This file contains 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
# Ask for the folder path | |
$folderPath = Read-Host "Enter the full path to the folder containing media files (e.g., \"C:\Media\Folder\")" | |
# Ask for start and end times | |
$startTime = Read-Host "Enter the start time for trimming (format HH:MM:SS, e.g., 00:00:15)" | |
$endTime = Read-Host "Enter the end time for trimming (format HH:MM:SS, e.g., 00:23:40)" | |
# Ensure FFmpeg is available | |
$ffmpegPath = "ffmpeg" # Assumes FFmpeg is in the system PATH | |
# Validate inputs | |
if (-not (Test-Path $folderPath)) { | |
Write-Host "The specified folder does not exist." | |
exit | |
} | |
if (-not $startTime -or -not $endTime) { | |
Write-Host "Please provide both start and end times in the format HH:MM:SS (e.g., 00:01:30 for 1 minute and 30 seconds)." | |
exit | |
} | |
# Remove quotes from folder path if present | |
$folderPath = $folderPath.Trim('"') | |
# Create a subfolder named 'trim' if it doesn't exist | |
$trimFolderPath = Join-Path -Path $folderPath -ChildPath "trim" | |
if (-not (Test-Path $trimFolderPath)) { | |
New-Item -ItemType Directory -Path $trimFolderPath | Out-Null | |
} | |
# Supported media file extensions | |
$mediaExtensions = @(".mp4", ".mkv", ".mov", ".avi", ".mp3", ".wav", ".flac") | |
# Get media files in the folder | |
$mediaFiles = Get-ChildItem -Path $folderPath -File | Where-Object { | |
$mediaExtensions -contains $_.Extension.ToLower() | |
} | |
# Function to convert HH:MM:SS to seconds | |
function ConvertTo-Seconds($time) { | |
$parts = $time -split ":" | |
return [int]$parts[0] * 3600 + [int]$parts[1] * 60 + [int]$parts[2] | |
} | |
# Function to find the closest black screen time | |
function Find-ClosestBlackScreen($filePath, $targetTime) { | |
Write-Host "Analyzing black screen times for $($filePath)..." | |
$blackDetectCommand = "$ffmpegPath -i `"$filePath`" -vf blackdetect=d=0.1:pic_th=0.90 -an -f null - 2>&1" | |
$output = & cmd.exe /c $blackDetectCommand | |
$blackTimes = @() | |
foreach ($line in $output -split "`r`n") { | |
if ($line -match "black_start:(\d+\.\d+)") { | |
$blackTimes += [double]$matches[1] | |
} | |
} | |
$targetSeconds = ConvertTo-Seconds $targetTime | |
$closestTime = $blackTimes | Sort-Object { [math]::Abs($_ - $targetSeconds) } | Select-Object -First 1 | |
$closestTimeFormatted = [TimeSpan]::FromSeconds($closestTime).ToString("hh\:mm\:ss") | |
Write-Host "Closest black screen to $targetTime is at $closestTimeFormatted" | |
return $closestTimeFormatted | |
} | |
# Process each media file | |
foreach ($file in $mediaFiles) { | |
$inputFilePath = $file.FullName | |
$outputFilePath = Join-Path -Path $trimFolderPath -ChildPath $file.Name | |
# Find closest black screen times | |
Write-Host "Finding closest black screen times for $($file.Name)..." | |
$adjustedStartTime = Find-ClosestBlackScreen $inputFilePath $startTime | |
$adjustedEndTime = Find-ClosestBlackScreen $inputFilePath $endTime | |
# Build FFmpeg command | |
$ffmpegCommand = "$ffmpegPath -i `"$inputFilePath`" -ss $adjustedStartTime -to $adjustedEndTime -c copy `"$outputFilePath`"" | |
# Execute FFmpeg command | |
Write-Host "Processing $($file.Name) from $adjustedStartTime to $adjustedEndTime..." | |
Start-Process -NoNewWindow -Wait -FilePath "cmd.exe" -ArgumentList "/c $ffmpegCommand" | |
# Update progress | |
Write-Host "Completed processing $($file.Name)." | |
} | |
# Completion Message | |
Write-Host "All files processed. Press Enter to exit." | |
Read-Host |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment