synops/docs/proposals/skjermen.md
vegard c9bee967c7 Skjermen: dedikert sceneskifte-knapp med 0.2s fade + auto-pause
Én knapp, to trykk: fade ut (0.2s) → pause → bygg om → trykk igjen
→ fade inn (0.2s). Kort default for praktisk bruk, konfigurerbar.
Master opacity slider er separat for kreativ/manuell kontroll.

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

12 KiB

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 som standard uten grensesnittelementer — ingen BlockShell-header, ingen resize-handles, ingen border, ingen skygge. Bare innholdet. Skjermen er output.

Frameless er default, men valgfritt per element. Vert kan slå på ramme, navneskilt, skygge eller andre visuelle effekter per element i skjermen. Nyttig for f.eks. et bilde med border, eller en videostrøm med semi-transparent navnebanner over.

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 (dedikert, godt synlig):

Én knapp. To trykk. Ferdig.

Trykk 1: "Sceneskifte"
  → Rask fade til svart (0.2s default, konfigurerbar)
  → Opptak pauses automatisk ved full blackout
  → Knappen endrer tekst/farge: "Fortsett" (pulserer)
  → Bygg om scenen i ro og mak

Trykk 2: "Fortsett"
  → Opptak resumer
  → Rask fade inn fra svart (0.2s)
  → Knappen tilbake til "Sceneskifte"

I opptaksfilen: ...scene A [0.2s fade] scene B... Ser ut som en profesjonell overgang. Pausen er usynlig.

Fade-varigheten er kort som default (0.2s) — dette er et praktisk verktøy for å bytte scene raskt, ikke en kunstnerisk overgang. Kan justeres i innstillinger om ønskelig.

Master opacity slider (separat):

  • For manuell kontroll / kreativ bruk
  • 0-100%, live
  • Uavhengig av sceneskifte-knappen

Overgangstyper (for multi-skjerm switching):

  • Fade til svart (default)
  • Fade til hvitt
  • Fade til egendefinert farge
  • Crossfade (mellom to skjermer — se multi-skjerm)
  • Cut (øyeblikkelig, ingen fade)

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

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

Ytelsesanalyse (mars 2026)

Serverspesifikasjoner

  • 8 kjerner AMD EPYC @ 2.4 GHz (ingen hyperthreading)
  • 16 GB RAM (~10 GB tilgjengelig)
  • 204 GB ledig disk
  • ~270 Mbit/s båndbredde (Hetzner)
  • Ingen GPU

Video-strømmer (LiveKit SFU)

LiveKit er en SFU (Selective Forwarding Unit) — den videresender strømmer uten transkoding. Minimal CPU, primært båndbredde.

  • 3 deltakere: 9 strømmer (3 inn + 6 ut), ~15-25 Mbit/s
  • 10 deltakere: 100 strømmer, ~150-250 Mbit/s uten simulcast
  • 10 deltakere med simulcast: ~80-120 Mbit/s (realistisk)
  • LiveKit RAM: ~50-100 MB per sesjon med 3 deltakere

Server-side compositing (FFmpeg)

FFmpeg compositor: flere video-strømmer → én output.

  • 3 strømmer @ 720p → 1080p: ~2-3 CPU-kjerner kontinuerlig
  • RAM: ~500 MB - 1 GB per FFmpeg-instans

Kapasitetstabell

Scenario Gjennomførbart? Flaskehals
3 deltakere, klientside opptak Enkelt Ingen
3 deltakere, server compositing Ja 2-3 CPU-kjerner
10 deltakere, klientside Ja (med simulcast) Båndbredde
10 deltakere, server compositing ⚠️ Grenseland CPU + båndbredde
3 samtidige team, klientside Ja LiveKit RAM
3 samtidige team, server comp. Nei CPU (trenger 6-9 kjerner)
3 team klient + 1 team server Ja Balansert

Strategi

Klientside compositing som default. Skjerm-panelet bruker Canvas API til å komponere video-strømmene i nettleseren. Opptak via MediaRecorder API. Serveren bare videresender strømmer.

Fordeler:

  • Serveren belastes minimalt — skalerer til mange samtidige team
  • Null ekstra CPU for compositing
  • Lavere latens (ingen round-trip til server)

Ulemper:

  • Opptak-kvalitet avhenger av klientens maskin
  • Klienten må ha nok CPU (moderne laptop/desktop er nok)

Server-side compositing som valgfri premium:

  • For opptak i høyere kvalitet enn klienten klarer
  • For eksport/re-rendering i etterkant
  • Begrenset til én sesjon om gangen på nåværende server
  • Købasert: "bestill rendering" → jobbkø → ferdig → varsling

Oppgradering ved behov:

  • 16-kjerner, 32 GB hos Hetzner: ~€30/mnd ekstra
  • Gir kapasitet for 2-3 samtidige server-side compositinger
  • Eller: dedikert render-server (billig Hetzner-boks kun for FFmpeg)

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