release: 5.0.6 — streamlink stdout-Capture + CSS select+checkbox fixes

Streamlink Diagnose:
- stdout-Buffer wird jetzt zusaetzlich zu stderr gesammelt; einige
  streamlink-Builds schreiben 'error:'-Lines auf stdout statt stderr,
  was bisher zu leerem stderrTail + 'Streamlink exit code 1' ohne
  Detail-Info gefuehrt hat.
- download-part-failed Debug-Log enthaelt jetzt stderrTail UND
  stdoutTail (jeweils letzte 2000 chars), plus User-facing-Error wird
  aus beiden Streams kombiniert gesucht.

CSS:
- .form-group select: 'background: ...' Shorthand wurde durch
  'background-color: ...' ersetzt — Shorthand hatte background-image
  (Chevron-SVG), background-repeat, background-position, background-size
  aus der globalen select-Regel resettet, was zu tiled Chevrons im
  Dropdown gefuehrt hat ('Best (default) ▼▼▼▼▼▼...').
- input[type='checkbox']:checked: rotated-border-Trick durch inline-
  SVG-Checkmark ersetzt — die rotated borders renderten in mstsc/RDP-
  Sessions teilweise als Pfeile statt Haken (DPI-Skalierungs-Artefakt).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xRangerDE 2026-05-19 04:04:33 +02:00
parent e270e1ec12
commit 5e78068169
4 changed files with 55 additions and 26 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
"version": "5.0.5",
"version": "5.0.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
"version": "5.0.5",
"version": "5.0.6",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",

View File

@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
"version": "5.0.5",
"version": "5.0.6",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",

View File

@ -3139,13 +3139,24 @@ function downloadVODPart(
}
}, 1000);
const stdoutBuffer: string[] = [];
proc.stdout?.on('data', (data: Buffer) => {
const line = data.toString();
// No per-line stdout — streamlink emits 10-100 lines/sec during
// an active download, which floods the terminal in dev and the
// electron-launched console in prod. Progress + tag parsing
// below extracts everything we need; failures get logged via
// appendDebugLog from the consumer side.
// Capture non-progress lines auch fuer Diagnose — streamlink-Windows-
// Builds schreiben einige Errors auf stdout statt stderr (z.B. "error:
// No playable streams found on this URL"). Wenn stderr leer bleibt,
// greift der close-handler auf stdout zurueck.
stdoutBuffer.push(line);
if (stdoutBuffer.length > 200) stdoutBuffer.shift();
const lower = line.toLowerCase();
if (lower.includes('error:') || lower.includes('warning:')) {
appendDebugLog('download-part-stdout-err', { itemId, message: line.trim() });
if (lower.includes('error:')) {
// Letzte echte streamlink-Errorzeile, auch wenn auf stdout
const errLine = line.split('\n').map(l => l.trim()).filter(l => l.toLowerCase().includes('error:')).pop();
if (errLine) lastErrorLine = errLine;
}
}
// Parse progress
const match = line.match(/(\d+\.\d+)%/);
@ -3227,17 +3238,30 @@ function downloadVODPart(
return;
}
// Volle stderr-History im Debug-Log (kollabiert) — fuer Forensik
// wenn der User schreibt "es funktioniert nicht". User-facing
// genericError ist die echte streamlink-Fehlerzeile, nicht nur
// "Streamlink Fehlercode 1".
// Volle stderr+stdout-History im Debug-Log fuer Forensik.
// Streamlink-Windows-Builds schreiben Errors gelegentlich auf
// stdout statt stderr ("No playable streams found on this URL"
// war historisch ein stdout-Error). Wir mergen beide Streams
// damit immer SICHTBAR ist was passiert.
const fullStderr = stderrBuffer.join('').trim();
const userFacingError = lastErrorLine
|| (fullStderr.split('\n').filter(l => l.trim()).pop() || '').trim()
|| tBackend('streamlinkExitCode', { code: String(code ?? -1) });
const fullStdout = stdoutBuffer.join('').trim();
// Letzte Error-/Warning-Zeile aus beiden Streams suchen, falls
// lastErrorLine noch leer ist (z.B. weil streamlink ohne Output
// mit Code 1 exited — was bei pre-flight-Auth-Fails passiert).
let userFacingError = lastErrorLine;
if (!userFacingError) {
const combined = (fullStderr + '\n' + fullStdout).split('\n').map(l => l.trim()).filter(Boolean);
userFacingError = combined.filter(l => l.toLowerCase().includes('error:')).pop()
|| combined.filter(l => !l.startsWith('[')).pop()
|| '';
}
if (!userFacingError) {
userFacingError = tBackend('streamlinkExitCode', { code: String(code ?? -1) });
}
appendDebugLog('download-part-failed', {
itemId, filename, code, error: userFacingError,
stderrTail: fullStderr.slice(-2000),
stdoutTail: fullStdout.slice(-2000),
});
resolve({ success: false, error: userFacingError });
});

View File

@ -756,20 +756,21 @@ input[type="checkbox"]:hover:not(:disabled) {
}
input[type="checkbox"]:checked {
background: var(--accent);
/* Inline-SVG-Checkmark statt rotated-border-Trick robuster ueber
DPI-Skalierungen und Remote-Desktop-Renderings (RDP / mstsc), wo
die kleinen border-rotation-Pseudo-Elemente teilweise als
Dreiecke / Pfeile gerendert wurden. */
background-color: var(--accent);
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3.5 8.5 6.5 11.5 12.5 5'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
background-size: 12px;
border-color: var(--accent);
}
input[type="checkbox"]:checked::after {
content: '';
position: absolute;
left: 4px;
top: 0.5px;
width: 5px;
height: 9px;
border: solid #fff;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
/* Pseudo-Element nicht mehr noetig — Checkmark kommt aus background. */
content: none;
}
input[type="checkbox"]:focus-visible {
@ -1761,7 +1762,11 @@ select option {
.form-group input:not([type="checkbox"]):not([type="radio"]), .form-group select {
width: 100%;
background: var(--bg-main);
/* background-color (nicht background shorthand) sonst wuerden
background-image (Chevron-SVG), background-repeat, background-size
und background-position aus der globalen `select`-Regel resettet,
was zu tiled Chevrons im Dropdown gefuehrt hat. */
background-color: var(--bg-main);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 4px;
padding: 10px 12px;