fix(v5): Windows-Pfadregeln ausdruecklich — path.win32 statt join
Ampel / ampel (push) Successful in 1m21s

Die Ampel (Linux) brach an den Katalog-Tests: das plattformabhaengige
path.join mischte dort Schraegstriche in Windows-Pfade. Rippy v5 baut
NUR Windows-Pfade — katalog.ts, handbrake.ts und ablauf/rippen.ts
rechnen jetzt ausdruecklich mit path.win32 und damit auf jeder
Plattform gleich. Im node:24-Container nachgestellt: vorher 2 failed,
mit dem Fix lokal 96 gruen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-08-30 18:16:17 +02:00
co-authored by Claude Fable 5
parent 844bca37ff
commit ca338ad467
4 changed files with 349 additions and 2 deletions
@@ -0,0 +1,69 @@
// Preset-Wahl je Disc-Typ (KONZEPT § 6.10) — Regeln aus ripping.py, dort
// mit den Befunden vom 25.07.2026 begründet: EIN Preset für alles rechnete
// 4K auf 1080p herunter und DVDs hinauf.
export const DEFAULT_HB_PRESET = 'H.265 MKV 1080p30'
/** Einstellungs-Schlüssel je Disc-Typ. */
export const PRESET_SCHLUESSEL: Record<string, string> = {
dvd: 'transcodePresetDvd',
bluray: 'transcodePresetBluray',
uhd: 'transcodePresetUhd',
}
// Reservierter Wert: „diesen Typ NICHT komprimieren". Kein echtes
// HandBrake-Preset heißt so (gegen alle 90 aus --preset-list geprüft).
// Grund: 4K verlustfrei durchreichen, DVDs trotzdem schrumpfen.
export const PRESET_KEINE = 'keine'
export type Einstellungen = Record<string, string | boolean | undefined>
/** Soll dieser Disc-Typ nach dem Rip komprimiert werden? (pur) */
export function komprimierenFuer(discTyp: string, einstellungen: Einstellungen): boolean {
if (einstellungen['transcodeEnabled'] === false || einstellungen['transcodeEnabled'] === 'false') {
return false
}
const schluessel = PRESET_SCHLUESSEL[discTyp] ?? ''
if (schluessel.length > 0) {
const wert = String(einstellungen[schluessel] ?? '').trim()
if (wert === PRESET_KEINE) return false
}
return true
}
/** Welches HandBrake-Preset gilt für diesen Disc-Typ? (pur)
* Kette: Typ-Preset → allgemeines transcodePreset → DEFAULT. PRESET_KEINE
* wird ÜBERSPRUNGEN — diese Funktion darf nie „keine" als Preset-Namen
* liefern, sonst bekäme HandBrake `--preset keine` und scheiterte. */
export function presetFuer(discTyp: string, einstellungen: Einstellungen): string {
const schluessel = PRESET_SCHLUESSEL[discTyp] ?? ''
if (schluessel.length > 0) {
const eigen = String(einstellungen[schluessel] ?? '').trim()
if (eigen.length > 0 && eigen !== PRESET_KEINE) return eigen
}
const allgemein = String(einstellungen['transcodePreset'] ?? '').trim()
return allgemein.length > 0 ? allgemein : DEFAULT_HB_PRESET
}
/** „deu, eng , ,DEU" → ["deu","eng"] — HandBrake will ISO-639-2 klein;
* ein „DEU" aus einem Eingabefeld soll die Auswahl nicht still lahmlegen. */
export function sprachliste(wert: string | readonly string[] | null | undefined): string[] {
if (wert === null || wert === undefined) return []
const teile = typeof wert === 'string' ? wert.split(',') : [...wert]
const sauber: string[] = []
for (const teil of teile) {
const code = String(teil).trim().toLowerCase()
if (code.length > 0 && !sauber.includes(code)) sauber.push(code)
}
return sauber
}
/** Endung → HandBrake-Container. Am mitgelieferten HandBrake 1.11.2
* gegengeprüft (`--help`, Abschnitt `-f, --format`). */
export const FORMATE: Record<string, string> = {
'.mkv': 'av_mkv',
'.mp4': 'av_mp4',
'.m4v': 'av_mp4',
'.mov': 'av_mov',
'.webm': 'av_webm',
}