Files
rippy/rippy-windows/test/scan.test.ts
HitonabiandClaude Fable 5.1 3f7f962dff feat(v5): Kern 5.4.0 — Vorgaenge, Kompressions-Warteschlange, Roh-Aufraeumen, Sprachen je Titel, Erkennung v2
WAS: Der Rip endet, sobald die Roh-Dateien liegen; die Kompression laeuft
danach in einer Warteschlange (eine zur Zeit), das Laufwerk ist frei fuer
die naechste Disc. Jeder Rip ist jetzt ein Datensatz (Tabelle vorgaenge,
Schema 4): Roh-Ordner, Zielordner, Phase, Auftrag als JSON. Darauf bauen:
Roh-Aufraeumen nach Regel (Vorgabe 7 Tage, nur bei gelungener Kompression
und nur wenn jede fertige Datei da und nicht leer ist), Wiederholen ab
Kompression, Aufraeumen halber Dateien nach Abbruch/Fehler, Wiederaufnahme
nach Neustart. Unkomprimierte Rips (4K, kein HandBrake) werden in den
Zielordner VERSCHOBEN statt unter roh\ liegen zu bleiben.
Sprachen je Titel reisen vom Info-Lauf (SINFO) bis in HandBrake; fremder
Ton schaltet den deutschen Untertitel vor (--subtitle-default=1). Vor der
Kompression prueft ein HandBrake-Scan die Roh-Datei. MakeMKVs
Auswahlregel wird gesetzt, wenn keine steht, damit alle Sprachen in die
Roh-Datei kommen. Staffel und erste Folge von Hand schlagen die
Laufzeit-Raterei. Durchgehender Fortschritt, nach Groesse gewichtet.
Erkennung v2: leere TMDb-Eintraege (Stubs) zaehlen nicht, Laufzeit wird
nach dem Info-Lauf gegen TMDb gehalten, Titel-Struktur als Fingerabdruck,
bdmt_deu als zweite Titel-Variante. TMDb liefert Logo, Tagline,
Bewertung, FSK und Besetzung in derselben Anfrage. Laufwerks-Gesundheit
aus dem Windows-Ereignisprotokoll (wevtutil): Disc oder Hardware.

WARUM: Uebergabe-Punkte 1-5, 8-12 des SAVEPOINT vom 01.09.2026 — vom
Commander gutgeheissen (7 Tage / Untertitel vorgewaehlt / entkoppelte
Kompression waren seine Wahl).

GEMESSEN (Regel D): HandBrake 1.11 Sprach-Schalter an einer ffmpeg-
Testdatei (jpn/deu/deu/eng + deu/eng), HandBrake --scan --json Format,
TMDb movie/149 + tv/46296 mit append_to_response, wevtutil /f:xml an
diesem PC (338x cdrom 7, 8x cdrom 11 in 30 Tagen), makemkvcon --minlength,
MakeMKV-Auswahlregel laut forum.makemkv.com t=4386.

348 Tests gruen (vorher 261), Typpruefung und Bau gruen. Oberflaeche
folgt im naechsten Schritt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-01 22:02:03 +02:00

63 lines
2.8 KiB
TypeScript

// Tests des HandBrake-Scans (kern/komprimieren/scan.ts, 5.4.0) — am
// gemessenen Format: „JSON Title Set:" + Objekt + weiterer Text.
import { describe, expect, it } from 'vitest'
import { buildScanArgs, fehlendeSprachen, spurenAusScan } from '../src/kern/komprimieren/scan'
import { regelAusQuery, RIPPY_REGEL } from '../src/kern/werkzeuge/spurauswahl'
const AUSGABE = `[21:27:54] hb_init: starting libhb thread
Scanning title 1 of 1, preview 1, 25.00 %
JSON Title Set: {
"MainFeature": 0,
"TitleList": [
{
"AudioList": [
{ "Description": "\u65e5\u672c\u8a9e (AAC LC, 2.0 ch)", "Language": "\u65e5\u672c\u8a9e", "LanguageCode": "jpn", "TrackNumber": 1 },
{ "Description": "Deutsch (AAC LC, 2.0 ch)", "Language": "Deutsch", "LanguageCode": "deu", "TrackNumber": 2 },
{ "Description": "English (AAC LC, 2.0 ch)", "Language": "English", "LanguageCode": "eng", "TrackNumber": 3 }
],
"Duration": { "Hours": 0, "Minutes": 52, "Seconds": 47, "Ticks": 542070 },
"Index": 1,
"Name": "quelle",
"SubtitleList": [
{ "Format": "text", "Language": "Deutsch (UTF-8)", "LanguageCode": "deu", "SourceName": "UTF-8", "TrackNumber": 1 },
{ "Format": "text", "Language": "English (UTF-8)", "LanguageCode": "eng", "SourceName": "UTF-8", "TrackNumber": 2 }
]
}
]
}
HandBrake has exited.
`
describe('spurenAusScan', () => {
it('schneidet das Objekt aus dem Textprotokoll und liest Spuren + Dauer', () => {
const s = spurenAusScan(AUSGABE)!
expect(s.audio.map((a) => `${a.nr}:${a.lang}`)).toEqual(['1:jpn', '2:deu', '3:eng'])
expect(s.untertitel.map((u) => u.lang)).toEqual(['deu', 'eng'])
expect(s.dauerS).toBe(52 * 60 + 47)
})
it('ohne Marke oder mit kaputtem JSON: null, nie ein leerer Befund', () => {
expect(spurenAusScan('nichts')).toBeNull()
expect(spurenAusScan('JSON Title Set: { "TitleList": [ ')).toBeNull()
expect(spurenAusScan('JSON Title Set: { "TitleList": [] }')).toBeNull()
})
it('buildScanArgs: --scan --json, Titel 1', () => {
expect(buildScanArgs('R:\\roh\\a.mkv')).toEqual(['--scan', '--json', '--input', 'R:\\roh\\a.mkv', '--title', '1'])
})
})
describe('fehlendeSprachen', () => {
it('nennt, was gewünscht ist und nicht drin', () => {
const s = spurenAusScan(AUSGABE)!
expect(fehlendeSprachen(s, { audio: ['jpn', 'fra'], untertitel: ['deu', 'jpn'] })).toEqual({ audio: ['fra'], untertitel: ['jpn'] })
expect(fehlendeSprachen(s, { audio: [], untertitel: [] })).toEqual({ audio: [], untertitel: [] })
})
})
describe('MakeMKV-Auswahlregel — reg query lesen', () => {
it('findet den Wert in der Ausgabe', () => {
const ausgabe = `\r\nHKEY_CURRENT_USER\\Software\\MakeMKV\r\n app_DefaultSelectionString REG_SZ ${RIPPY_REGEL}\r\n\r\n`
expect(regelAusQuery(ausgabe)).toBe(RIPPY_REGEL)
expect(regelAusQuery('FEHLER: Der angegebene Registrierungsschlüssel oder Wert wurde nicht gefunden.')).toBeNull()
})
})