# 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) ```json { "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. ```json // 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. ```json // 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 |