synops/docs/features/lydmeldinger.md
vegard 00bf5d27ce Arkitekturbeslutninger: noder er sentrum, edges definerer alt
Grunnleggende arkitekturbeslutninger tatt og dokumentert:

- Alt er noder (brukere, team, innhold, mediefiler, samlings-noder)
- Edges definerer hva en node er (freeform typer, metadata i JSONB)
- Materialisert tilgangsmatrise (node_access) erstatter workspace-RLS
- Visibility (hidden/discoverable/readable/open) på noder
- Aliaser via usynlige system-edges
- Maskinrommet eier all skriving (SpacetimeDB først, PG asynk)
- SpacetimeDB holder hele grafen, PG er persistent backup
- Node- og edge-skjema spesifisert (docs/primitiver/)

Fjernet workspace-konseptet fra hele dokumentasjonen (~40 filer).
Fem retninger besluttet, én åpen (rom, ikke forum).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 10:29:54 +01:00

6.3 KiB
Raw Blame History

Feature: Lydmeldinger & Diktering

Filsti: docs/features/lydmeldinger.md

1. Konsept

En mobil-first talefeature med tre moduser som dekker spekteret fra kjappe chatmeldinger til langt feltopptak. Grunnprinsippet er det samme: du snakker inn i telefonen, og systemet gjør noe nyttig med det. Forskjellen er hva som er output.

Modus Typisk lengde Output Master-format Lagring
Voice-to-text <30 sek Rå transkripsjon i meldingsfeltet Tekst Ingen (lyden kastes)
Lydmelding <10 min Lydfil + transkripsjon for søk Lyd media_file + node i grafen
Diktering 130 min AI-ryddet tekst (strukturert notat) Tekst Node i grafen

Voice-to-text er en del av chat-featuren (se docs/features/chat.md, seksjon 8). Denne specen dekker de to tyngre modusene.

2. Lydmelding-modus

2.1 Brukerflyt

  1. Bruker åpner lydmelding-modus (via FAB-knapp, hurtigtast eller fra en channel).
  2. Trykker record. Nettleseren fanger lyd via MediaRecorder API (WebM/Opus).
  3. Kan valgfritt velge kontekst: et Tema, en Aktør, eller "Usortert".
  4. Ved stopp lastes lydfilen opp til SvelteKit (streaming for store filer).
  5. Filen lagres som media_file i mediamappen (/srv/synops/media/voice/).
  6. En whisper_transcribe-jobb opprettes i jobbkøen for å gjøre opptaket søkbart.
  7. Transkripsjonen lagres som metadata på noden — lydfilen forblir master.

2.2 Datamodell

Lydmeldingen er en node i Kunnskapsgrafen (node_type = 'melding', message_type = 'voice_memo'):

nodes (node_type = 'melding')
  → messages (channel_id, message_type = 'voice_memo', body = transkripsjon, metadata = { duration, transcription_status })
  → message_attachments → media_files (lydfilen)

Lydmeldinger kan:

  • Sendes i en channel (som vedlegg til en melding)
  • Leve fristående i en personlig "Innboks"-channel
  • Knyttes til Temaer/Aktører via graph_edges (manuelt eller AI-foreslått)

2.3 Triagering

Redaksjonen trenger en flate for å gå gjennom nye lydmeldinger:

  • Lytt, tagg med Temaer/Aktører
  • Marker for bruk i episode (kobles til Kanban/Kjøreplan)
  • Forkast / arkiver
  • Denne flaten er en filtrert visning av "Innboks"-channelen, ikke et eget system

2.4 Bruk i podcast

Lydmeldinger markert for bruk kan trekkes inn i Podcastfabrikkens pipeline. Lydfilen er allerede i media-mappen — den kan klippes inn i en episode direkte.

3. Dikteringsmodus

