server/docs/features/lydmeldinger.md
vegard 82ee710b47 Flytt ARCHITECTURE.md til docs/, CLAUDE.md som eneste startdokument
- ARCHITECTURE.md → docs/arkitektur.md
- CLAUDE.md: ny arbeidsflyt-seksjon (commit/push fritt, deploy krever ok)
- CLAUDE.md: dokumentasjonstre med alle docs/-referanser
- Alle interne referanser oppdatert (6 filer)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 15:50:49 +01:00

137 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 | 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 workspace-mappen (`/srv/sidelinja/media/{workspace_slug}/voice/`).
6. En `whisper_transcribe`-jobb opprettes i jobbkøen for å gjøre opptaket søkbart.
7. Transkripsjonen lagres som metadata noden lydfilen forblir master.
### 2.2 Datamodell
Lydmeldingen er en node i Kunnskapsgrafen (`node_type = 'melding'`, `message_type = 'voice_memo'`):
```
nodes (workspace_id, 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 å 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 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` transkripsjon (`medium` + `initial_prompt` for kvalitet)
- `dictation_cleanup` AI rydder i teksten
4. Brukeren ser resultatet: 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 innholdet
### 3.3 Datamodell
Dikterte notater er meldinger i en channel:
```
nodes (workspace_id, 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 workspace-opprettelse opprettes en privat channel per bruker for usorterte lydmeldinger og notater. Config:
```json
{
"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 |
| 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/{workspace_slug}/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 ved workspace-medlemskap (som del av `workspace_members`-inserten).
* Alt er workspace-scopet.