Last active
August 5, 2023 13:29
-
-
Save patelneel55/c040e97de474134486f0e9614c13b8c9 to your computer and use it in GitHub Desktop.
video-merge.ps1 - Merge multiple media files into a single or a group of files using ffmpeg
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
######################################### | |
# Quick script to merge video files # | |
######################################### | |
<# | |
.SYNOPSIS | |
Concatenates a list of video files into one or multiple video files. | |
.DESCRIPTION | |
This application allows you to feed it a list of all video files to be combined and combines them to another media files with every file containing 'max' original files. | |
SUPPORTED INPUT FILE FORMATS: .mkv, .vob, .mp4, .ts | |
.PARAMETER files | |
List of comma separated files that need to be combined. Default action is to get all media files in the current folder. | |
.PARAMETER output_name | |
Prefix of the final output files. Defaults to "output" | |
.PARAMETER max | |
This integer represents the limit of how many of the original files can be combined to a output file. Default value is 0. | |
.PARAMETER help | |
Provides usage and command to display this help text. | |
.PARAMETER default | |
Run the script using the default provided values. | |
.PARAMETER quiet | |
Suppress ffmpeg output | |
.EXAMPLE | |
./vide-merge.ps1 -mnum 3 | |
This command will take in all the video files in the current directory and combine them in 3s to provide the output files. For instance, 7 input files will generate 3 output files combining every 3 clips into one clip | |
.EXAMPLE | |
./video-merge.ps1 -files ./test.mkv,./hello.mkv,./test2.mkv | |
This command will combine all the input files into a single output file, "output-1.mkv", since mnum is 0 meaning there is no limit to how many clips a single output file can have. | |
.EXAMPLE | |
./video-merge.ps1 -files ./test.mkv,./hello.mp4,./tt.vob,./test2.mkv -mnum 2 -output_name test_output | |
This command will generate two files with the names, "test_output-1.mkv", "test_output-2.mkv". | |
#> | |
# Check for commandline arguments | |
param( | |
[switch]$help, | |
[switch]$default, | |
[string[]]$files = $(Get-ChildItem -Name *.mkv, *.vob, *.mp4, *.ts), | |
[string]$output_name = "output", | |
[int]$max = 0, | |
[switch]$quiet | |
) | |
# Check if help text needs to be printed or no unique input flag was passed. | |
if($help -or $PSBoundParameters.Count -eq 0) | |
{ | |
echo "Audio and Video Merger using ffmpeg" | |
echo "Usage: video-merge.ps1 [-help] [-default] [-files <list>] [-output_name <name>] [-max <value>]" | |
echo "`t To run using the default settings, run 'video-merge.ps1 -default'" | |
echo "`n" | |
Write-Host "Use -h to get full help or, even better, run 'man video-merge.ps1' or 'get-help video-merge.ps1 -detailed'." -ForegroundColor Yellow | |
exit | |
} | |
echo "video-merger.ps1 version 1.0.0." | |
echo "Audio and Video Merger using ffmpeg" | |
echo "`n" | |
# Generate media mpeg transport stream to convert all compressions to the same compression format | |
$inc = 0 | |
$cmd = "" | |
$fileArray = @() | |
ForEach($item in $files) | |
{ | |
$inc++ | |
$cmd += "ffmpeg -i `"$item`" -f mpegts -c copy file-$inc.mpeg.ts;" | |
$fileArray += "file-$inc.mpeg.ts" | |
} | |
# Check if input files need to be grouped based on max number of files per output file | |
$inc = 0 | |
if($max -ge 1) | |
{ | |
# Group files based on max value provided per output file | |
$files = @() | |
for($i = 0;$i -lt $fileArray.Length;$i++) | |
{ | |
$files += $fileArray[$i] | |
if(($i+1) % $mnum -eq 0) | |
{ | |
$cmd += "ffmpeg -i `"concat:$($files -join '|')`" -f matroska -c copy '$output_name-$(++$i).mkv';" | |
$files = @() | |
} | |
} | |
if($files.Length -ne 0) | |
{ | |
$cmd += "ffmpeg -i `"concat:$($files -join '|')`" -f matroska -c copy '$output_name-$(++$i).mkv';" | |
} | |
} | |
else | |
{ | |
$cmd += "ffmpeg -i `"concat:$($fileArray -join '|')`" -f matroska -c copy '$output_name.mkv';" | |
} | |
# Run all the commands | |
Invoke-Expression $cmd | |
# Cleanup temp streams | |
if($LastExitCode -eq 0) | |
{ | |
Remove-Item $fileArray | |
} | |
echo "`n" | |
Write-Host "Process Completed." -ForegroundColor Green |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
made a change that uses PowerShell 7 Parallel feature, it makes the conversion that much faster,
$cmd = ""
$fileArray = $ (Get-ChildItem -Name file-*)
$fileArray = @()
$files | ForEach-object -parallel{
#$inc++
$cmd = "C:\PROGRA~1\ffmpeg\bin\ffmpeg -i $_ -f mpegts -c copy file-$_"
Invoke-Expression $cmd
#$fileArray = $files
} -throttlelimit 100
$cmd = ""
Also consider adding a flag for HW acceleration on ffmpeg & a convert to h265 mp4 flag, reduced my files from 20Gb to 1Gb
C:\PROGRA~1\ffmpeg\bin\ffmpeg -threads 16 -hwaccel cuda -i -preset fast -c:v libx265