Public/media/Join-TsFile.ps1
function Join-TsFile { <# .SYNOPSIS Concatenates .ts video files in a specified location into a single output file .DESCRIPTION This cmdlet concatenates .ts video files from a specified directory or a list of files into a single output file. The files are processed in chunks to avoid command line length limitations, making the script suitable for handling a large number of files. If a FilesLocation is provided, it sorts the .ts files by creation time. If Files are provided, it uses that list instead. The output file is named "out.ts" by default. .PARAMETER FilesLocation The path to the directory containing the .ts files to concatenate. If not specified, the cmdlet will use the files provided in the -Files parameter. .PARAMETER Files An array of System.IO.FileInfo objects representing the .ts files to concatenate. If specified, this parameter overrides FilesLocation. .PARAMETER OutFile The name of the output file. By default, this is set to "out.ts". .PARAMETER ChunkSize The number of files to process in each chunk. This helps to avoid exceeding the command line length limit when concatenating files. .PARAMETER UseFFmpeg Use FFMPEG to join files instead of build in copy command. .EXAMPLE Join-TsFile "c:\test\" Joins all *.ts files found in a "c:\test\" directory .EXAMPLE Join-TsFile -Files (gci "c:\test\2") Joins all files passed as with Files argument .NOTES The cmdlet changes the current location to the directory specified by FilesLocation and restores the original location after the operation is complete. If the total command length is too long for the cmd /c copy operation, reducing the ChunkSize may help avoid errors. #> param ( [Parameter(Mandatory = $false, Position = 0)] [string]$FilesLocation, [Parameter(Mandatory = $false, Position = 1)] [System.IO.FileInfo[]]$Files, [Parameter(Mandatory = $false, Position = 2)] [string]$OutFile = "out.ts", [Parameter(Mandatory = $false, Position = 3)] [int]$ChunkSize = 1000, [Parameter(Mandatory = $false, Position = 4)] [switch]$UseFFmpeg ) function Test-FFmpegInstalled { return Get-Command ffmpeg -ErrorAction SilentlyContinue -OutVariable +Null } $location = Get-Location try { if (![string]::IsNullOrWhiteSpace($FilesLocation)) { $fileNames = Get-ChildItem -Path $FilesLocation -Filter "*.ts" | Sort-Object -Property CreationTime | % { $_.Name } } if ($Files) { $fileNames = $Files.Name $tsFile = $Files | Select-Object -First 1 $FilesLocation = $tsFile.Directory } $fileNames = $fileNames | ? { $_ -ne $OutFile } Set-Location $FilesLocation if ($UseFFmpeg -and (Test-FFmpegInstalled)) { $tmpFilePath = Join-Path -Path (Get-Location).Path -ChildPath "_fileList.txt" $fileNames | % { "file '$($_)'" } | Set-Content -Path $tmpFilePath ffmpeg -f concat -safe 0 -i $tmpFilePath -c copy $OutFile -loglevel quiet Remove-Item -Path $tmpFilePath } else { Copy-Item -Path $fileNames[0] -Destination $OutFile for ($i = 1; $i -lt $fileNames.Count; $i += $ChunkSize) { $chunk = $fileNames[$i..([math]::Min($i + $ChunkSize - 1, $fileNames.Count - 1))] $concatenatedNames = $chunk -join "+" cmd /c copy /b "$OutFile+$concatenatedNames" $OutFile | Out-Null } } } finally { Set-Location $location } } |