883c1c290b
Der Modulkopf von caps.py verspricht "ehrlich erkannt, nicht behauptet" -
erkenne_encoder() tat aber drei Mal das Gegenteil:
1. cpu-x264 und cpu-x265 standen fest verdrahtet in der Liste ("immer
dabei"). Ein Rip-Worker OHNE HandBrake behauptete damit, komprimieren zu
koennen; jeder Transcode dort endete sofort mit "nicht installiert".
2. 'vaapi' wurde allein wegen /dev/dri gemeldet, ohne zu pruefen, ob
HandBrake das ueberhaupt kann. Auf der VM gemessen: das Worker-Image
kennt svt_av1/x264/x265/mpeg4/mpeg2/VP8/VP9/theora und KEINEN einzigen
Hardware-Encoder. Rippy haette VAAPI versprochen und dann versagt.
3. Ueber die Rechenleistung sagte es gar nichts. Genau deshalb war nicht zu
sehen, dass ein 4K-Encode auf dieser Maschine Tage braucht: CPU-Modell
ist das generische "QEMU Virtual CPU version 2.5+", grep -c avx2
/proc/cpuinfo = 0, nur bis sse4_2. x265 lebt von AVX2. Gemessen an der
Leseposition des Quellstroms: 28-55 h fuer einen Film, 3,84 von 4 Kernen
gesaettigt. Abhilfe waere der CPU-Typ 'host' in Proxmox.
Jetzt wird die Encoder-Liste aus `HandBrakeCLI --help` geparst (Abschnitt
-e/--encoder, Formatstrings im Worker-Image gemessen - AGENTS Regel D), und
Hardware zaehlt nur, wenn Geraet UND HandBrake-Unterstuetzung da sind. Neu
gemeldet: cpu-av1 (svt_av1 ist wirklich verfuegbar) sowie CPU-Modell,
Kernzahl und Vektorbefehlsstufe je Worker.
UI: Kerne/Vektorbefehle stehen bei jedem Worker (Worker-Tab und
Einstellungen -> System), dazu die ungefilterte HandBrake-Auskunft und eine
sichtbare Warnung, wenn AVX2 fehlt - inklusive des Hinweises auf den
VM-CPU-Typ. Der Warntext liegt in lib/encoder.ts, damit er nicht doppelt
im Code steht.
Mit im gleichen Zug (dieselbe Datei): der Schalter "Alle Tracks rippen" ist
entfallen. Er war ein Placebo - abcde bekommt keine Track-Auswahl und es gab
auch keine Oberflaeche, um eine Teilmenge zu waehlen. Eine Audio-CD wurde
also immer vollstaendig gerippt, egal wie der Schalter stand. An seiner
Stelle steht jetzt die Wahrheit.
7 Tests, Testdaten sind echte HandBrake-Ausgaben von der VM. Der Parser ist
zusaetzlich gegen die vollen 697 Zeilen der echten --help gegengeprueft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
116 lines
4.7 KiB
Python
116 lines
4.7 KiB
Python
"""Tests der Fähigkeiten-Erkennung — reine Funktionen, keine Infrastruktur.
|
|
|
|
Die Testdaten sind ECHTE Ausgaben, am 25.07.2026 im Worker-Image der Rippy-VM
|
|
abgenommen (AGENTS Regel D). Erfundene Formate hätten hier keinen Wert: genau
|
|
daran ist die Erkennung vorher gescheitert.
|
|
"""
|
|
|
|
import caps
|
|
|
|
# Wörtlich aus `docker exec rippy-worker-1 HandBrakeCLI --help` (HandBrake im
|
|
# Worker-Image, 25.07.2026). Bemerkenswert: KEIN Hardware-Encoder dabei.
|
|
HB_HILFE_ECHT = """
|
|
-Z, --preset <string> Select preset by name
|
|
-e, --encoder <string> Select video encoder:
|
|
svt_av1
|
|
svt_av1_10bit
|
|
x264
|
|
x264_10bit
|
|
x265
|
|
x265_10bit
|
|
x265_12bit
|
|
mpeg4
|
|
mpeg2
|
|
VP8
|
|
VP9
|
|
VP9_10bit
|
|
theora
|
|
--encoder-preset <string>
|
|
Adjust video encoding settings
|
|
"""
|
|
|
|
# Wie dieselbe Stelle auf einer Maschine MIT Hardware-Encodern aussieht
|
|
# (HandBrake-Windows-Build; Struktur identisch, nur mehr Namen).
|
|
HB_HILFE_MIT_HARDWARE = """
|
|
-e, --encoder <string> Select video encoder:
|
|
x264
|
|
x265
|
|
nvenc_h264
|
|
nvenc_h265
|
|
qsv_h264
|
|
qsv_h265
|
|
--encoder-preset <string>
|
|
"""
|
|
|
|
|
|
def test_encoder_liste_wird_aus_echter_hilfe_gelesen():
|
|
encoder = caps.parse_encoder_liste(HB_HILFE_ECHT)
|
|
assert encoder == [
|
|
"svt_av1", "svt_av1_10bit",
|
|
"x264", "x264_10bit",
|
|
"x265", "x265_10bit", "x265_12bit",
|
|
"mpeg4", "mpeg2", "VP8", "VP9", "VP9_10bit", "theora",
|
|
]
|
|
# Der Block endet an der nächsten Option — sie darf nicht mitgelesen werden
|
|
assert not any("encoder-preset" in e for e in encoder)
|
|
assert not any(e.startswith("-") for e in encoder)
|
|
|
|
|
|
def test_encoder_liste_ohne_handbrake_ist_leer():
|
|
assert caps.parse_encoder_liste("") == []
|
|
assert caps.parse_encoder_liste(None) == []
|
|
assert caps.parse_encoder_liste("irgendein Text ohne Encoder-Abschnitt") == []
|
|
|
|
|
|
def test_ohne_handbrake_keine_encoder():
|
|
"""Der wichtigste Fall: vorher standen cpu-x264/cpu-x265 fest verdrahtet in
|
|
der Liste. Ein Rip-Worker ohne HandBrake behauptete damit, komprimieren zu
|
|
können — und jeder Transcode dort endete sofort mit 'nicht installiert'."""
|
|
assert caps.leite_backends_ab([], dri_da=True, nvidia_da=True) == []
|
|
|
|
|
|
def test_backends_aus_echter_liste():
|
|
encoder = caps.parse_encoder_liste(HB_HILFE_ECHT)
|
|
# Kein /dev/dri, kein NVIDIA — und HandBrake kann hier ohnehin keine Hardware
|
|
assert caps.leite_backends_ab(encoder, dri_da=False, nvidia_da=False) == [
|
|
"cpu-x264", "cpu-x265", "cpu-av1",
|
|
]
|
|
|
|
|
|
def test_hardware_nur_wenn_geraet_UND_handbrake_es_kann():
|
|
"""Befund 25.07.2026: Vorher genügte /dev/dri, um 'vaapi' zu melden. Das
|
|
Worker-Image kann laut eigener Auskunft aber gar keinen Hardware-Encoder —
|
|
Rippy hätte VAAPI versprochen und wäre beim Encodieren gescheitert."""
|
|
ohne_hw = caps.parse_encoder_liste(HB_HILFE_ECHT)
|
|
assert "vaapi" not in caps.leite_backends_ab(ohne_hw, dri_da=True, nvidia_da=True)
|
|
assert "nvenc" not in caps.leite_backends_ab(ohne_hw, dri_da=True, nvidia_da=True)
|
|
|
|
mit_hw = caps.parse_encoder_liste(HB_HILFE_MIT_HARDWARE)
|
|
# Gerät fehlt → trotz Können kein Hardware-Backend
|
|
assert caps.leite_backends_ab(mit_hw, dri_da=False, nvidia_da=False) == [
|
|
"cpu-x264", "cpu-x265",
|
|
]
|
|
# Beides da → beides gemeldet
|
|
beides = caps.leite_backends_ab(mit_hw, dri_da=True, nvidia_da=True)
|
|
assert "vaapi" in beides # qsv_* vorhanden
|
|
assert "nvenc" in beides
|
|
|
|
|
|
def test_simd_stufe_erkennt_die_hoechste():
|
|
assert caps.beste_simd("fpu vme de sse4_2 avx avx2") == "avx2"
|
|
assert caps.beste_simd("sse4_2 avx avx2 avx512f") == "avx512f"
|
|
assert caps.beste_simd("fpu vme de pse tsc sse4_2") == "sse4_2"
|
|
assert caps.beste_simd("") == "unbekannt"
|
|
assert caps.beste_simd(None) == "unbekannt"
|
|
|
|
|
|
def test_simd_stufe_der_rippy_vm_ist_sse4_2():
|
|
"""Echt gemessen auf der Rippy-VM (25.07.2026): generisches QEMU-CPU-Modell,
|
|
`grep -c avx2 /proc/cpuinfo` = 0. Genau das macht Software-4K dort so lahm."""
|
|
flags_vm = (
|
|
"fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 "
|
|
"clflush mmx fxsr sse sse2 syscall nx lm rep_good nopl cpuid "
|
|
"pni cx16 sse4_1 sse4_2 x2apic popcnt aes hypervisor lahf_lm"
|
|
)
|
|
assert caps.beste_simd(flags_vm) == "sse4_2"
|