You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
52 lines
3.1 KiB
52 lines
3.1 KiB
# 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).
|