Skip to content

Commit 5481416

Browse files
larszuclaude
andcommitted
Scope-Hilfe: Erklärkarte je Scope mit Aufgabe zum Abhaken, im Hilfe-Menü schaltbar
„?“ im Panelkopf: was, wofür, wie lesen, Aufgabe mit Testbild und Erfolgskriterium, typischer Fehler – für alle 36 Scopes, DE/EN. Texte gegen Normen (BT.709/2100/1886, R 103, R 128, BS.1770), Tektronix-/Sony-/BBC- Unterlagen und den Code geprüft (docs/research/scope-hilfe.md). Recherche Anwenderwünsche: docs/research/scope-wuensche.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015SeZtGvNXy2CQn9CDiA1Na
1 parent 771cc9d commit 5481416

14 files changed

Lines changed: 1737 additions & 0 deletions

File tree

‎README.de.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ Konfiguration: `--port`/`PORT` (4192; nicht 4190 – steht auf der Sperrliste de
291291

292292
`npm run dist:mac`, `npm run dist:win` bzw. `npm run dist:linux` baut die App mit eingebetteter Bridge und mitgeliefertem ffmpeg (Mac: Universal). Release: Tag `v*` → `release.yml` baut Windows, macOS und Linux (AppImage, deb), prüft das ffmpeg im Paket und hängt Installer und ffmpeg-Quelltext ans Release; `workflow_dispatch` ist ein Probelauf. Das mitgelieferte ffmpeg ist GPLv3 ohne nonfree-Teile, siehe [THIRD_PARTY.md](THIRD_PARTY.md) und [docs/research/ffmpeg-lizenz.md](docs/research/ffmpeg-lizenz.md).
293293

294+
## Scope-Hilfe
295+
296+
**Hilfe → Scope-Hilfe einblenden** setzt ein „?“ in jeden Panelkopf. Es öffnet eine kurze Karte: was der Scope zeigt, wofür man ihn beim Shading, Matching oder bei der Legalitätsprüfung braucht, wie man ihn liest, eine kleine Aufgabe mit dem eingebauten Testbild samt Erfolgskriterium zum Abhaken und ein typischer Fehler. Die Texte sind gegen BT.709/BT.2100/BT.1886, EBU R 103/R 128, ITU-R BS.1770 und Tektronix-, Sony- und BBC-Unterlagen geprüft, die Aussagen über die App gegen den Code; Quellen und Widersprüche zwischen den Quellen stehen in [docs/research/scope-hilfe.md](docs/research/scope-hilfe.md). Ausschalten über denselben Menüpunkt.
297+
294298
## Feedback
295299

296300
**Hilfe → Feedback senden …** öffnet einen Bericht mit Beschreibung, System (Betriebssystem und Version, Prozessor, Arbeitsspeicher), Grafik und Bildschirmen, Leistung (Anzeige-fps, je Quelle Auflösung, fps, verworfene Bilder) und den letzten Warnungen. Jeder Teil lässt sich abwählen; der angezeigte Text ist genau das, was gesendet wird. Nie enthalten: Bilder, Quellennamen und -adressen, Dateipfade, Benutzer- und Rechnernamen; Adressen, IPs und E-Mail-Adressen in Meldungen werden ersetzt. Senden per E-Mail an scopes@zumpelars.de (privat) oder als GitHub-Issue (öffentlich).

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ view.setSource(src);
207207
- No AJA input. NDI only with the NDI runtime installed, no sound, untested with real network sources. DeckLink only through our own helper (ffmpeg's own DeckLink device is "nonfree" and cannot be redistributed); it ships with the desktop app but has never run with hardware, and the Windows helper has only been compiled. Audio from the browser is limited to 2 channels (more only through the bridge). Not tested yet: multichannel interfaces and Dante on real hardware, the bridge on Windows, the A/V offset against a real camera.
208208
- Browser sources (camera, file) are always 8 bit and pass through the browser's colour management.
209209

210+
## Scope help
211+
212+
**Help → Show Scope Help** puts a "?" into every panel head. It opens a short card: what the scope shows, what it is for in shading, matching or legality checks, how to read it, one small task with the built-in test pattern and a success check to tick off, and a common pitfall. The texts are checked against BT.709/BT.2100/BT.1886, EBU R 103/R 128, ITU-R BS.1770 and Tektronix, Sony and BBC documents, the statements about the app against the code; sources and disagreements between sources are in [docs/research/scope-hilfe.md](docs/research/scope-hilfe.md). The same menu item switches it off.
213+
210214
## Feedback
211215

212216
**Help → Send Feedback …** opens a report with your description, system (OS and version, processor, memory), graphics and screens, performance (display fps; per source resolution, fps, dropped frames) and the latest warnings. Each part can be left out; the text shown is exactly what is sent. Never included: pictures, source names and addresses, file paths, user and computer names; addresses, IPs and e-mail addresses in messages are replaced. Send by e-mail to scopes@zumpelars.de (private) or as a GitHub issue (public).

‎docs/research/scope-hilfe.md‎

Lines changed: 1109 additions & 0 deletions
Large diffs are not rendered by default.

‎docs/research/scope-wuensche.md‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Scope-Wünsche aus Broadcast, Live und Event
2+
3+
Stand 09.10.2026. Recherche: Threads aus r/VIDEOENGINEERING (gelesen über das Archiv api.pullpush.io, Reddit selbst sperrt automatische Abrufe), YouTube-Titel und -Kapitel, Herstellerseiten. Was davon in lz-scopes umgesetzt wird, ist offen. Zusammenfassung von Quellen, keine eigenen Messungen.
4+
5+
Durchgehender Befund: Zum Shading gibt es kaum Lernmaterial, Wissen wird „from the old dogs to the new guys on site“ weitergegeben ([1jjmwmu](https://www.reddit.com/r/VIDEOENGINEERING/comments/1jjmwmu/colour_correction/)); im Corporate-Bereich macht oft eine Person EIC, V1 und Shading zugleich ([1behzp2](https://www.reddit.com/r/VIDEOENGINEERING/comments/1behzp2/eiccamera_shading/)). Daraus folgt die Scope-Hilfe (Hilfe → Scope-Hilfe einblenden).
6+
7+
## Gewünscht, in lz-scopes noch nicht vorhanden
8+
9+
| # | Wunsch | Quelle | Aufwand |
10+
|---|---|---|---|
11+
| 1 | Referenzspur einfrieren und über das Live-Signal legen (Waveform, Parade, Diamond) – gestimmte Kamera als Vorlage für die nächste | [Tektronix App-Note 25W-27159](https://www.telestream.net/pdfs/app-notes/Camera-Setup-Matching-and-Alignment-Application-Note-25W271590.pdf), empfohlen in [13ik5e1](https://www.reddit.com/r/VIDEOENGINEERING/comments/13ik5e1/video_shading/) | klein |
12+
| 2 | Kachelansicht: derselbe Scope für 4–8 Kameras mit Kamera-ID | [PRISM CAM/MULTI](https://blog.telestream.com/?p=12623), [Nobe Live Pack](https://digitalproduction.com/2026/03/11/nobe-omniscope-gets-live-pack-for-on-set-and-live-monitoring/) | klein–mittel |
13+
| 3 | Blendenskala (STOP) für jede Gamma, nicht nur Log | [PRISM STOP](https://blog.telestream.com/master-hdr-video-production-with-stop-monitoring/) | klein |
14+
| 4 | Fokushilfe: Peaking plus Schärfewert im Bereich | Leader LV5600 Focus Assist, Nobe Live Pack | klein–mittel |
15+
| 5 | Rauschmessung (Black Noise / SNR im Messrahmen) | [Leader Noise Meter](https://www.svgeurope.org/blog/news-roundup/leader-video-noise-meter-option-for-4k-waveform-monitor/) | klein–mittel |
16+
| 6 | Kameradaten im Scope: Iris, ND, Gain, Farbtemperatur, Tally, ID (Werte liefert lz-camera-bridge) | [Leader LV5600-SER27](https://www.testequipmentdepot.com/leader-lv5600-ser27-internal-option-id-iris-and-tally-display-software-option-for-lv5600-units.html) | mittel |
17+
| 7 | White-Shading-Karte: Ebenheit von Luma/Farbe auf gleichmäßiger Fläche, zerlegt in Sägezahn/Parabel H/V | [TV Technology](https://tvtechnology.com/miscellaneous/white-shading), [Ross](https://help.rossvideo.com/acid/Tasks/Acid-Cam/Lens/Lens-White.html) | klein–mittel |
18+
| 8 | Geführter Shading-Ablauf (Schwarz bei zu, Black Balance, Graukeil, Weiß, Knee, Matrix) | [13ik5e1](https://www.reddit.com/r/VIDEOENGINEERING/comments/13ik5e1/video_shading/), [16hdoql](https://www.reddit.com/r/VIDEOENGINEERING/comments/16hdoql/can_someone_explain_to_me_color_matrix_in_the/) | mittel |
19+
20+
## Gewünscht und schon vorhanden
21+
22+
Diamond zum Mitteln der Schwärzen ([1qtm2oq](https://www.reddit.com/r/VIDEOENGINEERING/comments/1qtm2oq/black_shading_question/)), Vectorscope-Zoom ×2/×5, YRGB-Parade, farbige Waveform, CIE, Hautton-Linie und -Waveform, Falschfarben, Lichtmesser, HDR-Skalen in cd/m², CST/LUT je Messpunkt für HDR/SDR-Simulcast, Farbabgleich in Kamerabegriffen, R128, Zebra, R103-Gamut, jetzt auch HLS-Vectorscope.
23+
24+
## Ideen, die es so noch nicht gibt
25+
26+
1. **Kamera-Match-Matrix:** N Kameras auf dieselbe Farbtafel, ΔE00 je Feld zur Referenzkamera, Vorschlag für die Multi-Matrix-Achsen. Canon bietet Abgleich nur statisch als LUT für eigene Kameras ([Canon](https://sg.canon/en/business/releases-free-pc-app-colour-matching-remote-and-main-cameras/news)), Sony beschreibt ihn manuell.
27+
2. **Hautton über alle Kameras:** Gesichter je Kamera erkennen, Hautverteilungen farbig in einem Vectorscope überlagern. Nobe kann es nur je Quelle.
28+
3. **Drift-Wächter während der Show:** Schwarzboden und Neutralstatistik je Kamera verfolgen, Alarm bei Abweichung vom Gruppenmittel (LED-Licht, Wolken, [13ik5e1](https://www.reddit.com/r/VIDEOENGINEERING/comments/13ik5e1/video_shading/)).
29+
4. **Black-/Flare-Assistent:** Schwarz-Schwerpunkt bei geschlossener und offener Blende vergleichen, Differenz als Flare-Vektor ([1qtm2oq](https://www.reddit.com/r/VIDEOENGINEERING/comments/1qtm2oq/black_shading_question/)).
30+
5. **Shutter-/Scanraten-Finder** für LED-Wände und -Licht: zeitliche FFT des Zeilenprofils, Shutter-Vorschlag mit ganzen Zyklen ([ENTTEC](https://support.enttec.com/pixel/pixel-general-knowledge/why-do-leds-flicker-on-camera), IEEE P2020 nur im Labor).
31+
6. **Moiré-Messer:** 2D-FFT im Wandbereich, Aliasing als Risikoanzeige (Sony warnt nur aus der Geometrie, [Newsshooter](https://www.newsshooter.com/2023/04/13/sony-virtual-production-tool-set/)).
32+
7. **Simulcast-Abweichungskarte:** ΔITP zwischen echtem und zurückgewandeltem Bild als Heatmap ([ProVideo Coalition](https://www.provideocoalition.com/fa-cup-final-broadcast-most-of-the-audience-watched-it-in-hd-sdr/)).
33+
8. **Encoder-Konfidenz für Streams:** Programm gegen Rücklauf (HLS/RTMP) – Blockbildung, Banding, A/V-Versatz, live; für kleine Produktionen gibt es nichts ([Streaming Learning Center](https://streaminglearningcenter.com/?p=20297)).
34+
9. **Objektiv-Fingerabdruck:** Farbabweichung und White Shading je Objektiv und Zoomstellung speichern, bei Wechsel abgleichen (Panasonic Lens Files nur für White Shading).
35+
36+
Herkunft der Liste: Recherche-Agent, Quellen nicht einzeln nachgeprüft; vor einer Umsetzung die jeweilige Primärquelle lesen.

‎e2e/menu.spec.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,19 @@ test('Feedback senden: Bericht zeigt genau die gewählten Daten', async () => {
8787
await dlg.locator('.modal-head button.icon').click();
8888
await expect(dlg).toHaveCount(0);
8989
});
90+
91+
test('Scope-Hilfe: „?“ im Panelkopf öffnet die Karte, Menü schaltet sie aus und an', async () => {
92+
const q = a.page.locator('.panel button[title^="Was ist"]');
93+
await expect(q.first()).toBeVisible();
94+
await q.first().click();
95+
const card = a.page.locator('.popover.scopehelp:popover-open');
96+
await expect(card).toContainText('Ausprobieren');
97+
await card.getByRole('checkbox', { name: 'Ausprobiert' }).check();
98+
await expect(card).toContainText(/1 von \d+ Aufgaben ausprobiert/);
99+
await a.page.keyboard.press('Escape');
100+
await menuClick(a, 'help:toggle');
101+
await expect(q).toHaveCount(0);
102+
await expect.poll(() => checked('help:toggle')).toBe(false);
103+
await menuClick(a, 'help:toggle');
104+
await expect(q.first()).toBeVisible();
105+
});

‎src/help/scopeHelp.ts‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Scope help (Help → Show scope help): a "?" in every panel head opens a short card – what the
2+
// scope is, what it is for, how to read it, one small task to try with the test pattern or a
3+
// camera, and a common pitfall. Tasks can be ticked off; the count shows what is left to try.
4+
// Texts: src/i18n/<lang>/help.ts, checked against the sources in docs/research/scope-hilfe.md.
5+
6+
import { checkbox, h, hint, kicker, type Kid } from '../ui';
7+
import { hasKey, t, type Key } from '../i18n';
8+
import type { ScopeType } from '../graticule';
9+
10+
const ON_KEY = 'lz-scopes.help';
11+
const DONE_KEY = 'lz-scopes.help.done';
12+
13+
export function helpOn(): boolean {
14+
try { return localStorage.getItem(ON_KEY) !== '0'; } catch { return true; }
15+
}
16+
export function setHelpOn(on: boolean) {
17+
try { localStorage.setItem(ON_KEY, on ? '1' : '0'); } catch { /* private mode */ }
18+
}
19+
20+
function doneSet(): Set<string> {
21+
try { const v = JSON.parse(localStorage.getItem(DONE_KEY) ?? '[]'); return new Set(Array.isArray(v) ? v.map(String) : []); } catch { return new Set(); }
22+
}
23+
function setDone(scope: string, on: boolean) {
24+
const s = doneSet(); if (on) s.add(scope); else s.delete(scope);
25+
try { localStorage.setItem(DONE_KEY, JSON.stringify([...s])); } catch { /* private mode */ }
26+
}
27+
28+
const k = (scope: string, part: string) => `help.${scope}.${part}` as Key;
29+
/** Scopes with a help text (the "?" appears only there). */
30+
export const hasHelp = (scope: ScopeType | string) => hasKey(k(scope, 'one'));
31+
32+
/** All scopes that have a task, for the progress count. */
33+
export function helpScopes(all: readonly string[]) { return all.filter((s) => hasKey(k(s, 'try'))); }
34+
35+
/** Rows of the help card for one scope (rebuilt each time the popover opens). */
36+
export function helpCard(scope: ScopeType, all: readonly string[]): Kid[] {
37+
if (!hasHelp(scope)) return [hint(t('help.none'))];
38+
const lines = (part: string) => (hasKey(k(scope, part)) ? t(k(scope, part)).split('\n').filter(Boolean) : []);
39+
const done = doneSet();
40+
const tasks = helpScopes(all);
41+
const progress = h('p', { class: 'hint help-progress' }, t('help.progress', { done: tasks.filter((s) => done.has(s)).length, all: tasks.length }));
42+
return [
43+
h('p', { class: 'help-one' }, t(k(scope, 'one'))),
44+
...lines('what').map((l) => h('p', {}, l)),
45+
lines('read').length ? kicker(t('help.read')) : null,
46+
lines('read').length ? h('ul', { class: 'help-list' }, ...lines('read').map((l) => h('li', {}, l))) : null,
47+
hasKey(k(scope, 'try')) ? h('div', { class: 'help-try' },
48+
kicker(t('help.try')),
49+
h('p', {}, t(k(scope, 'try'))),
50+
hasKey(k(scope, 'check')) ? h('p', { class: 'hint' }, t('help.checkPrefix'), ' ', t(k(scope, 'check'))) : null,
51+
checkbox(done.has(scope), t('help.done'), (v) => { setDone(scope, v); const n = doneSet(); progress.textContent = t('help.progress', { done: tasks.filter((s) => n.has(s)).length, all: tasks.length }); }),
52+
progress) : null,
53+
hasKey(k(scope, 'pitfall')) ? h('p', { class: 'help-pitfall' }, h('strong', {}, t('help.pitfall')), ' ', t(k(scope, 'pitfall'))) : null,
54+
].filter(Boolean) as Kid[];
55+
}

‎src/i18n/de.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import opple from './de/opple';
3434
import led from './de/led';
3535
import calib from './de/calib';
3636
import feedback from './de/feedback';
37+
import help from './de/help';
3738
import type { Key } from './en';
3839
import type { Msg } from './types';
3940

@@ -68,4 +69,5 @@ export const de: Record<Key, Msg> = {
6869
...led,
6970
...calib,
7071
...feedback,
72+
...help,
7173
};

0 commit comments

Comments
 (0)