fix(v5): 5.6.1 — Untertitel-Spuren wieder erkannt: Stream-Typ per Code (6203), nicht per lokalisiertem Wort
Commander-Fund 03.09.2026 (Digimon Adventure: Last Evolution Kizuna): im
Auswahl-Dialog fehlten die UNTERTITEL-Chips. Gemessen mit makemkvcon64 -r
info auf diesem PC: MakeMKV schreibt den Stream-Typ in seiner Anzeigesprache
("Untertitel"), der Parser prüfte auf "Subtitles" (Messung vom 26.07. an
einem englischen MakeMKV). "Audio" heißt zufällig gleich, deshalb fiel nur
der Untertitel-Weg aus. Jetzt entscheidet der Typ-Code im vierten Feld
(6201 Video, 6202 Audio, 6203 Untertitel); das Wort bleibt Notnagel.
Test rip-parser-561 mit den gemessenen Zeilen (deu×2/jpn×2 Ton, deu×3
Untertitel, darunter "PGS German (nur erzwungene)"); die volle Messung
liegt unter beweise/messungen/2026-09-03-makemkvcon-info-kizuna.txt.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
8f671ff160
commit
687173430c
@@ -1,3 +1,15 @@
|
||||
Version 5.6.1
|
||||
|
||||
Untertitel-Spuren werden wieder erkannt.
|
||||
MakeMKV schreibt den Typ eines Streams in seiner Anzeigesprache - auf einem
|
||||
deutsch eingestellten MakeMKV "Untertitel" statt "Subtitles". Rippy prueft
|
||||
seit 5.4.0 auf das englische Wort und fand deshalb keine Untertitel mehr
|
||||
(Ton heisst in beiden Sprachen "Audio", darum fiel es dort nicht auf).
|
||||
Jetzt zaehlt der Typ-Code (6202 Ton, 6203 Untertitel), der ist
|
||||
sprachunabhaengig. Gemessen an der Blu-ray "Digimon Adventure: Last
|
||||
Evolution Kizuna": drei deutsche PGS-Spuren, darunter eine nur fuer
|
||||
erzwungene Untertitel.
|
||||
|
||||
Version 5.6.0
|
||||
|
||||
Mehrere Filme auf einer Disc.
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "rippy",
|
||||
"version": "5.6.0",
|
||||
"version": "5.6.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "rippy",
|
||||
"version": "5.6.0",
|
||||
"version": "5.6.1",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"electron-updater": "^6.8.9",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "rippy",
|
||||
"productName": "Rippy",
|
||||
"version": "5.6.0",
|
||||
"version": "5.6.1",
|
||||
"description": "Rippy v5 — Disc-Ripping als eigenständiges Windows-Programm (KONZEPT-WINDOWS.md)",
|
||||
"main": "out/haupt/index.js",
|
||||
"author": "KrBrZ",
|
||||
|
||||
@@ -114,9 +114,21 @@ export function parseTitelInfo(ausgabe: string): TitelInfo[] {
|
||||
// ⚠️ Die Sprache steht in 3/4 — NICHT in 28/29: Die tragen auf JEDEM
|
||||
// Stream „eng"/„English" (MakeMKVs Anzeigesprache). Wer 28 nimmt, hält
|
||||
// jede Disc für englisch.
|
||||
// ⚠️ 5.6.1 (Commander-Fund 03.09.2026, Digimon Last Evolution Kizuna): Auch
|
||||
// der TEXT von Attribut 1 ist MakeMKVs Anzeigesprache — deutsch eingestellt
|
||||
// schreibt es `SINFO:1,5,1,6203,"Untertitel"`, nicht „Subtitles". „Audio"
|
||||
// heißt zufällig in beiden Sprachen gleich, deshalb fehlten NUR die
|
||||
// Untertitel. Verlässlich ist der CODE im vierten Feld: 6201 Video,
|
||||
// 6202 Audio, 6203 Untertitel (gemessen an makemkvcon64 auf diesem PC).
|
||||
export const STREAM_CODE_VIDEO = 6201
|
||||
export const STREAM_CODE_AUDIO = 6202
|
||||
export const STREAM_CODE_UNTERTITEL = 6203
|
||||
|
||||
export interface StreamInfo {
|
||||
nr: number
|
||||
typ: string
|
||||
/** Typ-Code aus Attribut 1 (6201/6202/6203), 0 wenn keiner dastand. */
|
||||
typCode: number
|
||||
lang: string
|
||||
sprache: string
|
||||
codec: string
|
||||
@@ -129,7 +141,7 @@ export interface TitelStreams {
|
||||
untertitel: StreamInfo[]
|
||||
}
|
||||
|
||||
const SINFO_ZEILE = /^SINFO:(\d+),(\d+),(\d+),\d+,"(.*)"\s*$/
|
||||
const SINFO_ZEILE = /^SINFO:(\d+),(\d+),(\d+),(\d+),"(.*)"\s*$/
|
||||
|
||||
export function parseStreamInfo(ausgabe: string): Map<number, TitelStreams> {
|
||||
const titel = new Map<number, Map<number, StreamInfo>>()
|
||||
@@ -139,7 +151,8 @@ export function parseStreamInfo(ausgabe: string): Map<number, TitelStreams> {
|
||||
const tNr = Number(treffer[1])
|
||||
const sNr = Number(treffer[2])
|
||||
const attr = Number(treffer[3])
|
||||
const wert = treffer[4]
|
||||
const code = Number(treffer[4])
|
||||
const wert = treffer[5]
|
||||
let streams = titel.get(tNr)
|
||||
if (streams === undefined) {
|
||||
streams = new Map()
|
||||
@@ -147,10 +160,13 @@ export function parseStreamInfo(ausgabe: string): Map<number, TitelStreams> {
|
||||
}
|
||||
let eintrag = streams.get(sNr)
|
||||
if (eintrag === undefined) {
|
||||
eintrag = { nr: sNr, typ: '', lang: '', sprache: '', codec: '', kanaele: '', beschreibung: '' }
|
||||
eintrag = { nr: sNr, typ: '', typCode: 0, lang: '', sprache: '', codec: '', kanaele: '', beschreibung: '' }
|
||||
streams.set(sNr, eintrag)
|
||||
}
|
||||
if (attr === 1) eintrag.typ = wert
|
||||
if (attr === 1) {
|
||||
eintrag.typ = wert
|
||||
eintrag.typCode = code
|
||||
}
|
||||
else if (attr === 3) eintrag.lang = wert
|
||||
else if (attr === 4) eintrag.sprache = wert
|
||||
else if (attr === 6) eintrag.codec = wert
|
||||
@@ -164,9 +180,10 @@ export function parseStreamInfo(ausgabe: string): Map<number, TitelStreams> {
|
||||
const untertitel: StreamInfo[] = []
|
||||
for (const sNr of [...streams.keys()].sort((a, b) => a - b)) {
|
||||
const s = streams.get(sNr)!
|
||||
// MakeMKV schreibt „Subtitles" (englisch, Plural) — gemessen.
|
||||
if (s.typ === 'Audio') audio.push(s)
|
||||
else if (s.typ.startsWith('Subtitle')) untertitel.push(s)
|
||||
// Der Code entscheidet (5.6.1); das Wort nur als Notnagel für Ausgaben
|
||||
// ohne Code („Audio", „Subtitles", „Untertitel").
|
||||
if (s.typCode === STREAM_CODE_AUDIO || (s.typCode === 0 && s.typ === 'Audio')) audio.push(s)
|
||||
else if (s.typCode === STREAM_CODE_UNTERTITEL || (s.typCode === 0 && (s.typ.startsWith('Subtitle') || s.typ.startsWith('Untertitel')))) untertitel.push(s)
|
||||
}
|
||||
ergebnis.set(tNr, { audio, untertitel })
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// 5.6.1 — Commander-Fund vom 03.09.2026: Bei der Blu-ray „Digimon Adventure:
|
||||
// Last Evolution Kizuna" fehlten im Auswahl-Dialog die Untertitel-Chips,
|
||||
// obwohl die Disc drei deutsche PGS-Spuren hat. Gemessen mit
|
||||
// makemkvcon64 -r info auf diesem PC: MakeMKV (deutsch eingestellt) schreibt
|
||||
// den Stream-Typ als „Untertitel", der Parser prüfte auf „Subtitles". Der
|
||||
// Typ-Code im vierten Feld (6203) ist sprachunabhängig.
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { STREAM_CODE_AUDIO, STREAM_CODE_UNTERTITEL, parseStreamInfo, sprachenFuerTitel } from '../src/kern/rip/parser'
|
||||
|
||||
// Wörtlich aus der Messung (gekürzt auf Typ, Sprache, Name, Beschreibung).
|
||||
const KIZUNA = [
|
||||
'SINFO:1,0,1,6201,"Video"',
|
||||
'SINFO:1,0,6,0,"Mpeg4"',
|
||||
'SINFO:1,1,1,6202,"Audio"',
|
||||
'SINFO:1,1,3,0,"deu"',
|
||||
'SINFO:1,1,4,0,"German"',
|
||||
'SINFO:1,1,30,0,"DTS-HD MA Surround 5.1 German"',
|
||||
'SINFO:1,2,1,6202,"Audio"',
|
||||
'SINFO:1,2,3,0,"deu"',
|
||||
'SINFO:1,2,4,0,"German"',
|
||||
'SINFO:1,3,1,6202,"Audio"',
|
||||
'SINFO:1,3,3,0,"jpn"',
|
||||
'SINFO:1,3,4,0,"Japanese"',
|
||||
'SINFO:1,4,1,6202,"Audio"',
|
||||
'SINFO:1,4,3,0,"jpn"',
|
||||
'SINFO:1,4,4,0,"Japanese"',
|
||||
'SINFO:1,5,1,6203,"Untertitel"',
|
||||
'SINFO:1,5,3,0,"deu"',
|
||||
'SINFO:1,5,4,0,"German"',
|
||||
'SINFO:1,5,30,0,"PGS German"',
|
||||
'SINFO:1,6,1,6203,"Untertitel"',
|
||||
'SINFO:1,6,3,0,"deu"',
|
||||
'SINFO:1,6,4,0,"German"',
|
||||
'SINFO:1,6,22,0,"6144"',
|
||||
'SINFO:1,6,30,0,"PGS German (nur erzwungene)"',
|
||||
'SINFO:1,7,1,6203,"Untertitel"',
|
||||
'SINFO:1,7,3,0,"deu"',
|
||||
'SINFO:1,7,4,0,"German"',
|
||||
].join('\n')
|
||||
|
||||
describe('parseStreamInfo — Stream-Typ per Code, nicht per Wort (5.6.1)', () => {
|
||||
it('deutsches MakeMKV schreibt „Untertitel": die drei PGS-Spuren werden erkannt', () => {
|
||||
const streams = parseStreamInfo(KIZUNA).get(1)!
|
||||
expect(streams.audio.map((s) => s.lang)).toEqual(['deu', 'deu', 'jpn', 'jpn'])
|
||||
expect(streams.untertitel.map((s) => s.lang)).toEqual(['deu', 'deu', 'deu'])
|
||||
expect(streams.untertitel[0].typCode).toBe(STREAM_CODE_UNTERTITEL)
|
||||
expect(streams.audio[0].typCode).toBe(STREAM_CODE_AUDIO)
|
||||
expect(streams.untertitel[1].beschreibung).toBe('PGS German (nur erzwungene)')
|
||||
})
|
||||
it('für den Dialog: deu×2 Ton, jpn×2 Ton, deu×3 Untertitel', () => {
|
||||
const sprachen = sprachenFuerTitel(parseStreamInfo(KIZUNA).get(1))
|
||||
expect(sprachen.audio).toEqual([
|
||||
{ lang: 'deu', sprache: 'German', spuren: 2 },
|
||||
{ lang: 'jpn', sprache: 'Japanese', spuren: 2 },
|
||||
])
|
||||
expect(sprachen.untertitel).toEqual([{ lang: 'deu', sprache: 'German', spuren: 3 }])
|
||||
})
|
||||
it('jede Anzeigesprache: der Code zählt — französisch, englisch, und ohne Code das Wort als Notnagel', () => {
|
||||
expect(parseStreamInfo('SINFO:0,1,1,6203,"Sous-titres"\nSINFO:0,1,3,0,"fra"').get(0)!.untertitel).toHaveLength(1)
|
||||
expect(parseStreamInfo('SINFO:0,1,1,6203,"Subtitles"\nSINFO:0,1,3,0,"eng"').get(0)!.untertitel).toHaveLength(1)
|
||||
expect(parseStreamInfo('SINFO:0,1,1,0,"Subtitles"\nSINFO:0,1,3,0,"eng"').get(0)!.untertitel).toHaveLength(1)
|
||||
expect(parseStreamInfo('SINFO:0,1,1,0,"Untertitel"\nSINFO:0,1,3,0,"deu"').get(0)!.untertitel).toHaveLength(1)
|
||||
expect(parseStreamInfo('SINFO:0,1,1,0,"Audio"\nSINFO:0,1,3,0,"deu"').get(0)!.audio).toHaveLength(1)
|
||||
})
|
||||
it('Video bleibt draußen', () => {
|
||||
const streams = parseStreamInfo('SINFO:0,0,1,6201,"Video"\nSINFO:0,0,3,0,"und"').get(0)!
|
||||
expect(streams.audio).toHaveLength(0)
|
||||
expect(streams.untertitel).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user