synops/docs/features/lydstudio.md
vegard b4c4bb8a0f Lydstudio: lydredigering via FFmpeg i nettleseren
Ikke-destruktiv redigering via EDL (Edit Decision List):
- Backend: audio.rs med FFmpeg-subprocess for klipp, normalisering,
  silence trim, fades, noise reduction, EQ, kompressor
- Frontend: /studio/[id] med wavesurfer.js RegionsPlugin,
  verktøypanel, sesjonslagring, og render-dialog
- Studio-trait for samlinger, versjonshistorikk via derived_from-edges
- API: audio_analyze (synkron), audio_process (jobbkø), audio_info

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:45:53 +00:00

4.4 KiB

Lydstudio — Lydredigering i nettleseren

Status: Under utvikling (v1)

Konsept

Lydstudioet er en visning (/studio/[id]) av en medienode som gir brukeren verktøy for enkel lydredigering direkte i nettleseren. Tenk "Audacity-light" integrert i Synops-plattformen.

Prinsipp: Ikke-destruktiv redigering. Originalen i CAS røres aldri. Operasjoner lagres som en EDL (Edit Decision List), og rendres til ny fil via maskinrommet + ffmpeg.

Arkitektur

Node/edge-modell

Original medienode (media, cas_hash: "abc...")
  ←derived_from── Prosessert medienode (media, cas_hash: "def...", metadata.edl)
  ←has_studio──── Studio-sesjon (content, metadata.edl = {...})
  • Studioet er en visning, ikke en ny node_kind
  • Studio-sesjon er en content-node som lagrer EDL-en (gjenopptagbart)
  • Prosessert fil er en ny medienode med derived_from-edge

EDL-format (Edit Decision List)

{
  "source_hash": "abc123...",
  "operations": [
    { "type": "cut", "start_ms": 15200, "end_ms": 17800 },
    { "type": "normalize", "target_lufs": -16.0 },
    { "type": "trim_silence", "threshold_db": -30.0, "min_duration_ms": 500 },
    { "type": "fade_in", "duration_ms": 1000 },
    { "type": "fade_out", "duration_ms": 2000 },
    { "type": "noise_reduction", "strength_db": -25.0 },
    { "type": "equalizer", "low_gain": 2.0, "mid_gain": 0.0, "high_gain": -1.0 },
    { "type": "compressor", "threshold_db": -20.0, "ratio": 4.0 }
  ]
}

Prosesseringsflyt

Frontend (EDL)
  → POST /intentions/audio_process
  → Jobbkø (audio_process, prioritet 5)
  → maskinrommet: edl → ffmpeg filtergraf → subprocess
  → Resultat lagres i CAS → ny medienode + derived_from edge

Operasjoner

Operasjon FFmpeg-filter Beskrivelse
Klipp (cut) aselect + asetpts Fjern region (nysing, telefon, etc.)
Normaliser loudnorm (to-pass) EBU R128 loudness-normalisering, typisk -16 LUFS
Trim stillhet silencedetect → cuts Forkort/fjern stille regioner
Fade in afade=t=in Gradvis inngang
Fade out afade=t=out Gradvis utgang
Noise reduction afftdn FFT-basert støyreduksjon
EQ equalizer Tre-bånds parametrisk (lav/mid/høy)
Kompressor acompressor Dynamisk kompresjon ("radio-lyd")

Operasjonsrekkefølge (ved render)

  1. Cuts (aselect) — fjerner regioner
  2. Noise reduction (afftdn)
  3. EQ (equalizer)
  4. Compressor (acompressor)
  5. Normalize (loudnorm) — alltid nest sist
  6. Fades (afade) — helt sist

API-endepunkter

POST /intentions/audio_analyze

Synkron analyse av lydfil: loudness, silence-regioner, metadata.

// Request
{ "cas_hash": "abc...", "silence_threshold_db": -30.0, "silence_min_duration_ms": 500 }

// Response
{
  "loudness": { "input_i": -23.1, "input_tp": -5.2, "input_lra": 14.0, "input_thresh": -34.0 },
  "silence_regions": [{ "start_ms": 1200, "end_ms": 2800, "duration_ms": 1600 }],
  "info": { "duration_ms": 180000, "sample_rate": 44100, "channels": 2, "codec": "mp3", "format": "mp3" }
}

POST /intentions/audio_process

Køer render-jobb med EDL. Returnerer job_id for polling.

// Request
{ "media_node_id": "uuid", "edl": { "source_hash": "...", "operations": [...] }, "output_format": "mp3" }

// Response
{ "job_id": "uuid" }

GET /query/audio_info?hash=...

Hurtig metadata om lydfil (ffprobe).

Frontend

  • Rute: /studio/[id] — waveform-visning av medienode
  • Waveform: wavesurfer.js med RegionsPlugin for visuell region-markering
  • Verktøypanel: Alle operasjoner tilgjengelig som knapper/slidere
  • Tastatur: Space (play/pause), Delete (klipp), Ctrl+Z (angre)
  • Transkripsjon: Segmenter synkronisert med waveform (klikk → seek)
  • Render: Dialog med format-valg, deretter jobb-polling

Avhengigheter

  • ffmpeg 6.1.1 — installert native på serveren
  • wavesurfer.js — allerede i bruk (AudioPlayer.svelte)
  • Trait: studio — aktiverer "Rediger i studioet"-knapp på medienoder

Filer

Fil Rolle
maskinrommet/src/audio.rs EDL-parser, ffmpeg-kommandoer, jobbhåndterer
maskinrommet/src/jobs.rs audio_process dispatch
maskinrommet/src/intentions.rs API-endepunkter for analyze/process/info
frontend/src/routes/studio/[id]/+page.svelte Hovedside
frontend/src/lib/components/studio/ Waveform, panel, render-dialog