synops/docs/proposals/skjermen.md
vegard bebf08644d Skjermen: frameless modus for noder inne i skjermen
Noder som dras inn i skjermen rendres uten grensesnittelementer —
ingen BlockShell-header, border, resize-handles. Bare rent innhold.
Skjermen er output, ikke utviklerverktøy. Vert redigerer layout
via skjermens egen editor-modus.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 08:05:33 +00:00

286 lines
8.9 KiB
Markdown

# 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
### Frameless modus
Noder som dras inn i skjermen rendres **uten grensesnittelementer**.
Ingen BlockShell-header, ingen resize-handles, ingen border, ingen
skygge. Bare innholdet. Skjermen er output — den skal se ut som
et ferdig bilde, ikke som et utviklerverktøy.
Resize og flytting av elementer *inne i skjermen* gjøres av
skjermens egen editor-modus (kun tilgjengelig for vert), ikke
av BlockShell. Elementene er rene rektangler med innhold.
Dette betyr at noder trenger en `frameless`-renderingsmodus:
- **Videoramme:** bare `<video>` — ingen kontroller, ingen header
- **Bildenode:** bare `<img>` — ingen border, ingen metadata
- **Tekstnode:** bare teksten — med font/farge/størrelse
- **Chat-overlay:** bare meldingsstrøm — transparent bakgrunn
BlockShell brukes fortsatt for paneler *utenfor* skjermen
(i arbeidsflaten). Det er bare inne i skjerm-panelet at
innhold rendres frameless.
### Ting som kan dras inn
| Kilde | Resultat i skjermen |
|-------|---------------------|
| Videoramme (deltaker) | Ren video-strøm (frameless) |
| Bildenode (CAS) | Rent bilde (frameless) |
| Tekstnode | Ren tekst med styling (frameless) |
| Chat-panel | Meldingsstrøm med transparent bg |
| Lydvisualisering | Waveform/VU uten ramme |
| Presentasjon | Slides (frameless) |
| Skjermdeling | Deltakerens skjerm (frameless) |
| Annen node | Minimal rendering, tilpasset innhold |
### 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