commit
86d1b44000
@ -0,0 +1,2 @@
|
|||||||
|
Lies docs/05-testplan-hardware.md und docs/06-netzwerk.md.
|
||||||
|
Erstelle für den aktuellen Stand der App eine Checkliste, die ich im Testaufbau abarbeiten kann: welche Geräte, welche IP-Adressen, welche Szene, welche Messung (Latenz, CPU-Last, Aussetzer über Zeit). Ergänze fehlende Schritte direkt in docs/05-testplan-hardware.md.
|
||||||
@ -0,0 +1 @@
|
|||||||
|
Gib mir einen kurzen Stand: welcher Meilenstein ist offen, was ist fertig, was ist ungetestet, welche offenen Fragen stehen in den docs. Maximal 10 Zeilen.
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
# Musubi
|
||||||
|
|
||||||
|
**NDI rein. Bild, Ton und Stimme raus.**
|
||||||
|
|
||||||
|
Musubi (結び, japanisch: das Knüpfen, Verbinden) ist eine macOS-App von Zielke Studio für kleine Live-Übertragungen. Sie macht MacBook und Mac mini zu den fehlenden Bausteinen einer Regie:
|
||||||
|
|
||||||
|
- NDI-Quellen im Vollbild auf beliebige Bildschirme
|
||||||
|
- NDI-Ton (auch ohne Bild) gezielt auf einzelne Kanäle eines Audio-Interfaces
|
||||||
|
- Talkback per Sprechtaste
|
||||||
|
- Intercom, PGM-Vorschau und Tally fürs Handy im Browser
|
||||||
|
- Szenen, die Regie-Mac und Bühnen-Mac auf einen Klick einrichten
|
||||||
|
|
||||||
|
Erster Einsatz: OP-Liveübertragung (ATEM im OP, Regie im Saal, eine Netzwerkleitung dazwischen).
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Planung abgeschlossen, Entwicklung startet mit Meilenstein 0. Siehe [docs/04-fahrplan.md](docs/04-fahrplan.md).
|
||||||
|
|
||||||
|
## Dokumente
|
||||||
|
|
||||||
|
| Datei | Inhalt |
|
||||||
|
|---|---|
|
||||||
|
| [CLAUDE.md](CLAUDE.md) | Arbeitsanweisungen für Claude Code |
|
||||||
|
| [START.md](START.md) | Startbefehl für Claude Code |
|
||||||
|
| [docs/01-konzept.md](docs/01-konzept.md) | Idee, Rollen, Funktionsumfang |
|
||||||
|
| [docs/02-architektur.md](docs/02-architektur.md) | Module, Frameworks, Datenflüsse |
|
||||||
|
| [docs/03-design.md](docs/03-design.md) | Designsystem, Farben, Typografie, Texte |
|
||||||
|
| [docs/04-fahrplan.md](docs/04-fahrplan.md) | Meilensteine mit Abnahmetests |
|
||||||
|
| [docs/05-testplan-hardware.md](docs/05-testplan-hardware.md) | Tests, sobald die Hardware da ist |
|
||||||
|
| [docs/06-netzwerk.md](docs/06-netzwerk.md) | IP-Plan, Schnittstellen, Relay als Plan B |
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Xcode (aktuell), macOS auf Apple Silicon zum Entwickeln
|
||||||
|
- NDI SDK für macOS (nicht im Repo, siehe [Vendor/README.md](Vendor/README.md))
|
||||||
|
- Zielgeräte: MacBook (Apple Silicon) und Mac mini 2018 (Intel, macOS 15) → Universal Build
|
||||||
|
|
||||||
|
© Zielke Studio
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
# Start mit Claude Code
|
||||||
|
|
||||||
|
## Einmalig vorbereiten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Developer/musubi # dein Repo
|
||||||
|
git init && git add . && git commit -m "chore: project brief and docs"
|
||||||
|
# NDI SDK installieren und nach Vendor/NDI/ kopieren (siehe Vendor/README.md)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Startbefehl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude "Lies CLAUDE.md und alle Dateien in docs/. Fasse in 5 Sätzen zusammen, was Musubi ist und was Meilenstein 0 verlangt. Mach dann einen Plan für Meilenstein 0 (Xcode-Projekt als Universal Build für macOS 14, Modulstruktur laut docs/02-architektur.md, NDI SDK einbinden, Designsystem aus design/Theme.swift, leeres Hauptfenster mit Quellenliste). Warte auf mein OK, bevor du Dateien anlegst."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Danach
|
||||||
|
|
||||||
|
- Nächster Meilenstein: `/meilenstein` (Slash-Command in `.claude/commands/`)
|
||||||
|
- Hardware-Test vorbereiten: `/hardwaretest`
|
||||||
|
- Stand prüfen: `/status`
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
# Vendor
|
||||||
|
|
||||||
|
## NDI SDK
|
||||||
|
|
||||||
|
Das NDI SDK wird **nicht** eingecheckt (Lizenzbedingungen).
|
||||||
|
|
||||||
|
1. NDI SDK für macOS von ndi.video herunterladen und installieren.
|
||||||
|
2. Header und `libndi` nach `Vendor/NDI/` kopieren:
|
||||||
|
```
|
||||||
|
Vendor/NDI/include/Processing.NDI.Lib.h (+ übrige Header)
|
||||||
|
Vendor/NDI/lib/libndi.dylib (Universal: arm64 + x86_64)
|
||||||
|
```
|
||||||
|
3. Prüfen, dass die Bibliothek beide Architekturen enthält:
|
||||||
|
```
|
||||||
|
lipo -info Vendor/NDI/lib/libndi.dylib
|
||||||
|
```
|
||||||
|
4. Lizenz- und Namensregeln (NDI®-Kennzeichnung, Weitergabe) vor jedem Verkauf prüfen.
|
||||||
|
|
||||||
|
## Blackmagic ATEM Switchers SDK (ab Meilenstein 6)
|
||||||
|
|
||||||
|
Aus dem Blackmagic Support Center laden (Developer SDK zu ATEM Switchers). Ablage in `Vendor/ATEM/`, nicht einchecken, falls die Lizenz es verlangt.
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Musubi",
|
||||||
|
"color": {
|
||||||
|
"sumi": { "dark": "#14151B", "light": "#F4F4F6", "role": "background" },
|
||||||
|
"kasumi": { "dark": "#1E2029", "light": "#FFFFFF", "role": "surface" },
|
||||||
|
"usuzumi": { "dark": "#2B2E3A", "light": "#DADBE2", "role": "line" },
|
||||||
|
"washi": { "dark": "#ECE9E2", "light": "#16171D", "role": "text" },
|
||||||
|
"nezumi": { "dark": "#8E8C96", "light": "#6A6974", "role": "textMuted" },
|
||||||
|
"ai": { "dark": "#8A99F2", "light": "#4F63D9", "role": "accent" },
|
||||||
|
"shu": { "value": "#E5484D", "role": "statusLive" },
|
||||||
|
"moegi": { "value": "#3DBE7A", "role": "statusPreview" },
|
||||||
|
"kohaku": { "value": "#E8A23A", "role": "statusWarning" }
|
||||||
|
},
|
||||||
|
"radius": { "card": 12, "button": 8, "chip": 6 },
|
||||||
|
"spacing": { "unit": 8, "cardPadding": 16 },
|
||||||
|
"stroke": { "line": 1, "cord": 2, "knot": 6 },
|
||||||
|
"type": {
|
||||||
|
"app": { "ui": "SF Pro", "numbers": "SF Mono" },
|
||||||
|
"brand": { "heading": "Kanit 600", "body": "Kanit 400", "highlight": "Instrument Serif Italic" }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
# Architektur
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
```
|
||||||
|
Technik-Netz Musubi (MacBook, Regie) Ausgänge
|
||||||
|
────────────── ─────────────────────────── ─────────────────────
|
||||||
|
ZowieBox MV ─NDI|HX3─▶ NDIKit ──▶ VideoOutput ───────────────▶ Regie-Bildschirm
|
||||||
|
ZowieBox PGM ─NDI|HX3─▶ │
|
||||||
|
└──▶ AudioMatrix ──────────────────▶ MOTU M2 Out 1/2 → Ui12
|
||||||
|
Headset-Mikro ─────────────────▶ AudioMatrix
|
||||||
|
ATEM ─────────Status───▶ Tally ──▶ Intercom ◀──WebRTC──▶ Handy im OP (Klinik-Netz)
|
||||||
|
MusubiCore (Szenen) ─Bonjour─▶ Mac mini (Knoten, Bühne)
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Mac mini empfängt NDI selbst direkt aus dem Technik-Netz und wird von der Regie nur gesteuert.
|
||||||
|
|
||||||
|
## Module
|
||||||
|
|
||||||
|
| Modul | Aufgabe | Technik |
|
||||||
|
|---|---|---|
|
||||||
|
| MusubiCore | Modelle (Quelle, Ausgang, Route, Szene), Persistenz, Einstellungen | Swift, Codable/JSON, Swift Testing |
|
||||||
|
| NDIKit | Quellen finden, empfangen (Video+Audio oder nur Audio), Statistik | NDI SDK (C), `NDIlib_find_*`, `NDIlib_recv_*`, Bandbreite `audio_only` für reinen Ton |
|
||||||
|
| VideoOutput | Frames darstellen, ein Vollbildfenster je `NSScreen`, Anzeigemodus 50 Hz | Metal oder `AVSampleBufferDisplayLayer`, `CGDisplayCopyAllDisplayModes` |
|
||||||
|
| AudioMatrix | Quellen → Ausgangskanäle, Gain, Mute, Pegel, Sprechtaste | Core Audio / `AVAudioEngine`, Kanalzuordnung (`channelMap`) |
|
||||||
|
| Remote | Regie ↔ Knoten: Szene setzen, Status melden | Bonjour (`NWListener`/`NWBrowser`), JSON-Nachrichten |
|
||||||
|
| Intercom | Web-Seite, Signalisierung, Audio hin/zurück, PGM-Vorschau | eingebetteter HTTPS-Server, WebRTC (Opus, H.264 via VideoToolbox), Bindung an Schnittstelle |
|
||||||
|
| Tally | PGM/Vorschau-Eingänge des ATEM lesen | Blackmagic ATEM Switchers SDK |
|
||||||
|
|
||||||
|
## Datenmodell (Entwurf)
|
||||||
|
|
||||||
|
```swift
|
||||||
|
struct Source: Codable, Hashable { var ndiName: String; var label: String }
|
||||||
|
enum Output: Codable, Hashable { case screen(displayID: UInt32), audioChannel(deviceUID: String, channel: Int) }
|
||||||
|
struct Route: Codable, Hashable { var source: Source; var output: Output; var mode: Mode
|
||||||
|
enum Mode: String, Codable { case videoAndAudio, videoOnly, audioOnly } }
|
||||||
|
struct Scene: Codable, Identifiable { var id: UUID; var name: String; var role: Role; var routes: [Route] }
|
||||||
|
enum Role: String, Codable { case control, node }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Threads
|
||||||
|
|
||||||
|
- NDI-Empfang je Quelle auf eigener Queue.
|
||||||
|
- Video: Frames ohne Kopie an die Darstellung (CVPixelBuffer), Rendern im Takt des Displays.
|
||||||
|
- Audio: Ringpuffer zwischen NDI-Empfang und Render-Callback, keine Allokationen im Callback, Drift-Ausgleich (Resampling) zwischen NDI-Takt und Interface-Takt.
|
||||||
|
|
||||||
|
## Netzwerk-Bindung
|
||||||
|
|
||||||
|
- NDI, Bonjour, Remote: nur Technik-Schnittstelle.
|
||||||
|
- Intercom: nur Klinik-Schnittstelle (oder TURN-Relay nach außen).
|
||||||
|
- Schnittstellen in den Einstellungen per Name wählbar (z. B. `en7` Technik, `en0` Klinik).
|
||||||
Loading…
Reference in new issue