- Omorganiser docs/: konsepter, features, infra og proposals i egne mapper - Ny docs/erfaringer/ med lærdommer fra chat-implementering (Svelte 5, SpacetimeDB, adapter-mønster) - Oppdater ARCHITECTURE.md: Lag 1 status, ny §10 Erfaringslogg, SpacetimeDB i lokal dev - Oppdater synkronisering.md med implementeringsstatus og designvalg - Oppdater lokal.md med SpacetimeDB og AI Gateway - Utvid PG-skjema med channels, messages, media_files, message_revisions - Legg til seed_dev.sql, migration_safety.md, .env.example - Nye feature-specs: chat, kanban, whiteboard, live_ai, lydmeldinger m.fl. - Nye konsept-specs: studioet, møterommet, redaksjonen, den asynkrone gjesten m.fl. - SpacetimeDB og AI Gateway i docker-compose.dev.yml - collect-docs.sh inkluderer erfaringer/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
137 lines
6.4 KiB
Markdown
137 lines
6.4 KiB
Markdown
# 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** | 1–30 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 på 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 å 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 (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. ARCHITECTURE.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/{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.
|