param( [Parameter(Mandatory = $true)] [string]$InputPath ) function Get-Mkvinfo { $possiblePaths = @( "$env:USERPROFILE\Downloads\mkvtoolnix\mkvinfo.exe", "$env:USERPROFILE\Downloads\mkvtoolnix\mkvinfo", "mkvinfo.exe", "mkvinfo", "./mkvtoolnix/mkvinfo.exe", "./mkvtoolnix/mkvinfo" ) foreach ($path in $possiblePaths) { if (Get-Command $path -ErrorAction SilentlyContinue) { return $path } } return $null } function Test-MVCContent { param( [string]$InputFile, [string]$MkvinfoPath ) try { $trackInfo = & $MkvinfoPath $InputFile 2>&1 if ($trackInfo -match "Block addition ID type: 1836475203 \(mvcC\)") { return $true } if ($trackInfo -match "Video stereo mode: \d+") { return $true } if ($trackInfo -match "Block addition ID extra data.*mvcC|mvcC.*Block addition") { return $true } if ($trackInfo -match "Codec ID: V_MPEG4/ISO/AVC" -and $trackInfo -match "Block addition") { return $true } return $false } catch { Write-Warning "Could not analyze file for MVC streams: $($_.Exception.Message)" return $false } } function Get-Mkvextract { $possiblePaths = @( "$env:USERPROFILE\Downloads\mkvtoolnix\mkvextract.exe", "$env:USERPROFILE\Downloads\mkvtoolnix\mkvextract", "mkvextract.exe", "mkvextract", "./mkvtoolnix/mkvextract.exe", "./mkvtoolnix/mkvextract" ) foreach ($path in $possiblePaths) { if (Get-Command $path -ErrorAction SilentlyContinue) { return $path } } return $null } function Invoke-H264Extraction { param( [string]$InputFile, [string]$MkvextractPath, [string]$H264File ) Write-Host "`nStep 1: Extracting H.264 stream..." -ForegroundColor Cyan $extractArgs = @("-f", "tracks", "`"$InputFile`"", "0:`"$H264File`"", "--fullraw") Write-Host "Running: $MkvextractPath $($extractArgs -join ' ')" -ForegroundColor Gray & $MkvextractPath $extractArgs if (-not (Test-Path $H264File)) { throw "Failed to extract H.264 stream" } Write-Host "H.264 extraction completed" -ForegroundColor Green } function New-FullFrameSBS { param( [string]$H264File, [string]$InputFile, [string]$SbsFile ) Write-Host "`nStep 2: Decoding MVC to SBS..." -ForegroundColor Cyan $pipeName = "\\.\pipe\frimdata" $frimProcess = Start-Process -FilePath "FRIM_x64_version_1.31\FRIMDecode64.exe" -ArgumentList "-i:mvc", "`"$H264File`"", "-sbs", "-o", $pipeName -PassThru -NoNewWindow Start-Sleep -Seconds 2 Write-Host "Running ffmpeg to create full-frame SBS..." -ForegroundColor Gray $ffmpegArgs = @("-y", "-f", "rawvideo", "-vcodec", "rawvideo", "-s", "3840x1080", "-pix_fmt", "yuv420p", "-thread_queue_size", "128", "-r", "24000/1001", "-i", "`"$pipeName`"", "-i", "`"$InputFile`"", "-c:v", "prores_ks", "-profile:v", "3", "-vendor", "apl0", "-pix_fmt", "yuv422p10le", "-c:a", "copy", "-sn", "-map", "0:v:0", "-map", "1", "-map", "-1:v", "`"$SbsFile`"") Write-Host "Running: ffmpeg $($ffmpegArgs -join ' ')" -ForegroundColor Gray & ffmpeg $ffmpegArgs $frimProcess.WaitForExit() if (-not (Test-Path $SbsFile)) { throw "Failed to create full-frame SBS video" } Write-Host "Full-frame SBS creation completed" -ForegroundColor Green } function New-HalfFrameSBS { param( [string]$SbsFile, [string]$OutputFile ) Write-Host "`nStep 3: Creating half-frame SBS for 3D TV..." -ForegroundColor Cyan $halfFrameArgs = @("-i", "`"$SbsFile`"", "-vsync", "vfr", "-vf", "`"scale=iw/2:ih`"", "-c:v", "libx264", "-profile:v", "main", "-level", "4.1", "-pix_fmt", "yuv420p", "-crf", "23", "-refs", "3", "-bf", "2", "-g", "30", "-keyint_min", "23", "-sc_threshold", "40", "-c:a", "aac", "-b:a", "192k", "-ar", "48000", "-ac", "2", "`"$OutputFile`"") Write-Host "Running: ffmpeg $($halfFrameArgs -join ' ')" -ForegroundColor Gray & ffmpeg $halfFrameArgs if (-not (Test-Path $OutputFile)) { throw "Failed to create half-frame SBS video" } Write-Host "Half-frame SBS creation completed" -ForegroundColor Green } function New-CompressedSBS { param( [string]$SbsFile, [string]$CompressedSbsFile ) Write-Host "`nStep 4: Compressing full-frame SBS to H.264/AAC..." -ForegroundColor Cyan $compressArgs = @("-i", "`"$SbsFile`"", "-c:v", "libx264", "-preset", "slow", "-crf", "18", "-c:a", "aac", "-b:a", "320k", "-movflags", "+faststart", "`"$CompressedSbsFile`"") Write-Host "Running: ffmpeg $($compressArgs -join ' ')" -ForegroundColor Gray & ffmpeg $compressArgs if (-not (Test-Path $CompressedSbsFile)) { throw "Failed to create compressed SBS video" } Write-Host "Compressed SBS creation completed" -ForegroundColor Green } function Invoke-SingleFileProcessing { param( [string]$InputFile, [string]$MkvextractPath ) $fileInfo = Get-Item $InputFile $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileInfo.Name) $directory = $fileInfo.DirectoryName $h264File = Join-Path $directory "$baseName.h264" $sbsFile = Join-Path $directory "$baseName-sbs.mkv" $compressedSbsFile = Join-Path $directory "$baseName-sbs-compressed.mp4" $outputFile = Join-Path $directory "$baseName-half-sbs.mp4" Write-Host "`nProcessing 3D BluRay: $InputFile" -ForegroundColor Green Write-Host "Output directory: $directory" -ForegroundColor Yellow Invoke-H264Extraction -InputFile $InputFile -MkvextractPath $mkvextractPath -H264File $h264File New-FullFrameSBS -H264File $h264File -InputFile $InputFile -SbsFile $sbsFile New-CompressedSBS -SbsFile $sbsFile -CompressedSbsFile $compressedSbsFile New-HalfFrameSBS -SbsFile $sbsFile -OutputFile $outputFile Write-Host "Processing completed successfully!" -ForegroundColor Green Write-Host "Output file: $outputFile" -ForegroundColor Yellow $fileSize = [math]::Round((Get-Item $outputFile).Length / 1MB, 2) Write-Host "File size: $fileSize MB" -ForegroundColor Yellow Write-Host "Cleaning up intermediate files..." -ForegroundColor Cyan if (Test-Path $h264File) { Remove-Item $h264File -Force Write-Host "Removed: $h264File" -ForegroundColor Gray } if (Test-Path $sbsFile) { Remove-Item $sbsFile -Force Write-Host "Removed: $sbsFile" -ForegroundColor Gray } Write-Host "Cleanup completed!" -ForegroundColor Green Write-Host "Compressed SBS file kept: $compressedSbsFile" -ForegroundColor Yellow } try { if (-not (Test-Path $InputPath)) { Write-Error "Input path '$InputPath' not found!" exit 1 } $mkvextractPath = Get-Mkvextract if (-not $mkvextractPath) { Write-Error "mkvextract not found! Please ensure MKVToolNix is installed in your Downloads folder or in PATH." exit 1 } $mkvinfoPath = Get-Mkvinfo if (-not $mkvinfoPath) { Write-Error "mkvinfo not found! Please ensure MKVToolNix is installed in your Downloads folder or in PATH." exit 1 } Write-Host "Using mkvextract: $mkvextractPath" -ForegroundColor Gray Write-Host "Using mkvinfo: $mkvinfoPath" -ForegroundColor Gray $inputItem = Get-Item $InputPath if ($inputItem.PSIsContainer) { Write-Host "Processing directory: $InputPath" -ForegroundColor Green $videoExtensions = @("*.mkv", "*.mp4", "*.avi", "*.m4v", "*.mov", "*.wmv", "*.flv", "*.webm") $videoFiles = @() foreach ($ext in $videoExtensions) { $videoFiles += Get-ChildItem -Path $InputPath -Filter $ext -File } if ($videoFiles.Count -eq 0) { Write-Host "No video files found in directory: $InputPath" -ForegroundColor Yellow exit 0 } Write-Host "Found $($videoFiles.Count) video files" -ForegroundColor Yellow $processedCount = 0 $skippedCount = 0 $noMvcCount = 0 foreach ($videoFile in $videoFiles) { $baseName = [System.IO.Path]::GetFileNameWithoutExtension($videoFile.Name) $outputFile = Join-Path $videoFile.DirectoryName "$baseName-half-sbs.mp4" if (Test-Path $outputFile) { Write-Host "`nSkipping $($videoFile.Name) - output already exists: $outputFile" -ForegroundColor Yellow $skippedCount++ continue } Write-Host "`nAnalyzing $($videoFile.Name) for MVC streams..." -ForegroundColor Cyan if (-not (Test-MVCContent -InputFile $videoFile.FullName -MkvinfoPath $mkvinfoPath)) { Write-Host "Skipping $($videoFile.Name) - no MVC streams detected (not a 3D BluRay)" -ForegroundColor Yellow $noMvcCount++ continue } Write-Host "MVC streams detected in $($videoFile.Name) - proceeding with processing" -ForegroundColor Green try { Invoke-SingleFileProcessing -InputFile $videoFile.FullName -MkvextractPath $mkvextractPath $processedCount++ } catch { Write-Error "Failed to process $($videoFile.Name): $($_.Exception.Message)" continue } } Write-Host "`nBatch processing completed!" -ForegroundColor Green Write-Host "Processed: $processedCount files" -ForegroundColor Yellow Write-Host "Skipped: $skippedCount files (already exist)" -ForegroundColor Yellow Write-Host "No MVC: $noMvcCount files (not 3D BluRay)" -ForegroundColor Yellow } else { Write-Host "Processing single file: $InputPath" -ForegroundColor Green Write-Host "Analyzing file for MVC streams..." -ForegroundColor Cyan if (-not (Test-MVCContent -InputFile $InputPath -MkvinfoPath $mkvinfoPath)) { Write-Error "File does not contain MVC streams - this is not a 3D BluRay file!" exit 1 } Write-Host "MVC streams detected - proceeding with processing" -ForegroundColor Green Invoke-SingleFileProcessing -InputFile $InputPath -MkvextractPath $mkvextractPath } } catch { $errorMessage = "Error during processing: " + $_.Exception.Message Write-Error $errorMessage exit 1 }