3.1 Brukerflyt

  1. Bruker åpner dikteringsmodus (mobil-first, men fungerer på desktop).
  2. Snakker fritt — kan være flere minutter. Visuell indikator viser at opptak pågår.
  3. Ved stopp opprettes to jobber i jobbkøen (sekvensielt):
    • whisper_transcribe — rå transkripsjon (medium + initial_prompt for kvalitet)
    • dictation_cleanup — AI rydder i teksten
  4. Brukeren ser resultatet: rå transkripsjon og AI-ryddet versjon side om side.
  5. Kan redigere den ryddede versjonen før lagring.
  6. Lagres som et notat (node i grafen). Lydfilen slettes etter vellykket transkripsjon.

3.2 AI-opprydding (dictation_cleanup)

AI Gateway (sidelinja/rutine) prosesserer transkripsjonen med instruksjon om å:

  • Fjerne fyllord, gjentakelser og ufullstendige setninger
  • Strukturere i avsnitt med overskrifter der det gir mening
  • Bevare talerens mening og tone — ikke omskrive til "AI-språk"
  • Foreslå #Tema- og @Aktør-tags basert på innholdet

3.3 Datamodell

Dikterte notater er meldinger i en channel:

nodes (node_type = 'melding')
  → messages (channel_id, message_type = 'text', body = ryddet tekst, metadata = { raw_transcript, source: 'dictation' })

Metadata bevarer rå-transkripsjonen slik at brukeren alltid kan se hva som faktisk ble sagt.

3.4 Målkanal

Brukeren velger hvor notatet havner:

  • Personlig notat-channel — default, kun synlig for brukeren selv
  • Tema-channel — delt med redaksjonen som et innspill
  • Direkte til en annen bruker — som en asynkron "talemelding i tekstform"

4. Felles infrastruktur

4.1 Opptak (klient)

Begge moduser bruker samme opptakskomponent i SvelteKit:

  • MediaRecorder API med WebM/Opus
  • Visuell feedback (lydnivå-indikator, varighet)
  • Modus-velger: Lydmelding / Diktering
  • Kontekst-velger: Tema, Aktør, eller Usortert

4.2 Opplasting

SvelteKit håndterer filopplasting strømmende. For korte klipp (<2 min) kan opplasting starte umiddelbart etter stopp. For lengre opptak bør det vises en fremdriftsindikator.

4.3 Whisper

Begge moduser bruker live transkripsjonspipelinen (se docs/features/live_transkripsjon.md) i batch-modus via jobbkøen. Modellvalg:

  • Lydmelding: small (rask, transkripsjonen er sekundær — lyden er master)
  • Diktering: medium + initial_prompt (kvalitet prioritert — teksten er master)

4.4 Personlig "Innboks"-channel

Ved brukeropprettelse opprettes en privat channel per bruker for usorterte lydmeldinger og notater. Config:

{
  "threads": false,
  "mentions": false,
  "attachments": true,
  "research_clips": false,
  "ttl_days": null
}

5. Dataklassifisering (ref. docs/arkitektur.md 2.2)

Data Kategori Detaljer
Lydfiler (voice memos) Kritisk (backup) Unikt råmateriale — lyden er innholdet, kan brukes direkte i podcasten
Diktert tekst (ryddet) Kritisk (PG) Brukerens innhold
Rå transkripsjon Avledet Kan regenereres fra lydfil
Lydfil fra diktering Flyktig (TTL) Lyden er kun et transportformat for teksten — slettes etter at brukeren har godkjent den ryddede teksten. Spart diskplass, og unngår å lagre halvformulerte tanker som lyd.

6. Jobbtyper

Jobbtype Modellalias Beskrivelse
whisper_transcribe Eksisterende jobbtype, gjenbrukes
dictation_cleanup sidelinja/rutine AI-opprydding av transkripsjon

7. Instruks for Claude Code

  • Opptakskomponenten skal være en gjenbrukbar Svelte-komponent med modus-prop (voice_memo / dictation).
  • Lydfiler lagres i media/voice/ — aldri i databasen.
  • Diktering: slett lydfilen først etter at brukeren har godkjent den ryddede teksten.
  • voice_memo er en ny message_type — utvid enum i migrasjonen.
  • Personlig innboks-channel opprettes automatisk for nye brukere.
  • Tilgang styres via node_access-matrisen.