feat(v5): jede Spur einzeln anhaken — Codec und Kanäle je Tonspur, Untertitel genauso
WAS: Der Auswahl-Dialog zeigt je Titel jede Ton- und Untertitelspur, die der Info-Lauf gemessen hat („German · DTS-HD MA · Surround 5.1", „German · DD · Stereo (Kommentar)", „German · PGS (nur erzwungene)"), vorbelegt wie bisher (je Wunschsprache die erste Tonspur, alle Untertitel der Wunsch- sprachen) — angehakt wird einzeln. Die Untertitel-Vorwahl je Extra ist jetzt eine Spur. Der Parser liest dazu SINFO-Attribute 2 (Anordnung), 22 (Flags) und markiert abgeleitete Spuren (Bit 0x800, an der Kizuna- Disc gemessen): DTS-Kerne werden nicht angeboten, „nur erzwungene"- Untertitel schon. Die Ablage scannt die Roh-Datei und findet die gewählten MakeMKV-Spuren gestuft wieder (Sprache + Codec-Familie + Kanäle → … → Sprache), HandBrake bekommt `--audio 1,3 --subtitle 2,1 --subtitle-default=1`; Fehlendes wird gemeldet, scheitert der Scan, gelten die Sprachen der gewählten Spuren als Liste. MakeMKVs Auswahl- regel lässt Stereo-Doppel jetzt stehen (nur -sel:havecore); Rippys alte Regel wird in der Registry ersetzt, eine fremde bleibt. Dazu F31 (Durchsicht): `--aencoder copy` ohne `--audio-copy-mask` verengt HandBrakeCLI 1.11.2 auf „copy:aac" — AC3/DTS/TrueHD wurden seit 5.0 in AAC umgerechnet. Beide Wege setzen die Maske jetzt ausdrücklich (gemessen 12.09.2026: AC3 bleibt AC3, Passthru-Zeile nennt alle Codecs). WARUM: Commander-Entscheid 12.09.2026 („Jede Spur einzeln anhaken") — bisher ließ sich je Sprache nur „alles oder nichts" wählen, und der Kommentar-Ton fehlte in der Roh-Datei (havemulti). Gemessen am mitgelieferten HandBrakeCLI mit ffmpeg-gebauter Quelle (test/messung.spuren.test.ts, RIPPY_MESSUNG=1): --audio 1,3 → jpn und deu-Kommentar, --subtitle 2,1 --subtitle-default=1 → eng (default) vor deu, --subtitle none → keine Spur. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fc2d16ca38
commit
e7e33e9021
@@ -199,7 +199,7 @@ describe('komprimierenUndAblegen', () => {
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien }),
|
||||
umgebung(ablage, {
|
||||
spurenScannen: async () => ({ audio: [{ nr: 1, lang: 'deu', beschreibung: 'Deutsch' }], untertitel: [], dauerS: 3167 }),
|
||||
spurenScannen: async () => ({ audio: [{ nr: 1, lang: 'deu', beschreibung: 'Deutsch', codec: 'dtshd', kanaele: 6 }], untertitel: [], dauerS: 3167 }),
|
||||
}),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
@@ -395,3 +395,91 @@ describe('komprimierenUndAblegen — Durchsicht 5.7.0', () => {
|
||||
expect(ergebnis.dateien.map((d) => d.split(/[\\/]/).pop())).toEqual(['title_t00 (2).mkv'])
|
||||
})
|
||||
})
|
||||
|
||||
// ── 5.7.0: Spuren einzeln ──────────────────────────────────────────────────
|
||||
describe('Spuren einzeln (5.7.0)', () => {
|
||||
const jpnHd = { nr: 1, lang: 'jpn', sprache: 'Japanese', codec: 'DTS-HD MA', kanaele: '6', layout: 'Surround 5.1', beschreibung: '', abgeleitet: false }
|
||||
const deuKommentar = { nr: 4, lang: 'deu', sprache: 'German', codec: 'DD', kanaele: '2', layout: 'Stereo', beschreibung: 'DD Stereo German (Kommentar)', abgeleitet: false }
|
||||
const deuPgs = { nr: 5, lang: 'deu', sprache: 'German', codec: 'PGS', kanaele: '', layout: '', beschreibung: 'PGS German', abgeleitet: false }
|
||||
const engPgs = { nr: 7, lang: 'eng', sprache: 'English', codec: 'PGS', kanaele: '', layout: '', beschreibung: 'PGS English', abgeleitet: false }
|
||||
const scan = {
|
||||
audio: [
|
||||
{ nr: 1, lang: 'jpn', beschreibung: '', codec: 'dtshd', kanaele: 6 },
|
||||
{ nr: 2, lang: 'deu', beschreibung: '', codec: 'ac3', kanaele: 6 },
|
||||
{ nr: 3, lang: 'deu', beschreibung: '', codec: 'ac3', kanaele: 2 },
|
||||
],
|
||||
untertitel: [
|
||||
{ nr: 1, lang: 'deu', beschreibung: '', codec: 'PGS', kanaele: 0 },
|
||||
{ nr: 2, lang: 'eng', beschreibung: '', codec: 'PGS', kanaele: 0 },
|
||||
],
|
||||
dauerS: 3167,
|
||||
}
|
||||
|
||||
it('gewählte Spuren erreichen HandBrake als Nummern — japanischer Ton stellt die deutschen Untertitel vor und wählt sie vor', async () => {
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv'])
|
||||
dateien[0].audioSprachen = ['jpn', 'deu']
|
||||
dateien[0].untertitelSprachen = ['eng', 'deu']
|
||||
dateien[0].audioSpuren = [jpnHd, deuKommentar]
|
||||
dateien[0].untertitelSpuren = [engPgs, deuPgs]
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien }),
|
||||
umgebung(ablage, { spurenScannen: async () => scan }),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(ergebnis.status).toBe('fertig')
|
||||
expect(hb.aufrufe[0].audioNr).toEqual([1, 3])
|
||||
expect(hb.aufrufe[0].untertitelNr).toEqual([1, 2])
|
||||
expect(hb.aufrufe[0].untertitelStandardNr).toBe(1)
|
||||
expect(ergebnis.hinweise.join(' ')).not.toContain('NICHT in der Roh-Datei')
|
||||
})
|
||||
|
||||
it('eine gewählte Spur fehlt in der Roh-Datei → Hinweis, der Rest läuft', async () => {
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv'])
|
||||
const fra = { ...jpnHd, nr: 9, lang: 'fra', sprache: 'French' }
|
||||
dateien[0].audioSpuren = [fra, deuKommentar]
|
||||
dateien[0].untertitelSpuren = []
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien }),
|
||||
umgebung(ablage, { spurenScannen: async () => scan }),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(hb.aufrufe[0].audioNr).toEqual([3])
|
||||
expect(hb.aufrufe[0].untertitelNr).toEqual([])
|
||||
expect(ergebnis.hinweise.join(' ')).toContain('Tonspur French DTS-HD MA ist NICHT in der Roh-Datei')
|
||||
})
|
||||
|
||||
it('Scan der Roh-Datei scheitert → Sprachen der gewählten Spuren als Liste (wie bisher)', async () => {
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv'])
|
||||
dateien[0].audioSpuren = [jpnHd]
|
||||
dateien[0].untertitelSpuren = [deuPgs]
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien }),
|
||||
umgebung(ablage, { spurenScannen: async () => null }),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(hb.aufrufe[0].audioNr).toBeUndefined()
|
||||
expect(hb.aufrufe[0].audioSprachen).toEqual(['jpn'])
|
||||
expect(hb.aufrufe[0].untertitelSprachen).toEqual(['deu'])
|
||||
expect(hb.aufrufe[0].untertitelStandard).toBe(true)
|
||||
expect(ergebnis.hinweise.join(' ')).toContain('ließen sich nicht messen')
|
||||
})
|
||||
|
||||
it('keine gewählte Tonspur findbar → Sprachlisten statt stummer Datei', async () => {
|
||||
const { ablage, roh, dateien } = aufbau(['title_t00.mkv'])
|
||||
const fra = { ...jpnHd, nr: 9, lang: 'fra', sprache: 'French' }
|
||||
dateien[0].audioSpuren = [fra]
|
||||
dateien[0].untertitelSpuren = [deuPgs]
|
||||
const ergebnis = await komprimierenUndAblegen(
|
||||
auftrag({ rohOrdner: roh, dateien }),
|
||||
umgebung(ablage, { spurenScannen: async () => scan }),
|
||||
() => {},
|
||||
KEIN_ABBRUCH,
|
||||
)
|
||||
expect(hb.aufrufe[0].audioNr).toBeUndefined()
|
||||
expect(hb.aufrufe[0].audioSprachen).toEqual(['fra'])
|
||||
expect(ergebnis.hinweise.join(' ')).toContain('keine der gewählten Tonspuren gefunden')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user