fix(caps,ui): Encoder werden gemessen statt behauptet
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>
This commit is contained in:
@@ -14,6 +14,7 @@ interface WorkerInfo {
|
||||
const ENCODER_LABELS: Record<string, string> = {
|
||||
'cpu-x264': 'CPU · H.264 (x264)',
|
||||
'cpu-x265': 'CPU · H.265 (x265)',
|
||||
'cpu-av1': 'CPU · AV1 (SVT-AV1)',
|
||||
'vaapi': 'Hardware · VAAPI (AMD/Intel)',
|
||||
'nvenc': 'Hardware · NVENC (NVIDIA)',
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ interface WorkerWahl {
|
||||
}
|
||||
|
||||
const ENCODER_KURZ: Record<string, string> = {
|
||||
'cpu-x264': 'H.264', 'cpu-x265': 'H.265', 'vaapi': 'VAAPI⚡', 'nvenc': 'NVENC⚡',
|
||||
'cpu-x264': 'H.264', 'cpu-x265': 'H.265', 'cpu-av1': 'AV1',
|
||||
'vaapi': 'VAAPI⚡', 'nvenc': 'NVENC⚡',
|
||||
}
|
||||
|
||||
interface TitelInfo {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Server, RefreshCw, Copy, CheckCircle, Trash2, Download } from 'lucide-react'
|
||||
import { api } from '../lib/api'
|
||||
import { simdWarnung } from '../lib/encoder'
|
||||
import { useToast } from '../context/ToastContext'
|
||||
import { Card, CardHeader, CardTitle, CardContent } from './ui/Card'
|
||||
import { Button } from './ui/Button'
|
||||
@@ -16,16 +17,22 @@ interface WorkerInfo {
|
||||
ip?: string
|
||||
makemkv?: string
|
||||
handbrake?: string
|
||||
cpu_modell?: string
|
||||
cpu_kerne?: string
|
||||
cpu_simd?: string
|
||||
handbrake_encoder?: string
|
||||
}
|
||||
}
|
||||
|
||||
const ENCODER_LABELS: Record<string, string> = {
|
||||
'cpu-x264': 'CPU · H.264',
|
||||
'cpu-x265': 'CPU · H.265',
|
||||
'cpu-av1': 'CPU · AV1 (SVT)',
|
||||
'vaapi': 'GPU · VAAPI (AMD/Intel)',
|
||||
'nvenc': 'GPU · NVENC (NVIDIA)',
|
||||
}
|
||||
|
||||
|
||||
function relativeZeit(iso?: string): string {
|
||||
if (!iso) return 'nie'
|
||||
const sekunden = Math.floor((Date.now() - new Date(iso).getTime()) / 1000)
|
||||
@@ -134,6 +141,18 @@ export default function WorkerVerwaltung() {
|
||||
{w.info?.ip ? ` · IP ${w.info.ip}` : ''}
|
||||
{w.info?.hostname && w.info.hostname !== w.name ? ` · ID ${w.info.hostname}` : ''}
|
||||
</p>
|
||||
{(w.info?.cpu_kerne || w.info?.cpu_simd) && (
|
||||
<p className="text-xs text-slate-500 dark:text-slate-400" title={w.info?.cpu_modell || ''}>
|
||||
{w.info?.cpu_kerne ? `${w.info.cpu_kerne} Kerne` : ''}
|
||||
{w.info?.cpu_kerne && w.info?.cpu_simd ? ' · ' : ''}
|
||||
{w.info?.cpu_simd ? `Vektorbefehle ${w.info.cpu_simd}` : ''}
|
||||
</p>
|
||||
)}
|
||||
{simdWarnung(w.info?.cpu_simd) && (
|
||||
<p className="mt-1 text-xs text-amber-600 dark:text-amber-400 max-w-xl">
|
||||
{simdWarnung(w.info?.cpu_simd)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
Reference in New Issue
Block a user