aboutsummaryrefslogtreecommitdiff
path: root/process_3d_bluray.ps1
blob: 2ec8ccb5a86dfbb6435b2e5d89c57b47ac5386ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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
}