fe12401e34
Aus dem gescheiterten Test-Rip des Commanders (Job 95afdc89) und seiner
UI-Durchsicht. Der Reihe nach.
## 1. Der externe Encoder wurde SEHR WOHL gesehen (Diagnose-Korrektur)
Der Commander schloss aus der Meldung, das System sehe seinen PC nicht. Live
gemessen sagt das Gegenteil:
meta.transcode_node = tobisnicerpc@TobisNicerPC
VM-Worker-Log = nur rip_disc, KEIN transcode_files
22:19:41.271 Kompression eingereiht
22:19:41.453 "Keine Roh-MKVs gefunden" <- 182 ms spaeter
Das Routing hat funktioniert. Sein PC nahm die Aufgabe an und lehnte sie sofort
ab, weil er /app/media/rippy/<job> nicht finden kann - ein Pfad, der nur INNEN
im Container existiert. Der Rip war vollstaendig (79,6 GB auf der NAS).
## 2. Der Hardware-Encoder-Bug war meiner
leite_backends_ab() verlangte zusaetzlich ein Geraet: /dev/dri fuer
VAAPI/QSV/VCE bzw. nvidia-smi fuer NVENC. Unter WINDOWS gibt es beides nicht -
der PC des Commanders (RX 9070 XT) meldete deshalb nur CPU-Encoder, obwohl
HandBrakes Windows-Build vce_*/nvenc_*/qsv_* beherrscht. Der Bug traf genau den
Anwendungsfall, fuer den externe Worker gedacht sind.
Die Pruefung war ausserdem ueberfluessig: HandBrake probiert Hardware beim
Start selbst an und listet nur Nutzbares - auf der VM belegt durch
"qsv: not available on this system" bei gleichzeitig fehlendem qsv_* in --help.
Jetzt ist HandBrakes Liste die einzige Auskunft.
Dazu nach FAMILIE unterschieden (nvenc/qsv/vce/vaapi) statt alles in "vaapi" zu
werfen - eine AMD-Karte lief unter dem Intel-Namen. Hardware-AV1 bekommt eine
eigene Kennung, weil es die beste Kombination aus Tempo und Groesse ist und
sonst unsichtbar bliebe.
## 3. Vektorbefehle unter Windows - gemessen, nicht "unbekannt"
Es gibt dort kein /proc/cpuinfo, also meldete der Windows-Worker
"Vektorbefehle unbekannt" - gerade auf der Maschine, die encodieren soll.
Jetzt ueber IsProcessorFeaturePresent (kernel32, winnt.h dokumentiert) plus
CPU-Name aus der Registry. Auf dem Commander-PC gegengeprueft:
vorher: AMD64 Family 26 Model 68 Stepping 0 / Vektorbefehle unbekannt
jetzt: AMD Ryzen 7 9700X 8-Core Processor / avx512f / 16 Kerne
Damit verschwindet die AVX2-Warnung fuer diesen Worker von selbst - genau das
hatte der Commander gefordert.
## 4. Ehrliche Fehlermeldung statt "Keine Roh-MKVs gefunden"
Neues _erreichbarkeit_pruefen() unterscheidet jetzt drei Faelle statt einem:
Pfad nicht erreichbar UND kein Mapping gesetzt (nennt RIPPY_PATH_MAP samt
Beispiel), Mapping gesetzt aber greift nicht, oder Pfad einfach nicht da. Und
es prueft BEIDE Pfade - im Fall des Commanders lag die Quelle auf der
erreichbaren NAS, das ZIEL aber auf der VM-Platte ohne Samba; das waere erst
beim Schreiben nach Stunden Rechenzeit aufgefallen.
Jede Meldung sagt jetzt ausdruecklich, dass die Rohdaten NICHT verloren sind
und "Neu komprimieren" genuegt.
## 5. Persoenliche Werte raus
Vier Platzhalter trugen die Umgebung des Commanders (192.168.178.20,
TOBIS-PC, seine Jellyfin- und Rippy-IP). In einem Repo, das weitergegeben
wird, hat das nichts verloren.
Nebenbei dreimal in die eigene Falle getappt: deutsche Anfuehrungszeichen in
DOPPELT gequoteten Python-Strings beenden den String vorzeitig. Der Bestand
nutzt dafuer einfach gequotete f-Strings - jetzt auch meine.
NOCH OFFEN und wichtig: RIPPY_PATH_MAP wird von niemandem GESETZT (Installer,
UI, Compose). Ein Windows-Worker kann damit grundsaetzlich nicht transcodieren.
Das ist der naechste Schritt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
141 lines
5.8 KiB
Python
141 lines
5.8 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([]) == []
|
|
assert caps.leite_backends_ab(None) == []
|
|
|
|
|
|
def test_backends_aus_echter_liste():
|
|
"""Das Worker-Image der VM kann laut eigener Auskunft keine Hardware —
|
|
entsprechend steht hier nur CPU."""
|
|
encoder = caps.parse_encoder_liste(HB_HILFE_ECHT)
|
|
assert caps.leite_backends_ab(encoder) == ["cpu-x264", "cpu-x265", "cpu-av1"]
|
|
|
|
|
|
def test_handbrakes_liste_ist_die_auskunft_ohne_geraetepruefung():
|
|
"""Regel-Wechsel 25.07.2026, weil die alte Fassung einen Bug hatte.
|
|
|
|
Vorher wurde zusätzlich ein Gerät verlangt: /dev/dri für VAAPI/QSV/VCE bzw.
|
|
nvidia-smi für NVENC. Unter WINDOWS gibt es beides nicht — der PC des
|
|
Commanders (RX 9070 XT) meldete deshalb nur CPU-Encoder, obwohl HandBrakes
|
|
Windows-Build vce_*/nvenc_*/qsv_* beherrscht. Der Bug traf genau den
|
|
Anwendungsfall, für den externe Worker gedacht sind.
|
|
|
|
Die Prüfung war zudem überflüssig: HandBrake probiert Hardware beim Start
|
|
selbst an und listet nur Nutzbares (auf der VM belegt — 'qsv: not available
|
|
on this system', und qsv_* fehlt dann in --help). Wer die Liste hat, hat die
|
|
Antwort; eine zweite Meinung braucht es nicht.
|
|
"""
|
|
mit_hw = caps.parse_encoder_liste(HB_HILFE_MIT_HARDWARE)
|
|
backends = caps.leite_backends_ab(mit_hw)
|
|
assert "nvenc" in backends
|
|
assert "qsv" in backends
|
|
# Ohne Geräteprüfung — es gibt keine Parameter mehr, die das verhindern
|
|
assert caps.leite_backends_ab(mit_hw) == backends
|
|
|
|
|
|
def test_hardware_wird_nach_familie_unterschieden():
|
|
"""Vorher landete alles in „vaapi" — eine AMD-Karte lief damit unter dem
|
|
Intel-Namen, und das UI konnte nicht sagen, welches Preset passt."""
|
|
amd = caps.leite_backends_ab(["x265", "vce_h264", "vce_h265"])
|
|
assert "vce" in amd
|
|
assert "qsv" not in amd and "nvenc" not in amd
|
|
|
|
intel = caps.leite_backends_ab(["x265", "qsv_h265"])
|
|
assert "qsv" in intel and "vce" not in intel
|
|
|
|
|
|
def test_hardware_av1_bekommt_eigene_kennung():
|
|
"""AV1 in Hardware ist derzeit die beste Kombination aus Tempo und
|
|
Dateigröße — das darf nicht in „nvenc" verschwinden, sonst kann das UI es
|
|
nicht empfehlen."""
|
|
backends = caps.leite_backends_ab(["x265", "nvenc_h265", "nvenc_av1"])
|
|
assert "nvenc" in backends
|
|
assert "nvenc-av1" in backends
|
|
# Ohne AV1 in der Liste gibt es die Kennung auch nicht
|
|
assert "nvenc-av1" not in caps.leite_backends_ab(["nvenc_h265"])
|
|
|
|
|
|
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"
|