feat(v5): 4K-UHD nach der Leistung — Grafikkarte mit 4K-Preset komprimiert, nur CPU bleibt verlustfrei
WAS: presetEmpfehlung liefert für UHD das 4K-Preset der gemessenen Grafikkarten-Familie (VCN/NVENC/QSV) — sonst PRESET_KEINE (verlustfrei); komprimierenFuer folgt der Empfehlung, wenn der Typ auf „automatisch" steht. Eigene Wahl schlägt beides. Fenster: Kachel, Kompressions-Karte und Erst-Einrichtung sagen „(8 Bit)" bzw. „verlustfrei — nur CPU-Encoder". Gemessen am 12.09.2026 (HandBrake 1.11.2, RX 9070 XT, Akira-UHD-Abbild): die 4K-Hardware-Presets sind 8-Bit (vce_h265, Profil main); der 10-Bit- HEVC-Encoder vce_h265_10bit stürzt beim Start ab (Segfault, mit Profil auto und main10); AV1 10-Bit („AV1 VCN 2160p 4K", vce_av1_10bit) läuft — steht als eigene Wahl in der Liste, mit dem Hinweis auf AV1-fähige Abspielgeräte. WARUM: Durchsicht 12.09.2026, A4 — Commander-Entscheid: „Rippy analysiert doch die Performance des PCs, könnten wir das nicht davon abhängig machen?" Vorher rechnete der CPU-Default 4K auf 1080p klein, tagelang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6b6e5c3436
commit
0fc87aa022
@@ -7,7 +7,7 @@
|
||||
// Werkzeuge mit Durchsuchen, Kompression mit Sprach-Auswahl, TMDb,
|
||||
// Benachrichtigung, Automatik und Roh-Regel. Dazu der Poster-Hintergrund.
|
||||
import { useEffect, useState } from 'react'
|
||||
import { DEFAULT_HB_PRESET, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import { DEFAULT_HB_PRESET, empfehlungText, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import { Badge, FELD_KLASSE, Feld, KNOPF_GOLD, KNOPF_LEISE, PfadFeld, Schalter, gbKurz } from '../bausteine'
|
||||
import { SprachAuswahl } from '../einstellungen/SprachAuswahl'
|
||||
import { benachrichtigungTesten, einstellungSetzen, posterLaden, speicherLaden, type Verbindung } from '../kernverbindung'
|
||||
@@ -167,7 +167,7 @@ export function ErstEinrichtung({ verbindung }: { verbindung: Verbindung }) {
|
||||
{EMPFEHLUNGEN.map(([name, typ]) => (
|
||||
<div key={typ} className="rounded-lg border border-tinte/8 bg-buehne/60 p-2">
|
||||
<p className="font-mono text-[10px] tracking-wider text-nebel">{name}</p>
|
||||
<p className="mt-0.5 font-mono text-xs text-gold-hell">{presetEmpfehlung(typ, backends, presets) || DEFAULT_HB_PRESET}</p>
|
||||
<p className="mt-0.5 font-mono text-xs text-gold-hell">{empfehlungText(typ, presetEmpfehlung(typ, backends, presets) || DEFAULT_HB_PRESET)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// einstellungSetzen in die EINE Quelle (§ 6.7).
|
||||
import { useState } from 'react'
|
||||
import type { GeraeteInfo, HauptStatus, VorgangEintrag } from '../../gemeinsam/nachrichten'
|
||||
import { presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import { empfehlungText, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import {
|
||||
Badge,
|
||||
FELD_KLASSE,
|
||||
@@ -127,7 +127,7 @@ export function KompressionKarte({ verbindung }: { verbindung: Verbindung }) {
|
||||
const werte = verbindung.einstellungen
|
||||
const presets = verbindung.werkzeuge?.presets ?? []
|
||||
const backends = verbindung.werkzeuge?.backends ?? []
|
||||
const empfehlungFuer = (typ: string): string => presetEmpfehlung(typ, backends, presets)
|
||||
const empfehlungFuer = (typ: string): string => empfehlungText(typ, presetEmpfehlung(typ, backends, presets))
|
||||
return (
|
||||
<SektionsKarte
|
||||
id="kompression"
|
||||
@@ -153,7 +153,8 @@ export function KompressionKarte({ verbindung }: { verbindung: Verbindung }) {
|
||||
</div>
|
||||
<p className="text-[11px] leading-4 text-nebel">
|
||||
„automatisch" nimmt die Empfehlung aus der gemessenen Liste deines HandBrake — auf dieser Maschine die Grafikkarte, wo es sie gibt. Eine eigene Wahl
|
||||
schlägt die Empfehlung immer.
|
||||
schlägt die Empfehlung immer. 4K-UHD wird nur mit Grafikkarten-Encoder komprimiert (8 Bit); ohne bleibt es verlustfrei. Wer HDR in 10 Bit will, wählt
|
||||
„AV1 VCN 2160p 4K" — die Abspielgeräte müssen dann AV1 können.
|
||||
</p>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<SprachAuswahl
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
RipStatus,
|
||||
VorgangEintrag,
|
||||
} from '../../gemeinsam/nachrichten'
|
||||
import { DEFAULT_HB_PRESET, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import { DEFAULT_HB_PRESET, PRESET_KEINE, empfehlungText, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import {
|
||||
Badge,
|
||||
IconDisc,
|
||||
@@ -58,9 +58,11 @@ export function presetAnzeige(typ: GeraeteInfo['typ'], verbindung: Verbindung):
|
||||
if (werte['transcodeEnabled'] === 'false') return 'ohne Kompression'
|
||||
const schluessel = typ === 'dvd' ? 'transcodePresetDvd' : typ === 'uhd' ? 'transcodePresetUhd' : 'transcodePresetBluray'
|
||||
const eigene = werte[schluessel] ?? ''
|
||||
if (eigene === PRESET_KEINE) return 'ohne Kompression'
|
||||
if (eigene.length > 0) return eigene
|
||||
const empfehlung = presetEmpfehlung(typ, verbindung.werkzeuge?.backends ?? [], verbindung.werkzeuge?.presets ?? [])
|
||||
const gewaehlt = eigene.length > 0 ? eigene : empfehlung.length > 0 ? empfehlung : DEFAULT_HB_PRESET
|
||||
return gewaehlt === 'keine' ? 'ohne Kompression' : gewaehlt
|
||||
if (empfehlung === PRESET_KEINE) return typ === 'uhd' ? 'verlustfrei (nur CPU-Encoder)' : 'ohne Kompression'
|
||||
return empfehlungText(typ, empfehlung.length > 0 ? empfehlung : DEFAULT_HB_PRESET)
|
||||
}
|
||||
|
||||
export function LaufwerkKachel({
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|
||||
export const DEFAULT_HB_PRESET = 'H.265 MKV 1080p30'
|
||||
|
||||
// Reservierter Wert: „diesen Typ NICHT komprimieren". Kein echtes
|
||||
// HandBrake-Preset heißt so (gegen alle 107 aus --preset-list geprüft).
|
||||
// Lebt seit 5.7.0 hier, weil die Empfehlung ihn liefern kann.
|
||||
export const PRESET_KEINE = 'keine'
|
||||
|
||||
const FAMILIEN: ReadonlyArray<readonly [backend: string, presetKennung: string]> = [
|
||||
['vce', 'VCN'],
|
||||
['nvenc', 'NVENC'],
|
||||
@@ -25,7 +30,19 @@ const FAMILIEN: ReadonlyArray<readonly [backend: string, presetKennung: string]>
|
||||
]
|
||||
|
||||
/** Das empfohlene Preset für diesen Disc-Typ — aus den GEMESSENEN
|
||||
* Backends und Preset-Namen. Fällt auf den CPU-Default zurück. */
|
||||
* Backends und Preset-Namen. DVD und Blu-ray fallen auf den CPU-Default
|
||||
* zurück.
|
||||
*
|
||||
* 4K-UHD seit 5.7.0 nach der Leistung (Commander-Entscheid 12.09.2026):
|
||||
* Gibt es einen Grafikkarten-Encoder UND dessen 4K-Preset, wird damit
|
||||
* komprimiert; gibt es nur CPU-Encoder, bleibt UHD verlustfrei
|
||||
* (PRESET_KEINE) — ein 4K-Encode auf der CPU dauert Tage, und der alte
|
||||
* CPU-Default „1080p30" rechnete 4K klein. Gemessen am 12.09.2026: Die
|
||||
* 4K-Hardware-Presets („H.265 VCN 2160p 4K" usw.) sind 8-Bit; der
|
||||
* 10-Bit-HEVC-Encoder der AMD-Karte (vce_h265_10bit) stürzt in HandBrake
|
||||
* 1.11.2 beim Start ab, 10-Bit-AV1 („AV1 VCN 2160p 4K") läuft — wer HDR
|
||||
* in 10 Bit will, wählt das AV1-Preset selbst (Abspielgeräte müssen AV1
|
||||
* können). */
|
||||
export function presetEmpfehlung(
|
||||
discTyp: string,
|
||||
backends: readonly string[],
|
||||
@@ -36,9 +53,19 @@ export function presetEmpfehlung(
|
||||
if (!backends.includes(backend)) continue
|
||||
const treffer = presets.find((p) => p.startsWith('H.265 ') && p.includes(kennung) && p.includes(gewuenscht))
|
||||
if (treffer !== undefined) return treffer
|
||||
// 4K-Familie ohne 4K-Preset: das 1080p-Pendant ist besser als CPU.
|
||||
// Eine 4K-Disc ohne 4K-Preset der Familie: nicht klein rechnen —
|
||||
// verlustfrei lassen (unten). Bei DVD/Blu-ray ist das 1080p-Pendant
|
||||
// besser als CPU.
|
||||
if (discTyp === 'uhd') continue
|
||||
const kleiner = presets.find((p) => p.startsWith('H.265 ') && p.includes(kennung))
|
||||
if (kleiner !== undefined) return kleiner
|
||||
}
|
||||
return DEFAULT_HB_PRESET
|
||||
return discTyp === 'uhd' ? PRESET_KEINE : DEFAULT_HB_PRESET
|
||||
}
|
||||
|
||||
/** Klartext zur Empfehlung fürs Fenster (5.7.0). */
|
||||
export function empfehlungText(discTyp: string, empfehlung: string): string {
|
||||
if (empfehlung === PRESET_KEINE) return discTyp === 'uhd' ? 'verlustfrei lassen — nur CPU-Encoder gemessen' : 'verlustfrei lassen'
|
||||
if (discTyp === 'uhd' && /2160p/.test(empfehlung)) return `${empfehlung} (8 Bit)`
|
||||
return empfehlung
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ export async function komprimierenUndAblegen(
|
||||
): Promise<AblageErgebnis> {
|
||||
const einstellungen = umgebung.einstellungen()
|
||||
const handbrake = umgebung.handbrake()
|
||||
const soll = komprimierenFuer(auftrag.discTyp, einstellungen)
|
||||
const soll = komprimierenFuer(auftrag.discTyp, einstellungen, umgebung.presetEmpfehlung?.(auftrag.discTyp) ?? '')
|
||||
const komprimiert = soll && handbrake.length > 0
|
||||
const preset =
|
||||
auftrag.preset.length > 0
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// mit den Befunden vom 25.07.2026 begründet: EIN Preset für alles rechnete
|
||||
// 4K auf 1080p herunter und DVDs hinauf.
|
||||
|
||||
import { DEFAULT_HB_PRESET, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
import { DEFAULT_HB_PRESET, PRESET_KEINE, presetEmpfehlung } from '../../gemeinsam/preset-empfehlung'
|
||||
|
||||
export { DEFAULT_HB_PRESET, presetEmpfehlung }
|
||||
export { DEFAULT_HB_PRESET, PRESET_KEINE, presetEmpfehlung }
|
||||
|
||||
/** Einstellungs-Schlüssel je Disc-Typ. */
|
||||
export const PRESET_SCHLUESSEL: Record<string, string> = {
|
||||
@@ -13,15 +13,12 @@ export const PRESET_SCHLUESSEL: Record<string, string> = {
|
||||
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 {
|
||||
/** Soll dieser Disc-Typ nach dem Rip komprimiert werden? (pur)
|
||||
* 5.7.0: Steht der Typ auf „automatisch" und die gemessene Empfehlung
|
||||
* sagt „keine" (4K ohne Grafikkarten-Encoder), bleibt es verlustfrei. */
|
||||
export function komprimierenFuer(discTyp: string, einstellungen: Einstellungen, empfehlung = ''): boolean {
|
||||
if (einstellungen['transcodeEnabled'] === false || einstellungen['transcodeEnabled'] === 'false') {
|
||||
return false
|
||||
}
|
||||
@@ -29,6 +26,7 @@ export function komprimierenFuer(discTyp: string, einstellungen: Einstellungen):
|
||||
if (schluessel.length > 0) {
|
||||
const wert = String(einstellungen[schluessel] ?? '').trim()
|
||||
if (wert === PRESET_KEINE) return false
|
||||
if (wert.length === 0 && empfehlung === PRESET_KEINE) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 5.7.0 — 4K nach der Leistung (Commander-Entscheid 12.09.2026): Grafik-
|
||||
// karten-Encoder plus 4K-Preset → komprimieren; nur CPU → verlustfrei.
|
||||
// Preset-Namen und Encoder am mitgelieferten HandBrake 1.11.2 gemessen
|
||||
// (--preset-list, --help; vce_h265_10bit stürzt ab, AV1 10-Bit läuft).
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { DEFAULT_HB_PRESET, PRESET_KEINE, empfehlungText, presetEmpfehlung } from '../src/gemeinsam/preset-empfehlung'
|
||||
import { komprimierenFuer, presetFuer } from '../src/kern/komprimieren/presets'
|
||||
|
||||
const PRESETS = ['H.265 MKV 1080p30', 'H.265 MKV 2160p60 4K', 'AV1 VCN 2160p 4K', 'H.265 VCN 2160p 4K', 'H.265 VCN 1080p', 'H.265 NVENC 1080p']
|
||||
const NUR_CPU = ['cpu-x264', 'cpu-x265', 'cpu-av1']
|
||||
const AMD = [...NUR_CPU, 'vce', 'vce-av1']
|
||||
const NVIDIA_OHNE_4K = [...NUR_CPU, 'nvenc']
|
||||
|
||||
describe('presetEmpfehlung für 4K-UHD', () => {
|
||||
it('Grafikkarte mit 4K-Preset → das 4K-Preset (8 Bit im Klartext)', () => {
|
||||
expect(presetEmpfehlung('uhd', AMD, PRESETS)).toBe('H.265 VCN 2160p 4K')
|
||||
expect(empfehlungText('uhd', 'H.265 VCN 2160p 4K')).toBe('H.265 VCN 2160p 4K (8 Bit)')
|
||||
})
|
||||
it('nur CPU → verlustfrei lassen, nie das 1080p-CPU-Preset', () => {
|
||||
expect(presetEmpfehlung('uhd', NUR_CPU, PRESETS)).toBe(PRESET_KEINE)
|
||||
expect(empfehlungText('uhd', PRESET_KEINE)).toContain('verlustfrei')
|
||||
})
|
||||
it('Grafikkarte ohne 4K-Preset → verlustfrei, nicht klein rechnen', () => {
|
||||
expect(presetEmpfehlung('uhd', NVIDIA_OHNE_4K, PRESETS)).toBe(PRESET_KEINE)
|
||||
})
|
||||
it('DVD und Blu-ray wie bisher: Grafikkarte, sonst CPU-Default', () => {
|
||||
expect(presetEmpfehlung('bluray', AMD, PRESETS)).toBe('H.265 VCN 1080p')
|
||||
expect(presetEmpfehlung('dvd', NUR_CPU, PRESETS)).toBe(DEFAULT_HB_PRESET)
|
||||
expect(presetEmpfehlung('bluray', NVIDIA_OHNE_4K, PRESETS)).toBe('H.265 NVENC 1080p')
|
||||
})
|
||||
})
|
||||
|
||||
describe('komprimierenFuer mit Empfehlung', () => {
|
||||
it('automatisch + Empfehlung „keine" → nicht komprimieren', () => {
|
||||
expect(komprimierenFuer('uhd', {}, PRESET_KEINE)).toBe(false)
|
||||
expect(komprimierenFuer('uhd', { transcodePresetUhd: '' }, PRESET_KEINE)).toBe(false)
|
||||
})
|
||||
it('eigene Wahl schlägt die Empfehlung — in beide Richtungen', () => {
|
||||
expect(komprimierenFuer('uhd', { transcodePresetUhd: 'AV1 VCN 2160p 4K' }, PRESET_KEINE)).toBe(true)
|
||||
expect(komprimierenFuer('uhd', { transcodePresetUhd: PRESET_KEINE }, 'H.265 VCN 2160p 4K')).toBe(false)
|
||||
expect(presetFuer('uhd', { transcodePresetUhd: 'AV1 VCN 2160p 4K' }, PRESET_KEINE)).toBe('AV1 VCN 2160p 4K')
|
||||
})
|
||||
it('Blu-ray bleibt unberührt', () => {
|
||||
expect(komprimierenFuer('bluray', {}, 'H.265 VCN 1080p')).toBe(true)
|
||||
expect(komprimierenFuer('bluray', {}, '')).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user