I've tried it on Heroes, Californication and Supernatural and it works a treat. It only works on Blu Rays though, DVDs don't have segment numbers or a lot of the other problems Blu Rays have.
I'm just playing around here so the things a mess, Min and Max duration are hard coded at the moment, they really ought to be set in the middle between the info getting and the actual ripping so you can modify things to your hearts content, but the script is here:
(You also need "MakeMKVFunctions.ps1" (in the next post), save them in the same directory as "MakeMKV.ps1" and "MakeMKVFunctions.ps1" and they should work. They work best in the Powershell ISE (YMMV))
"%windir%\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe"
%windir% is usually "C:\Windows\"
"MakeMKV.ps1"
Code: Select all
."$PSScriptRoot\MakeMKVFunctions.ps1"
if (-not ($MakeMKVCon = Get-MakeMKVCon)) { break }
$MKVPropEdit = Get-MKVPropEdit
cls
Skip-Lines 11
Write-Line Main Blue "Settings:"
Write-Line Head Magenta "Source:"
$DiscRecorder = Get-Disc
if (-not $DiscRecorder) { Write-Line Main Blue "No Source."; break }
$DiscRecorder.VolumePathNames | foreach {if ($_.length -eq 3 -and $_[1] -eq ':' -and $_[2] -eq '\') {$Drive=$_[0]}}
$Disc = $DiscRecorder.LegacyDeviceNumber
Write-Line Line Magenta "Drive [$Disc]: " 25 "$Drive`:\"
Write-Line Head Magenta "Set."
Write-Line Head Yellow "Destination:"
$Dest = Get-Dest "PSMakeMKV.cfg" "Choose Destination Folder."
Write-Line Line Yellow "Destination Folder:" 25 "$Dest"
Write-Line Head Yellow "Set."
Write-Line Head Cyan "Limitations:"
if (($MinDuration=(Get-Duration "Minimum Durations.txt" "Minimum Duration" "Time")))
{ Write-Line Line Cyan "Minimum Duration:" 25 ([string]$MinDuration)}
else {Write-Line Line Cyan "Minimum Duration:" 25 "None"}
if (($MaxDuration=(Get-Duration "Maximum Durations.txt" "Maximum Duration" "Time")) -gt $MinDuration)
{ Write-Line Line Cyan "Maximum Duration:" 25 ([string]$MaxDuration)}
else {Write-Line Line Cyan "Maximum Duration:" 25 "None"; $MaxDuration = 0}
if (($MinChapters=(Get-Duration "Minimum Chapter Count.txt" "Minimum Chapter Count" "Chapters")))
{ Write-Line Line Cyan "Minimum Chapter Count:" 25 ([string]$MinChapters)}
else {Write-Line Line Cyan "Minimum Chapter Count:" 25 "None"; $MinChapters = 0}
Write-Line Head Cyan "Set"
Write-Line Head DarkGreen "Profile:"
$Profile = Get-Profile
if ($Profile) { Write-Line Line DarkGreen "Profile:" 25 $Profile; $ProfileCommand="--profile=$Profile" }
else { Write-Line Line DarkGreen "Profile:" 25 "Using Default Profile."; $ProfileCommand=$null }
Write-Line Head DarkGreen "Set."
Write-Line Main Blue "All Set."
$DefaultProfile = [System.IO.Path]::GetDirectoryName($MakeMKVCon) + "\default.mmcp.xml"
if (-not ((Get-Item -Path "Running.tog" -ErrorAction SilentlyContinue))) {[void](New-Item -Path "Running.tog" -ItemType "file")}
while ($true)
{
if (" " -eq " ") {
if (-not ((Get-Item -Path "Running.tog" -ErrorAction SilentlyContinue))) { break }
$DebugOn = $true
while (-not (Get-WmiObject win32_logicaldisk -Filter "DeviceID=`"$Drive`:`" and Access>0")) { if ($DebugOn) { "`n"; Write-Line Main White "Please Insert Disc."; $DebugOn=$false }; Start-Sleep -Seconds 1 }
$CurTitle = $CurStream = -1
$DebugOn = $false
$NewData = New-Object -TypeName XML
[void]$NewData.AppendChild($NewData.CreateComment("$MakeMKVCon --noscan -r --messages=-stdout --profile=$DefaultProfile --minlength=0 info disc:$Disc"));
#$NewData = [xml] "<?xml version=`"1.0`"?><!-- <!DOCTYPE DiscInfo SYSTEM `"MakeMKVDiscInfo.dtd`"> --><Disc />"
$DiscData = $NewData.CreateElement("Disc")
[void]$NewData.AppendChild($DiscData)
$Dups = $NewData.CreateElement("Duplicates")
[void]$DiscData.AppendChild($Dups)
Write-Pillar
Write-Line Main DarkRed "MakeMKV Scan:"
Write-Line Head DarkCyan "Info:"
$Title = 0
&$MakeMKVCon "--noscan" "-r" "--messages=-stdout" ("--profile=$DefaultProfile") "--minlength=0" "info" ("disc:$Disc") | ForEach-Object -Process {
$Type = $Line = $Temp = ""
([string] $_).Split(":", 2) | foreach {if ($Type) {$Line = $_} else {$Type = $_}}
$EscapeOn = $InQuotes = $false
$Params = @()
switch -wildcard ($Line.ToCharArray())
{
'\' { if (-not $EscapeOn -and $InQuotes) { $EscapeOn = $true; continue } }
',' { if (-not $InQuotes) { $Params+=$Temp; $Temp=""; continue } }
'"' { if (-not $EscapeOn) { $InQuotes = -not $InQuotes; continue } }
? { $Temp+=$_; $EscapeOn = $false }
}
$Params+=$Temp
switch -wildcard ($Type)
{
"DRV" { break }
"TCOUNT" { break }
"MSG"
{
switch ([int]$Params[0])
{
$Message_DEBUG_ASSERT { Write-Line Line Red "Debug Assert:" ([int]-1) $Params[5] ([int]-1) "at" ([int]-1) $Params[6] }
$Message_OPENING_FILES { break }
$Message_TITLE_EQUAL {
$SourceNumber = ($Params[6].Split('('))[0]
$SourceNumber = $SourceNumber.Replace(".mpls", "").Replace(".m2ts", "")
$SourcePart = ""
if ($Params[6].Contains(".mpls("))
{
$SourcePart = ($Params[6].Split('('))[1].TrimEnd(')')
}
if ($Params[6].Contains(".mpls"))
{
$SourceEx = "mpls"
}
elseif ($Params[6].Contains(".m2ts"))
{
$SourceEx = "m2ts"
}
$Dup = $Dups.SelectSingleNode("Duplicate[@Source=""$SourceNumber"" and @Ext=""$SourceEx"" and @Part=""$SourcePart""]")
if (-not $Dup)
{
$Dup = Add-XML-Element $Dups "Duplicate"
Add-XML-Attribute $Dup "Source" $SourceNumber
Add-XML-Attribute $Dup "Part" $SourcePart
Add-XML-Attribute $Dup "Ext" $SourceEx
}
$SourceNumber = ($Params[5].Split('('))[0]
$SourceNumber = $SourceNumber.Replace(".mpls", "").Replace(".m2ts", "")
$SourcePart = ""
if ($Params[5].Contains(".mpls("))
{
$SourcePart = ($Params[5].Split('('))[1].TrimEnd(')')
}
if ($Params[5].Contains(".mpls"))
{
$SourceEx = "mpls"
}
elseif ($Params[5].Contains(".m2ts"))
{
$SourceEx = "m2ts"
}
$Copy = Get-XML-Element $Dup "Copy" "Source" $SourceNumber -Force
Add-XML-Attribute $Copy "Part" $SourcePart
Add-XML-Attribute $Copy "Ext" $SourceEx
break
}
$Message_TITLE_TOO_SMALL { break }
$Message_QUERY_OVERWRITE_FILE { break }
$Message_SAVE_FAILED { break }
$Message_SAVE_PART_SUCCESSFUL { break }
$Message_SAVE_SUCCESSFUL { break }
$Message_DISC_FAILED { break }
$Message_OPERATION_SUCCESSFUL { break }
$Message_COMPLETE_SUCCESSFUL { break }
$Message_COMPLETE_PART_SUCCESSFUL { break }
$Message_LOAD_HASH_TABLE { break }
$Message_DECRYPTOR_DETECTED { Write-Line Line DarkRed "Foreign Blu Ray Decryptor is Enabled"; }
$Message_AACS_NOT_PRESENT { Write-Line Line DarkRed "AACS Not Present" }
$Message_DIRECT_DISC_ACCESS { $DebugOn = $true; break }
$Message_DEBUG { if ($DebugOn) { Write-Line Line Red $Params[3] }; break }
$Message_DEBUG_LOG { Write-Line Line DarkCyan "Debug Log:" 22 $Params[5]; Write-Line Head DarkCyan "Read."; Write-Line Head DarkGreen "Disc Information:"; <#Write-Line Head Green "Titles:" ; #>break }
$Message_APP_START { Write-Line Line DarkCyan "Version:" 22 $Params[5]; break }
$Message_PATH_NOT_EXIST { Write-Host $Params[3]; break }
$Message_BUP_NOT_EQU_IFO { break }
$Message_TITLE_WITH_CELLS_ADDED { <#Write-Line Line Green "Title $Title" 12 "Added:" 20 $Params[5]; #>break }
$Message_TITLE_ADDED {
<#if ($Params[5].Contains(".mpls("))
{
$Params[5] = ($Params[5].Split('('))[0].Replace(".mpls","") + '-' + ($Params[5].Split('('))[1].TrimEnd(')').PadLeft(2, '0') + ".mpls"
}
Write-Line Line Green "Title $Title" 12 "Added:" 20 $Params[5]#>
$Title+=1
break
}
default { Write-Line Line DarkMagenta "Unknown Message (" $Params[0] "): " $Params[3]; Add-Content -Path "F:\Work\MakeMKV.log" -Value $_ }
}
break
}
"CINFO"
{
$CurTitle = $CurStream = -1
$Params[0]=[convert]::ToInt32($Params[0], 10)
if ($Params[0] -eq 2) { Write-Line Line DarkGreen "Disc Name:" 22 $Params[2] }
if ($Params[0] -eq 32) { Write-Line Line DarkGreen "Volume Name:" 22 $Params[2] }
if ($Params[0] -lt $Attributes.Count) { Add-XML-Attribute $DiscData $Attributes[$Params[0]] $Params[2] }
break
}
"TINFO"
{
$CurStream=-1
0..1 | foreach { $Params[$_]=[convert]::ToInt32($Params[$_], 10) }
if ($CurTitle -ne $Params[0]) { $CurTitleNode = Get-XML-Element $DiscData "Title" "Number" ($CurTitle=$Params[0]) -Force }
if ($Params[1] -eq 16)
{
$SourceNumber = ($Params[3].Split('('))[0]
$SourceNumber = $SourceNumber.Replace(".mpls", "").Replace(".m2ts", "")
$SourcePart = ""
if ($Params[3].Contains(".mpls("))
{
$SourcePart = ($Params[3].Split('('))[1].TrimEnd(')')
}
if ($Params[3].Contains(".mpls"))
{
$SourceEx = "mpls"
}
elseif ($Params[3].Contains(".m2ts"))
{
$SourceEx = "m2ts"
}
$CurTitleName = Add-XML-Element $CurTitleNode "Names"
$Copy = Get-XML-Element $CurTitleName "Name" "Source" $SourceNumber -Force
Add-XML-Attribute $Copy "Part" $SourcePart
Add-XML-Attribute $Copy "Ext" $SourceEx
}
if ($Params[1] -lt $Attributes.Count) { Add-XML-Attribute $CurTitleNode $Attributes[$Params[1]] $Params[3] }
if ($Params[1] -eq 26)
{
$Params[3]=$Params[3].Replace('(', '').Replace(')', '')
$CurTitleNode.SegmentsMap=$Params[3]
$Index=0
$Params[3].Split(',') | foreach {
if ($_ -ne "...") {
$Index++
[void] (Get-XML-Element (Get-XML-Element $DiscData "Segment" "Number" $_ -Force) "Title" "Number" $Params[0] -Force)
Add-XML-Attribute (Add-XML-Attribute (Add-XML-Element $CurTitleNode "Segment") "Number" $_ 2) "Order" $Index
}
}
}
break
}
"SINFO"
{
0..2 | foreach { $Params[$_]=[convert]::ToInt32($Params[$_], 10) }
if ($CurTitle -ne $Params[0]) { $CurTitleNode = Get-XML-Element $DiscData "Title" "Number" ($CurTitle=$Params[0]) -Force; $CurStream=-1 }
if ($CurStream -ne $Params[1]) { $CurStreamNode = Get-XML-Element $CurTitleNode "Stream" "Number" ($CurStream=$Params[1]) -Force }
if ($Params[2] -lt $Attributes.Count) { Add-XML-Attribute $CurStreamNode $Attributes[$Params[2]] $Params[4] }
break
}
default { "Unknown Output: " + $Type; break }
}
}
#$NewData.Save("D:\" + $DiscData.Name + ".xml")
}
else
{
$NewData = [xml] (Get-Content $DiscName); $DiscData = $NewData.SelectSingleNode("Disc")
}
Write-Line Line DarkGreen "Number of Titles:" 22 ([string]$Title)
Write-Line Line DarkGreen "Duplicated Titles:" 22 ([string]$Dups.Duplicate.count)
Write-Line Head DarkGreen "Done."
Write-Line Main DarkRed "Scan Complete."
Write-Pillar
Write-Line Main Gray "Title Decimation."
Write-Line Head Green "Gathering Info On Titles."
$DiscData.Title | foreach {
Enum-Streams $_ "Video"
Enum-Streams $_ "Audio"
Enum-Streams $_ "Subtitles"
Set-Times $_
}
if ($DiscData.Type -eq "Blu-ray disc")
{
$Dups.Duplicate | foreach {
$Dup = $_
$DiscData.Title | Where-Object {$Dup.Source -eq $_.Names.Name.Source -and $Dup.Part -eq $_.Names.Name.Part -and $Dup.Ext -eq $_.Names.Name.Ext} | foreach {
$TitleNames=$_.Names
$Dup.Copy | foreach {
$TitleName=Add-XML-Element $TitleNames "Name"
Add-XML-Attribute $TitleName "Source" $_.Source
Add-XML-Attribute $TitleName "Part" $_.Part
Add-XML-Attribute $TitleName "Ext" $_.Ext
}
}
}
$DiscData.SelectNodes("Title/Names/Name[@Part=1]") | foreach {
$TitleName=$_.Source
$DiscData.SelectNodes("Title/Names/Name[@Source=$TitleName]") | foreach {
if ($_.Part)
{
$_.Part = [string]([convert]::ToInt32($_.Part) + 1)
}
else
{
$_.Part = "1"
}
}
}
$DiscData.SelectNodes("Title/Names/Name[@Part=1]") | foreach {
$TitleName=$_.Source
$TitleDuration=0
$TitleSegmentsCount=0
$TitleSegmentsMap=""
$DiscData.SelectNodes("Title/Names/Name[@Source=$TitleName]") | Sort-Object Part | foreach {
$TitleDuration+=[convert]::ToInt32($_.ParentNode.ParentNode.Duration.InSeconds)
if ($TitleSegmentsMap)
{
$TitleSegmentsMap+=","
}
$TitleSegmentsMap+=$_.ParentNode.ParentNode.SegmentsMap
$TitleSegmentsCount+=[convert]::ToInt32($_.ParentNode.ParentNode.SegmentsCount)
}
$TitleNumber=[convert]::ToInt32($DiscData.SelectSingleNode("Title[last()]").Number) + 1
$NewTitle=Get-XML-Element $DiscData "Title" "Number" $TitleNumber -force
Add-XML-Attribute $NewTitle "SourceFileName" ($TitleName + ".mpls")
Add-XML-Attribute $NewTitle "SegmentsMap" $TitleSegmentsMap.Trim(',')
Add-XML-Attribute $NewTitle "SegmentsCount" $TitleSegmentsCount
Add-XML-Attribute $NewTitle "Dummy" "True"
Add-XML-Attribute $NewTitle "Duration" (Convert-Timecode-To-Base-Duration $TitleDuration -AsSeconds -AsTimeCode -FromSeconds)
Set-Times $NewTitle
$a = Add-XML-Element (Add-XML-Element $NewTitle "Names") "Name"
Add-XML-Attribute $a "Ext" $_.Ext
Add-XML-Attribute $a "Source" $_.Source
Add-XML-Attribute $a "Part" $_.Part
$Index=0
$TitleSegmentsMap.Split(',') | foreach {
if ($_ -ne "...") {
$Index++
[void] (Get-XML-Element (Get-XML-Element $DiscData "Segment" "Number" $_ -Force) "Title" "Number" $TitleNumber -Force)
Add-XML-Attribute (Add-XML-Attribute (Add-XML-Element $NewTitle "Segment") "Number" $_ 2) "Order" $Index
}
}
}
$DiscData.Title | foreach {
$TitleName=""
$TitleExt=""
$TitleNameCount=0
$_.SelectNodes("Names/Name") | Sort-Object Source | foreach {
$TitleNameCount+=1
if (-not $_.Part)
{
if ($TitleName) { $TitleName+="-" }
$TitleName+=$_.Source
}
if ($_.Ext) {$TitleExt=$_.Ext}
}
if ($TitleNameCount -eq 1)
{
$TitleName+=("." + $TitleExt)
}
$_.SourceFileName = $TitleName
}
$DeleteList = Add-XML-Element $DiscData "DeleteList"
$DiscData.Title | sort-object @{Expression={([object[]]$_.Names.Name)[0].Ext};Descending=$true}, SourceFileName | foreach {
$ThisTitle = $_
$TitleName = ""
$ThisTitle.Names.Name | sort-object Source | foreach {
if ($TitleName) { $TitleName+=", " }
$TitleName+=$_.Source
if ($_.Part)
{
$TitleName+="-" + $_.Part.PadLeft(2,'0')
}
$TitleName+="." + $_.Ext
}
if ($ThisTitle.Dummy)
{
$TitleName+=" (Dummy)"
}
$TitleName += " - " + $ThisTitle.Duration.TimeCode + " (" + $ThisTitle.Duration.InSeconds + " secs)"
if ($ThisTitle.ChapterCount)
{
$TitleName += " - " + $ThisTitle.ChapterCount + " Chapters."
}
Write-Line Line Green "Title " $_.Number 13 "Added:" 22 $ThisTitle.SegmentsMap (-3) "-" (-3) $TitleName
}
Write-Line Head Green "Done."
Write-Line Head White "Gathering Info On Segments."
$DiscData.SelectNodes("Title") | foreach {
Enum-Unique-Segments $_
}
do
{
$change2=$false
$Pseudo = Add-XML-Element $DiscData "PseudoTitles"
do
{
$Change=$false
$DiscData.Title | foreach {
$Count=0
$Total=_I ($Title=$_).Duration.InSeconds
$Segment=$null
$Occurrences=0
Get-Title-Segments $_ -Order | foreach {
if ($_.Duration -eq $null) { if ($Segment -ne $_) {$Count++ ; $Segment=$_; $Occurrences=1 } else { $Occurrences++ } }
else { $Total-=$_.Duration }
}
if ($Count -eq 1)
{
Add-XML-Attribute $Segment "Duration" ((_I $Total) / $Occurrences)
$Change2=$Change=$true
}
}
}
while ($Change)
do
{
$Change=$false
$DiscData.Title | foreach {
$ThisTitle = $_
$SegmentsMap = ',' + $ThisTitle.SegmentsMap + ','
$Duration = 0
$PTitle=$null
$SegmentsMap.Split(',') | where {$_ -ne "" -and $_ -ne "..."} | foreach {
$Segment = $DiscData.SelectSingleNode("Segment[@Number=$_]")
if ($Segment.Duration) { $Duration+=$Segment.Duration.InSeconds }
else
{
if (-not $PTitle) { $PTitle = Get-XML-Element $Pseudo "Title" "Number" $ThisTitle.Number -Force }
if (-not ($PSegment = $PTitle.SelectSingleNode("Segment[@Number=$_]")))
{ $PSegment = Get-XML-Element $PTitle "Segment" "Number" $_ -Force; Add-XML-Attribute $PSegment "Occurrences" 1 }
else { $PSegment.Occurrences = [string](1 + $PSegment.Occurrences) }
}
}
if ($PTitle)
{
Add-XML-Attribute $PTitle "Duration" (([int]$ThisTitle.Duration.InSeconds) - $Duration)
}
}
}
while ($Change)
if ($Pseudo.Title)
{
$Pseudo.Title | foreach {
if ($_.Segment.count -ne 2)
{
$ThisTitle = $_
$TitleNumber = $_.Number
$ThisTitle.Segment | foreach {
$ThisSegment = $_
$Number=$_.Number
if (-not $DiscData.SelectSingleNode("Segment[@Number!=$Number]").Duration)
{
$ThisTitle.Segment | foreach {
if ($_.Number -ne $Number)
{
$Found = $Pseudo.SelectNodes("Title[Segment[@Number=$Number] and (@Number!=$TitleNumber) and Segment[2] and not(Segment[3])]")
if ($Found.Count -ge ($ThisTitle.Segment.Count - 1))
{
$Seg = @()
$Tit = @()
$Found | foreach {
$Seg+=$_.SelectSingleNode("Segment[@Number!=$Number]").Number
$Tit+=$_.Number
}
$Last = -1
$Seg = ( $Seg | Sort-Object | foreach { if ($_ -ne $Last) { $_ }; $Last = $_ } )
if ($Seg.Count -eq ($ThisTitle.Segment.Count - 1))
{
$Last = -1
$Tit2 = ( $Tit | Sort-Object | foreach { if ($_ -ne $Last) { $_ }; $Last = $_ } )
$Last = 0
$Tit2 | foreach {
$Last+=[convert]::ToInt64($Pseudo.SelectSingleNode("Title[@Number=$_]").Duration)
}
Add-XML-Attribute ($DiscData.SelectSingleNode("Segment[@Number=$Number]")) "Duration" (([convert]::ToDouble($ThisTitle.Duration) - $Last)) 0
$Change2=$true
}
}
}
}
}
}
}
}
}
[void] $DiscData.RemoveChild($Pseudo)
$Pseudo = $null
$DiscData.Segment | foreach {
$ThisSegment = $_
if ($ThisSegment.Duration -and [convert]::ToDouble($ThisSegment.Duration) -lt 3)
{
$Number = $ThisSegment.Number
Get-Segment-Titles ([convert]::ToInt32($Number)) | foreach {
$ThisTitle = $_
$ThisTitle.SelectNodes("Segment[@Number=$Number]") | foreach { $ThisTitle.SegmentsCount = [string]([convert]::ToInt64($ThisTitle.SegmentsCount) - 1); [void]$ThisTitle.RemoveChild($_) }
$ThisTitle.SegmentsMap = ([string]$ThisTitle.SegmentsMap + ",").Replace(("," + $Number + ","), ",").TrimEnd(",")
}
[void]$DiscData.RemoveChild($ThisSegment)
Write-Line Line Red "Removing: " -Cyan "Segment" ([int]-(6-$Number.Length)) $Number -White 30 "Reason: Too Insignificant To Factor In."
}
}
$DiscData.Title | foreach {
if ([convert]::ToInt64($_.SegmentsCount) -eq 0)
{
Write-Line Line Red "Removing: " -Green "Title" ([int]-(8-$_.Number.Length)) $_.Number -White 30 "Reason: No More Segments Left."
[void]$DiscData.RemoveChild($_)
}
}
}
while ($Change2)
$DiscData.Segment | Sort-Object @{ Expression={([int]$_.Number)} } | foreach {
$ThisSegment = $_
if ($ThisSegment.Duration)
{
Write-Line Line White "Segment:" ([int](0 - (6 - ([string]$ThisSegment.Number).Length))) -Yellow ([string]$ThisSegment.Number) -White 16 "Has a duration of " -Yellow (Convert-Timecode-To-Base-Duration $ThisSegment.Duration -AsTimecode -Fromseconds -AsSeconds) -White " (" $ThisSegment.Duration " Secs)."
}
else
{
Write-Line Line White "Segment:" ([int](0 - (6 - ([string]$ThisSegment.Number).Length))) ([string]$ThisSegment.Number) 16 "Has an Unknown duration."
}
}
Write-Line Head White "Done."
Write-Line Head Black "Processing Duplicate Titles."
$DiscData.Title | foreach {
$ThisTitle=$_
$ThisTitleNumber=_I $ThisTitle.Number
$ThisTitleChapterCount=_I $ThisTitle.ChapterCount
$ThisTitleSegmentMap=[string]$ThisTitle.SegmentsMap
$DiscData.Title | foreach {
$NewTitle=$_
if ($ThisTitleNumber -ne ($NewTitleNumber=_I $NewTitle.Number))
{
$NewTitleChapterCount=_I $NewTitle.ChapterCount
if ($ThisTitleSegmentMap -eq ($NewTitleSegmentMap=[string]$NewTitle.SegmentsMap))
{
if ($ThisTitleChapterCount -ne $NewTitleChapterCount)
{
if ($ThisTitleChapterCount -eq 0)
{
Get-Title-Segments $ThisTitle | foreach { Add-Delete-Request $ThisTitleNumber $_.Number "Duplicate With No Chapters" $NewTitleNumber 5 }
}
}
if ((($ThisTitle.SelectNodes("Stream[@Type=('Audio' or 'Subtitles') and @LangCode='jpn']")).Count) -and (-not ($NewTitle.SelectNodes("Stream[@Type=('Audio' or 'Subtitles') and @LangCode='jpn']")).Count) -and ($NewTitle.UniqueAudio -ge $ThisTitle.UniqueAudio) -and ($NewTitle.UniqueSubtitle -ge $ThisTitle.UniqueSubtitle))
{
Get-Title-Segments $ThisTitle | foreach { Add-Delete-Request $ThisTitleNumber $_.Number "Duplicate Region A Version" $NewTitleNumber 5 }
}
}
}
}
}
Write-Line Head Black "Processing Contained Titles."
$DiscData.Title | foreach {
$ThisTitle=$_
$ThisTitleNumber=_I $ThisTitle.Number
$ThisTitleChapterCount=_I $ThisTitle.ChapterCount
$ThisTitleSegmentMap=[string]$ThisTitle.SegmentsMap
$ThisTitleSegments=(Get-Title-Segments $_)
$ThisTitleSegmentCount=_I $ThisTitle.SegmentsCount
$ContainedSegments = 0
$Reason = 0
$ThisTitleSegments | foreach {
$ThisSegment = $_
$ContainedSegment=0
(Get-Segment-Titles $_ $ThisTitleNumber) | foreach {
$NewTitle=$_
$NewTitleNumber=_I $_.Number
$Contained=0
if ($NewTitle.SegmentsMap -ne $ThisTitle.SegmentsMap)
{
$NewTitleChapterCount=_I $NewTitle.ChapterCount
$NewTitleSegmentCount=_I $NewTitle.SegmentsCount
$NewTitleSegments = Get-Title-Segments $NewTitle
if ($NewTitle.SegmentsMap.Contains($ThisTitle.SegmentsMap))
{
if ($ThisTitleSegmentCount -eq 1)
{
if (($NewTitleChapterCount -ne 0) -and ($ThisTitleChapterCount -eq 0))
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Component Of Larger Title" $NewTitleNumber 5
}
}
else
{
if (($NewTitleChapterCount -ne 0) -and ($ThisTitleChapterCount -eq 0))
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Component Of Larger Title" $NewTitleNumber 5
}
}
}
elseif ($ThisTitle.SegmentsMap.Contains($NewTitle.SegmentsMap))
{
if (($NewTitleChapterCount -ne 0) -and ($ThisTitleChapterCount -eq 0))
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Amalgamation Of Better Titles" $NewTitleNumber 5 -Rename
}
else
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Play All" $NewTitleNumber 5 -Rename
}
}
else
{
$Count = Compare-Segments $NewTitle.SegmentsMap $ThisTitle.SegmentsMap
if ($Count -eq $ThisTitle.SegmentsCount)
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Expanded Version" $NewTitleNumber 0
}
elseif ($Count -eq $NewTitle.SegmentsCount)
{
Add-Delete-Request $ThisTitleNumber $ThisSegment.Number "Suspected Shortened Version" $NewTitleNumber 0
}
}
}
}
}
}
Write-Line Head White "Removing Titles."
$Nuke_Used=$true
$DiscData.Title | foreach {
if ($Nuke_Used)
{
if ($Nuke_Colour -eq "-Yellow")
{
$Nuke_Colour = "-White"
}
else
{
$Nuke_Colour = "-Yellow"
}
$Nuke_Used=$false
}
$NewTitle = $_
if ($_.Dummy)
{
Nuke-Title $Newtitle "Temporary Title"
}
else
{
if (([int]$NewTitle.Duration.InSeconds) -lt $MinDuration)
{
Nuke-Title $Newtitle "Shorter Than Minimum Duration"
}
elseif ($MaxDuration -and (([double]$NewTitle.Duration.InSeconds) -gt $MaxDuration))
{
Nuke-Title $Newtitle "Longer Than Maximum Duration"
}
if (([int]$NewTitle.ChapterCount) -lt $MinChapters)
{
Nuke-Title $Newtitle "Not Enough Chapters"
}
if (-not $NewTitle.UniqueAudio)
{
Nuke-Title $Newtitle "No Audio Tracks"
}
if ($NewTitle.VideoQuality -lt 4)
{
Nuke-Title $Newtitle "Not HD Resolution"
}
}
}
$DiscData.Title | foreach {
if ($Nuke_Used)
{
if ($Nuke_Colour -eq "-Yellow")
{
$Nuke_Colour = "-White"
}
else
{
$Nuke_Colour = "-Yellow"
}
$Nuke_Used=$false
}
$NewTitle = $_
if ($ThisTitle=Get-XML-Element $DeleteList "Title" "Number" $NewTitle.Number)
{
$ThisSegment = ([Object[]]$ThisTitle.Segment)[0]
$c=@()
$ThisSegment.DeleteRequest | foreach {
if (-not $c.contains($_.Reason))
{
$c += $_.Reason
$ThisDeleteRequest = $_
$b=$true
$ThisTitle.Segment | foreach {
if (-not $_.SelectSingleNode(("DeleteRequest[@Reason=""" + $ThisDeleteRequest.Reason + """]"))) { $b=$false }
}
if ($b) {
$a = @()
Get-Title-Segments $NewTitle -Order -Unique | foreach { $ThisTitle.SelectNodes(("Segment[@Number=" + $_.Number + "]")) } | foreach {
$_.SelectNodes("DeleteRequest[@Reason=""" + $ThisDeleteRequest.Reason + """]") | foreach { if (-not (([object[]] $a).Contains($_.Cause))) {$a+=$_.Cause} }
}
$b=""
$a | foreach { if (-not ([object[]]$DiscData.Title)[$_].Delete) {([string]$b)+=$_ + ","}}
if ($b -and (-not $NewTitle.Delete))
{
if (0 -ne $ThisDeleteRequest.Level)
{
[void] (Nuke-Title $Newtitle $ThisDeleteRequest.Reason ("[" + "$b".TrimEnd(',') + "]"))
}
else
{
Write-Line Line Green "Hint: Title" ([int]-1) (([string]$NewTitle.Number).PadLeft(([string]([object[]]$DiscData.Title).Count).Length)) " is a " $ThisDeleteRequest.Reason
}
}
if ($ThisDeleteRequest.Rename)
{
$d=0
$ThisDelete
Get-Title-Segments $NewTitle -Order -Unique | foreach {
Get-Segment-Titles $_ -Order | foreach {
$SegmentTitle=$_
if (($_.SegmentsCount -lt $NewTitle.SegmentsCount) -and (',' + $NewTitle.SegmentsMap + ',').Contains((',' + $_.SegmentsMap + ',')))
{
$e = ($NewTitle.SegmentsMap + ',')
$f = 0
$g = Get-XML-Element $_ "Rename" "Source" $NewTitle.SourceFileName -force
Add-XML-Attribute $g "SourceList" ""
Add-XML-Attribute $g "SourceCount" "0"
Add-XML-Attribute $g "SourceDuration" $NewTitle.Duration.InSeconds
Add-XML-Attribute $g "SourceNumber" $NewTitle.Number
while ($e)
{
if ($e.StartsWith(($_.SegmentsMap + ',')))
{
$h = 0
$_.SegmentsMap.Split(',') | foreach { $g.SourceList+=((",{0:" + ("0" * $NewTitle.SegmentsCount.ToString().Length) + "}") -f $f); $g.SourceCount=[string](1 + $g.SourceCount); $f++ }
$e = $e.Remove(0, $_.SegmentsMap.Length + 1)
}
else
{
$e = $e.Remove(0, $e.Indexof(',') + 1)
$f++
}
}
$g.SourceList = $g.SourceList.Trim(',')
}
}
}
}
}
}
}
}
}
$a = ($DiscData.SelectNodes("Title[not(@Delete)]"))
Write-Line Head White "Number Of Titles Left To Rip:" ([int]-1) ([string]([object[]]$a).Count)
Write-Line Head DarkCyan -Cyan "Processing Playlists."
$PlayLists = @()
$DiscData.Title | foreach {
$ThisTitle = $_
if ($ThisTitle.Rename -and (-not $ThisTitle.Delete))
{
$a = ([Object[]]($_.Rename | Sort-Object {[double]$_.SourceDuration} -Descending))[0]
$b = 0
if ($PlayLists.count)
{
for ($b = 0; $b -lt ([Object[]]$PlayLists).count; $b++)
{
if ($PlayLists[$b] -eq $a.SourceNumber)
{
break
}
}
}
if ($b -eq ([Object[]]$PlayLists).count)
{
$PlayLists+=$a.SourceNumber
Write-Line Line DarkCyan -Cyan "Title: " $a.SourceNumber "(" $a.Source ") is a playlist."
}
}
}
Write-Line Head DarkCyan -Cyan "Number of Playlists Found:" ([int]-1) ([string]([Object[]]$PlayLists).count)
do
{
$Change = $false
$DiscData.Title | foreach {
$ThisTitle=$_
if (-not $_.Rename)
{
$CanBe=""
if (([object[]]$ThisTitle.Names.Name)[0].Ext -eq "mpls")
{
$CanBeList=@()
$CanBePlus=@()
$CanBeMinus=@()
$_.Names.Name | foreach {
$ThisName = $_
$ThisNumber = [convert]::ToInt32($_.Source)
$FindName = ([string]($ThisNumber - 1)).PadLeft(5,'0')
$FoundTitle = $DiscData.SelectNodes("Title[(Names/Name/@Source=""$FindName"") and Rename]")
if (([Object[]]$FoundTitle).Count -gt 1)
{
$FoundTitle = ($FoundTitle.Names.Name | Where-Object { $_.Source -eq $FindName } | Sort-Object { [int]$_.Part })[0].ParentNode.ParentNode
}
if (([Object[]]$FoundTitle).Count -eq 1)
{
$a = ([object[]]($FoundTitle.Rename | Sort-Object {[int]$_.SourceDuration} -Descending))[0]
$CanBeList+= (([int]$a.SourceList) + 1)
$CanBePlus+=$a
}
$FindName = ([string]($ThisNumber + 1)).PadLeft(5,'0')
$FoundTitle = $DiscData.SelectNodes("Title[(Names/Name/@Source=""$FindName"") and Rename]")
if (([Object[]]$FoundTitle).Count -gt 1)
{
$FoundTitle = ($FoundTitle.Names.Name | Where-Object { $_.Source -eq $FindName } | Sort-Object { [int]$_.Part })[0].ParentNode.ParentNode
}
if (([Object[]]$FoundTitle).Count -eq 1)
{
$a = ([object[]]($FoundTitle.Rename | Sort-Object {[int]$_.SourceDuration} -Descending))[0]
$CanBeList+= (([int]$a.SourceList) - 1)
$CanBeMinus+=$a
}
}
$CanBe = ($CanBeList | Sort-Object -Unique)
if (([object[]]$CanBe).Count -eq 1)
{
$CanBe = ([object[]]$CanBe)[0]
if ($CanBeMinus)
{
$g = $CanBeMinus[0]
}
else
{
$g = $CanBePlus[0]
}
[void] $ThisTitle.AppendChild($g.CloneNode($true))
$ThisTitle.Rename.SourceList = [string]$CanBe
$Change=$True
}
}
}
}
}
while ($Change)
$DiscData.Title | foreach {
$ThisTitle = $_
if ($_.Rename)
{
$a = ([Object[]]($_.Rename | Sort-Object {[int]$_.SourceDuration} -Descending))[0]
if (([Object[]]$PlayLists).count -lt 2)
{
if ($_.SourceFileName)
{
Add-XML-Attribute $_ "OutputName" (([string](([int]$a.SourceList) + 1)).PadLeft(2,'0') + "-" + ([string]$_.SourceFileName).Replace(".m2ts", "").Replace(".mpls", "") + ".mkv")
}
else
{
Add-XML-Attribute $_ "OutputName" (([string](([int]$a.SourceList) + 1)).PadLeft(2,'0') + "-" + ([string]$a.Source).Replace(".m2ts", "").Replace(".mpls", "") + ".mkv")
}
}
else
{
if ($_.SourceFileName)
{
Add-XML-Attribute $_ "OutputName" (([string]$_.Source).Replace(".m2ts", "").Replace(".mpls", "") + "-" + ([string](([int]$a.SourceList) + 1)).PadLeft(2,'0') + "-" + ([string]$_.SourceFileName).Replace(".m2ts", "").Replace(".mpls", "") + ".mkv")
}
else
{
Add-XML-Attribute $_ "OutputName" (([string]$_.Source).Replace(".m2ts", "").Replace(".mpls", "") + "-" + ([string](([int]$a.SourceList) + 1)).PadLeft(2,'0') + ".mkv")
}
}
}
else
{
if (([Object[]]$PlayLists).count -eq 1)
{
if ($CanBe)
{
Add-XML-Attribute $_ "OutputName" ($CanBe + "-" + $_.SourceFileName.Replace(".mpls", "") + ".mkv")
}
else
{
Add-XML-Attribute $_ "OutputName" ("00-" + $_.SourceFileName.Replace(".mpls", "") + ".mkv")
}
}
else
{
Add-XML-Attribute $_ "OutputName" ($_.SourceFileName.Replace(".mpls", "") + ".mkv")
}
}
}
$a = ($DiscData.SelectNodes("Title[not(@Delete)]") | Sort-Object @{Expression={$_.Names.Name[0].Ext}; Descending=$true}, OutputName)
}
else
{
$DiscData.Title | foreach {
$NewTitle = $_
if ($_.Dummy)
{
Nuke-Title $Newtitle ""
}
else
{
if (([int]$NewTitle.Duration.InSeconds) -lt $MinDuration)
{
Nuke-Title $Newtitle "Shorter Than Minimum Duration"
}
elseif ($MaxDuration -and (([int]$NewTitle.Duration.InSeconds) -gt $MaxDuration))
{
Nuke-Title $Newtitle "Longer Than Maximum Duration"
}
if (([int]$NewTitle.ChapterCount) -lt $MinChapters)
{
Nuke-Title $Newtitle "Not Enough Chapters"
}
if (-not $NewTitle.SelectNodes("Stream[@Audio]"))
{
Nuke-Title $Newtitle "No Audio Tracks"
}
}
}
$a = 1
$DiscData.SelectNodes("Title[not(@Delete)]") | foreach {
Add-XML-Attribute $_ "OutputName" ("Title {0:00}.mkv" -f $a)
$a++
}
$a = $DiscData.SelectNodes("Title[not(@Delete)]")
}
if ($a)
{
Write-Line Main Gray "Done."
Write-Pillar
([object[]]$a) | ForEach {
Write-Line Main Black "Title:" $_.Number
Write-Line Head Green "Duration:" (-5) -DarkGreen $_.Duration.Hours ":" $_.Duration.Minutes ":" $_.Duration.Seconds 45 -black "(" -darkgreen $_.Duration.InSeconds -black ")"
Get-Title-Segments $_ -Order | foreach {
if ($_.Duration)
{
Write-Line Line Green "Segment" 9 $_.Number ":" 15 $_.Duration
}
else
{
Write-Line Line Green "Segment" 9 $_.Number ":" 15 "Unknown"
}
}
Write-Line Head Green "End Durations."
Write-Line Head Magenta "Properties:"
Write-Line Line Magenta "Output Name:" 22 $_.OutputName
if ($_.ChapterCount)
{
Write-Line Line Magenta "Chapter Count:" 22 $_.ChapterCount
}
else
{
Write-Line Line Magenta "Chapter Count:" 22 "0"
}
Write-Line Head Magenta "End"
}
Write-Line Main Black "End Titles."
Write-Pillar
break
$FileLast = ([Object[]]$a).Count
#Prepare Output Folder
$FolderNumber = 1
if (-not ((Get-Item -Path $Dest -ErrorAction SilentlyContinue))) {[void](New-Item -Path $Dest -ItemType "directory")}
while (Get-Item -Path ("{0}\Disc {1:00}" -f $Dest, $FolderNumber) -ErrorAction SilentlyContinue) { $FolderNumber++ }
$OutPutDirectory="{0}\Disc {1:00}" -f $Dest, $FolderNumber
if ($DiscData.Name) { $DiscName = $DiscData.Name }
else { $DiscName = $DiscData.VolumeName }
[void](New-Item -Path $OutPutDirectory -ItemType "directory" -ErrorAction SilentlyContinue)
Add-Content -Path ("$OutPutDirectory\~" + ([RegEx]::Replace($DiscName, "[{0}]" -f ([RegEx]::Escape(-join [System.IO.Path]::GetInvalidFileNameChars())), '_'))) -Value ($DiscName + "`n" + $DiscData.VolumeName)
#End
$a | ForEach {
$ThisTitle=$_
$DoneLast = 0
if ($FileLast -gt 1) { while ($a[$DoneLast].Number -ne $ThisTitle.Number) { $DoneLast++ } }
$NewName = $_.OutputName
Write-Line Main White ("Progess: {0} of {1}." -f ($DoneLast+1), $FileLast)
Skip-Lines 1
Write-Line Main Black "Saving Title: " $ThisTitle.Number
Write-Line Head Green "Title Paths"
Write-Line Line Green "Temporary Name" 18 ":" ([int]-2) ([int](0 - $OutPutDirectory.Length)) $ThisTitle.OutputFileName
Write-Line Line Green "To Directory" 18 ":" ([int]-1) $OutPutDirectory "\"
Write-Line Line Green "Final Name" 18 ":" ([int]-2) ([int](0 - $OutPutDirectory.Length)) $NewName
Write-Line Head Green "Set."
$ReDo=$SubtitlesRemoved=$NowSaving=$false
if (-not ((Get-Item -Path $OutPutDirectory -ErrorAction SilentlyContinue))) {[void](New-Item -Path $OutPutDirectory -ItemType "directory")}
&$MakeMKVCon "--noscan" "-r" "--messages=-stdout" "--progress=-stdout" $ProfileCommand "--minlength=0" "mkv" "disc:$Disc" $ThisTitle.Number $OutPutDirectory | ForEach-Object -Process {
$Type = $Line = $Temp = ""
([string] $_).Split(":", 2) | foreach {if ($Type) {$Line = $_} else {$Type = $_}}
$EscapeOn = $InQuotes = $false
$Params = @()
$Line.ToCharArray() | foreach {
switch ($_)
{
'\' { if (-not $EscapeOn -and $InQuotes) { $EscapeOn = $true; break } }
',' { if (-not $InQuotes) { $Params+=$Temp; $Temp=""; break } }
'"' { if (-not $EscapeOn) { $InQuotes = -not $InQuotes; break } }
default { $Temp+=$_; $EscapeOn = $false }
}
}
$Params+=$Temp
switch -wildcard ($Type)
{
"MSG"
{
switch ([convert]::ToInt32($Params[0]))
{
$Message_DEBUG { if ($NowSaving) { Write-Line Line Red $Params[3]; break }}
$Message_DEBUG_LOG { break }
$Message_APP_START { $host.ui.RawUI.WindowTitle = $Params[5] ; break }
$Message_BUP_NOT_EQU_IFO { break }
$Message_PATH_NOT_EXIST { "Fatal Error: Destination Path Not Found." ; pause ; break }
$Message_OPENING_FILES { break }
$Message_FORCED_SUBTITLES_REMOVED {if ($SubtitlesRemoved) {$SubtitlesRemoved+=",{0}" -f $Params[5]} else {$SubtitlesRemoved=$Params[5]}; break }
$Message_AV_SYNC_ISSUES_FOUND { Write-Line Head Cyan "Av Sync Issues:" }
$Message_AV_SYNC_ISSUE { Write-Line Line Cyan -Magenta "@" -White "[" -Yellow $Params[6] -None "] Stream " -Green $Params[5] -None " - " -Gray $Params[8]; break }
$Message_QUERY_OVERWRITE_FILE { break }
$Message_SAVE_FAILED { Write-Line Main Black "Fatal Error: Failed to Complete Processing." ; pause ; break }
$Message_SAVE_PART_SUCCESSFUL { break }
$Message_SAVE_SUCCESSFUL { break }
$Message_OPERATION_SUCCESSFUL { if (-not $NowCompleted) { $NowCompleted = $true; break } }
$Message_SAVING_TITLES { if (-not $NowSaving) { $NowSaving = $true; break } }
$Message_COMPLETE_SUCCESSFUL
{
if ($SubtitlesRemoved) { Write-Line Line DarkGray "Empty Tracks [" $SubtitlesRemoved "] Removed." }
if ($ReDo)
{
if (-not ((Get-Item -Path ($OutPutDirectory + "\ERROR") -ErrorAction SilentlyContinue))) {[void](New-Item -Path ($OutPutDirectory + "\ERROR") -ItemType "directory")}
Move-Item ("{0}\{1}" -f $OutPutDirectory, $ThisTitle.OutputFileName) ($OutPutDirectory + "\ERROR")
Write-Line Line Red "Moved Broken File To ERROR Folder."
Write-Line Head Yellow "Failed."
}
else
{
Write-Line Head Yellow "Renaming" 18 ":"
Write-Line Line Yellow "From" 18 ":" ([int]-1) $ThisTitle.OutputFileName
Write-Line Line Yellow "To" 18 ":" ([int]-1) $NewName
Rename-Item -Path ("{0}\{1}" -f $OutPutDirectory, $ThisTitle.OutputFileName) -NewName $NewName
if ($MKVPropEdit) { &$MKVPropEdit "-e" "info" "-s" ("title=SegmentsMap:" + $ThisTitle.SegmentsMap) ("{0}\{1}" -f $OutPutDirectory, $NewName) | Out-Null }
if(!$?) { Write-Line Line Red "MKVPropEdit Error."; pause }
Write-Line Head Yellow "Successful."
}
Write-Line Main Black "Done."
Skip-Lines 1
break
}
$Message_COMPLETE_PART_SUCCESSFUL { break }
$Message_DISC_FAILED { Write-Line Line Red "Failed to Open Disc." }
$Message_LIBAV_TRACE_ERROR { Write-Line Line Red "LibAV Trace Error."; break }
$Message_SCSI_ERROR { Write-Line Line Red "SCSI Error."; break }
$Message_LOAD_HASH_TABLE { break }
$Message_TITLE_WITH_CELLS_ADDED { break }
$Message_TITLE_ADDED { break }
$Message_TITLE_EQUAL { break }
$Message_DIRECT_DISC_ACCESS { break }
$Message_CORRUPTION_IN_SOURCE { Write-Line Line Red "Corruption In Source."; $ReDo=$true; break }
default { Write-Line Line DarkMagenta "Unknown Message (" $Params[0] "): " $Params[3]; Add-Content -Path "F:\Work\MakeMKV.log" -Value $_ ; break }
}
}
"PRGT" { $ProgressTName = $Params[2] ; break }
"PRGC" { $ProgressCName = $Params[2] ; break }
"PRGV"
{
$ProgressCVal = _I $Params[0] ; $ProgressTVal = _I $Params[1] ; $ProgressMax = _I $Params[2] ; $ProgressDiv = $ProgressTVal / $ProgressMax
Write-Progress -activity "Total Progress" -Status ("Processing Title: {0} of {1}" -f ($DoneLast + 1), $FileLast) -CurrentOperation ("{0} -> {1}" -f $ThisTitle.SourceFileName, $ThisTitle.OutputFileName) -Id 0 -PercentComplete ((($DoneLast / $FileLast) + ((1 / $FileLast) * $ProgressDiv)) * 100) -ParentId -1
Write-Progress -activity "Current Progress" -Status $ProgressCName -CurrentOperation ("{0:p} Completed" -f $ProgressDiv) -Id 1 -PercentComplete ($ProgressDiv * 100) -ParentId 0
break
}
default { if ($Type -ne "DRV") { $_ } ; break }
}
}
}
}
else
{
Write-Line Head Red "No Titles Left To Rip."
Write-Line Main White "Done."
}
$DiscRecorder.EjectMedia()
Start-Sleep -Seconds 1
}