From 7e25e7c9bd135f30b4aaeb608805cd77feef5f1d Mon Sep 17 00:00:00 2001 From: Pascal Dulieu Date: Tue, 21 Apr 2026 21:15:02 +0100 Subject: Initial commit Made-with: Cursor --- process_3d_bluray.ps1 | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 process_3d_bluray.ps1 (limited to 'process_3d_bluray.ps1') diff --git a/process_3d_bluray.ps1 b/process_3d_bluray.ps1 new file mode 100644 index 0000000..2ec8ccb --- /dev/null +++ b/process_3d_bluray.ps1 @@ -0,0 +1,237 @@ +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 +} \ No newline at end of file -- cgit v1.2.3