Proposal: Skjermen — live-produksjon i arbeidsflaten
Skjerm-panel som live kompositor: dra inn videostrømmer, bilder, tekst og noder. Multi-skjerm med program/preview og live switching. Sceneskifte med fade-to-black + auto-pause for jukseredigering. Videoramme per deltaker, delt arbeidsflate som møterom/studio. Bygger på eksisterende primitiver (BlockShell, Canvas, LiveKit, drag-and-drop, CAS, PG NOTIFY). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2605f6de25
commit
af17ee3fa4
1 changed files with 265 additions and 0 deletions
265
docs/proposals/skjermen.md
Normal file
265
docs/proposals/skjermen.md
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
# Proposal: Skjermen — live-produksjon i arbeidsflaten
|
||||
|
||||
## Konsept
|
||||
|
||||
"Skjermen" er et panel i arbeidsflaten som fungerer som et
|
||||
produksjonsbord. Du drar inn videostrømmer, bilder, tekst og
|
||||
andre noder — og arrangerer dem fritt. Det som er i skjermen
|
||||
er det som tas opp eller strømmes.
|
||||
|
||||
Skjermen er ikke en video-editor. Den er en **live kompositor**
|
||||
som bruker drag-and-drop med eksisterende noder.
|
||||
|
||||
## Delt arbeidsflate som møterom/studio
|
||||
|
||||
Et møterom eller studio er en delt arbeidsflate med riktige traits.
|
||||
Alle deltakere ser sin egen arbeidsflate, men skjermen(e) er
|
||||
synkronisert — alle ser samme komposisjon.
|
||||
|
||||
```
|
||||
Delt arbeidsflate (podcaststudio):
|
||||
|
||||
Synkronisert: Personlig:
|
||||
┌──────────────────────┐ ┌─────────┐
|
||||
│ SKJERM (program) │ │ Notater │ ← kun deg
|
||||
│ Trond │ Arne │ └─────────┘
|
||||
│ Vegard│ Logo │ ┌─────────┐
|
||||
│ ●REC │ │ Chat │ ← alle ser
|
||||
└──────────────────────┘ └─────────┘
|
||||
┌──────────────────────┐ ┌─────────┐
|
||||
│ SKJERM (preview) │ │ Mixer │ ← delt
|
||||
│ Arne (stor) │ └─────────┘
|
||||
│ Trond│Vegard (små) │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
## Videoramme
|
||||
|
||||
Hvert deltaker har et panel — "videoramme" — som fanger kamera
|
||||
og mikrofon. Produserer en LiveKit-track som er en strøm-node.
|
||||
|
||||
- Styres av eieren (velg kamera, mikrofon, on/off)
|
||||
- Kan dras inn i skjermer av vert/produsent
|
||||
- Samme strøm kan refereres fra flere skjermer
|
||||
- Kan også fange skjermdeling
|
||||
|
||||
## Skjerm-panelet
|
||||
|
||||
### Grunnfunksjoner
|
||||
|
||||
- **Drop-target:** aksepterer videostrømmer, bilder, tekst, noder
|
||||
- **Fritt arrangement:** hvert element har posisjon, størrelse, z-order
|
||||
- **Resizerbart:** elementene inne i skjermen resizes fritt
|
||||
- **Aspect ratio:** låses til 16:9 (default), 4:3, 1:1 eller fritt
|
||||
- **Bakgrunn:** farge, gradient eller bilde
|
||||
- **Snap-to-grid:** valgfritt, for presis plassering
|
||||
|
||||
### Ting som kan dras inn
|
||||
|
||||
| Kilde | Resultat i skjermen |
|
||||
|-------|---------------------|
|
||||
| Videoramme (deltaker) | Live video-strøm |
|
||||
| Bildenode (CAS) | Statisk bilde (logo, illustrasjon) |
|
||||
| Tekstnode | Tittel, banner, navn-skilt |
|
||||
| Chat-panel | Live chat-overlay |
|
||||
| Lydvisualisering | Waveform/VU som visuelt element |
|
||||
| Presentasjon | Slides (bla manuelt eller auto) |
|
||||
| Skjermdeling | Deltakerens skjerm som strøm |
|
||||
| Annen node | Rendres som kort/boks |
|
||||
|
||||
### Fade og overganger
|
||||
|
||||
**Master opacity slider:**
|
||||
- 0% (helt svart) til 100% (fullt synlig)
|
||||
- Live, sanntids — brukes som manuell fade
|
||||
|
||||
**Sceneskifte-knapp:**
|
||||
```
|
||||
1. Trykk "Sceneskifte"
|
||||
2. Fade ut til svart (0.5-3s, konfigurerbar)
|
||||
3. Opptak pauses automatisk ved full blackout
|
||||
4. Bygg om scenen bak svartsensuren (flytt, resize, legg til, fjern)
|
||||
5. Trykk "Sceneskifte" igjen (eller "Fortsett")
|
||||
6. Opptak resumer
|
||||
7. Fade inn fra svart (samme varighet)
|
||||
```
|
||||
|
||||
I opptaksfilen ser det ut som én jevn overgang. Ingen klipping
|
||||
nødvendig. Live jukseredigering.
|
||||
|
||||
**Overgangstyper:**
|
||||
- Fade til svart (default)
|
||||
- Fade til hvitt
|
||||
- Fade til egendefinert farge
|
||||
- Crossfade (mellom to skjermer — se multi-skjerm)
|
||||
|
||||
### Opptak
|
||||
|
||||
- **REC-knapp** (rød prikk, synlig i skjerm-headeren)
|
||||
- **Pause/resume** (usynlig i output, sømløst)
|
||||
- **Tidskode-display** (total innspilt tid)
|
||||
- **Markører:** klikk for å sette en markør ("dette var bra",
|
||||
"klipp her") som lagres som tidsstempel-metadata
|
||||
- **Output:** server-side compositing via FFmpeg, eller
|
||||
canvas-capture API for klientsiden
|
||||
|
||||
### Forhåndsdefinerte layouts
|
||||
|
||||
Hurtigknapper for vanlige oppsett:
|
||||
- **Fullskjerm:** én kilde fyller alt
|
||||
- **2-split:** to kilder side om side
|
||||
- **3-split:** tre kilder (1 stor + 2 små, eller 3 like)
|
||||
- **PiP:** én stor + én liten i hjørnet
|
||||
- **Grid:** 2x2 eller 3x3
|
||||
- Alltid mulig å justere manuelt etterpå
|
||||
|
||||
## Multi-skjerm: Program / Preview
|
||||
|
||||
### Konsept
|
||||
|
||||
To (eller flere) skjermer som fungerer som TV-studio:
|
||||
|
||||
- **Program:** det som tas opp/strømmes akkurat nå
|
||||
- **Preview:** neste scene du forbereder
|
||||
|
||||
Samme videostrøm kan ligge i begge, med ulik layout.
|
||||
"Take" bytter dem.
|
||||
|
||||
### Bytte mellom skjermer
|
||||
|
||||
**Cut (øyeblikkelig):**
|
||||
- Preview → Program, Program → Preview
|
||||
- Bytte skjer på én frame
|
||||
|
||||
**Take (med overgang):**
|
||||
- Crossfade mellom Program og Preview
|
||||
- Konfigurerbar varighet
|
||||
- Program og Preview bytter roller etter overgangen
|
||||
|
||||
**Manuelt:**
|
||||
- Velg hvilken skjerm som er "live" via knapp/dropdown
|
||||
- De andre er tilgjengelige for redigering
|
||||
|
||||
### Brukseksempel: podcast med kameraveksling
|
||||
|
||||
```
|
||||
Skjerm A (program): Alle tre i grid
|
||||
Skjerm B (preview): Arne stor, Trond+Vegard små
|
||||
|
||||
Arne snakker → produsent trykker "Take" →
|
||||
Crossfade til Skjerm B (Arne stor) →
|
||||
Skjerm A er nå preview, redigeres for neste bytte
|
||||
|
||||
Trond tar over → produsent bygger Skjerm A om:
|
||||
Trond stor, Arne+Vegard små →
|
||||
Trykker "Take" → crossfade til Skjerm A
|
||||
```
|
||||
|
||||
Alt live, under innspilling, uten klipping etterpå.
|
||||
|
||||
### Ubegrenset antall skjermer
|
||||
|
||||
Ikke begrenset til to. Du kan ha:
|
||||
- Skjerm A: alle i grid (oversikt)
|
||||
- Skjerm B: Arne stor (nærportrett)
|
||||
- Skjerm C: Trond stor
|
||||
- Skjerm D: Vegard stor
|
||||
- Skjerm E: presentasjon fullskjerm
|
||||
- Skjerm F: chat-overlay over video
|
||||
|
||||
Bytt mellom dem etter behov. Hver har sin egen layout
|
||||
men deler de samme kilde-strømmene.
|
||||
|
||||
## Teknisk modell
|
||||
|
||||
### Skjerm som node
|
||||
|
||||
```
|
||||
node_kind: 'screen'
|
||||
metadata: {
|
||||
aspect_ratio: '16:9',
|
||||
background: { type: 'color', value: '#000000' },
|
||||
elements: [
|
||||
{ node_id: '<tronds-video>', x: 0, y: 0, w: 50, h: 50, z: 1 },
|
||||
{ node_id: '<arnes-video>', x: 50, y: 0, w: 50, h: 50, z: 1 },
|
||||
{ node_id: '<logo>', x: 80, y: 80, w: 15, h: 15, z: 10 },
|
||||
],
|
||||
is_program: true, // denne skjermen tas opp
|
||||
}
|
||||
```
|
||||
|
||||
Posisjon/størrelse i prosent (0-100) for oppløsningsuavhengighet.
|
||||
|
||||
### Skjerm i arbeidsflaten
|
||||
|
||||
Skjermen er et BlockShell-panel som:
|
||||
- Viser intern canvas med elementene
|
||||
- Synkroniseres via PG NOTIFY (alle ser samme layout)
|
||||
- Kun `owner`/`admin` kan endre innhold (dra inn/ut, resize)
|
||||
- Deltakere ser resultatet i sanntid
|
||||
|
||||
### Opptak
|
||||
|
||||
**Klientside (enklest):**
|
||||
- Canvas-capture API → MediaRecorder → upload til CAS
|
||||
- Begrensning: kvalitet avhenger av klientens maskin
|
||||
|
||||
**Serverside (bedre):**
|
||||
- Maskinrommet mottar layout-metadata + LiveKit-strømmene
|
||||
- FFmpeg compositor renderer til fil i sanntid
|
||||
- Uavhengig av klientens ytelse
|
||||
- Kan produsere flere oppløsninger
|
||||
|
||||
**Hybrid:**
|
||||
- Klientside for preview/monitoring
|
||||
- Serverside for endelig opptak
|
||||
|
||||
### Overgangsmotor
|
||||
|
||||
```rust
|
||||
struct Transition {
|
||||
from_screen: NodeId,
|
||||
to_screen: NodeId,
|
||||
kind: TransitionKind, // Fade, Cut, Crossfade, DipToColor
|
||||
duration_ms: u32,
|
||||
color: Option<Color>, // for DipToColor
|
||||
}
|
||||
```
|
||||
|
||||
Ved sceneskifte med pause:
|
||||
```
|
||||
1. Start DipToColor(svart) overgang
|
||||
2. Ved midtpunkt (100% svart): emit PauseRecording
|
||||
3. Vent på ResumeRecording signal
|
||||
4. Fullfør DipToColor (svart → transparent)
|
||||
```
|
||||
|
||||
## Hva dette bygger på (eksisterende)
|
||||
|
||||
- BlockShell: panel-wrapper med resize, drag, drop
|
||||
- Canvas: spatial layout med pan/zoom
|
||||
- LiveKit: WebRTC for video/lyd-strømmer
|
||||
- Drag-and-drop: universell overføring mellom paneler
|
||||
- CAS: lagring av opptak og bilder
|
||||
- PG NOTIFY + WebSocket: synkronisering av skjerm-layout
|
||||
- Node/edge-modell: alt er noder med relasjoner
|
||||
|
||||
## Hva som er nytt
|
||||
|
||||
- Skjerm-panel (canvas-i-canvas) med elementliste
|
||||
- Videoramme-panel (kamera/mikrofon-fangst)
|
||||
- Fade/overgang-motor
|
||||
- Multi-skjerm switching (program/preview)
|
||||
- Server-side compositing (FFmpeg)
|
||||
- Opptak med pause/resume og markører
|
||||
|
||||
## Prioritet
|
||||
|
||||
Høy ambisjon, kan bygges inkrementelt:
|
||||
1. Videoramme-panel (LiveKit-kamera i BlockShell)
|
||||
2. Enkel skjerm (drop-target med elementer, statisk layout)
|
||||
3. Opptak (klientside canvas-capture)
|
||||
4. Fade/overgang
|
||||
5. Multi-skjerm switching
|
||||
6. Server-side compositing
|
||||
7. Sceneskifte med auto-pause
|
||||
Loading…
Add table
Reference in a new issue