33 lines
No EOL
3.5 KiB
Markdown
33 lines
No EOL
3.5 KiB
Markdown
# Feature Spec: Podcastfabrikken (Lyd & Publiserings-Pipeline)
|
|
**Filsti:** `docs/features/podcastfabrikken.md`
|
|
|
|
## 1. Konsept
|
|
Den automatiserte "samlebåndet" som tar over når en ferdigklippet episode er klar, samt verktøyet for å **oppdatere eksisterende episoder** (f.eks. en rullerende intro-episode). Målet er at maskinen gjør 90 % av grovarbeidet (transkripsjon, metadata, kapittelinndeling), men at redaksjonen alltid kan overstyre resultatet manuelt før publisering.
|
|
|
|
## 2. Arkitektur & Dataflyt
|
|
Dette er en asynkron arbeidsflyt som kombinerer filsystem, AI, databaser og CI/CD.
|
|
|
|
1. **Trigger (Opplasting/Oppdatering):** Brukeren laster opp en `.mp3`-fil via SvelteKit-grensesnittet. Dette rutes enten som en *ny* episode (`INSERT`), eller en *oppdatering* av en eksisterende (`UPDATE`).
|
|
2. **Kø-system (PostgreSQL jobbkø):** Siden lydprosessering tar tid (CPU-intensivt), legges oppgaven i den felles jobbkøen (se `docs/features/jobbkø.md`). Opplastingen oppretter to jobber i sekvens: først `whisper_transcribe`, deretter `openrouter_analyze` (som trigges automatisk ved fullført transkripsjon).
|
|
3. **Transkripsjon (faster-whisper):** Rust-worker trigger `faster-whisper` lokalt på serveren og genererer rå tekst med tidsstempler.
|
|
4. **AI-Analyse (OpenRouter):** Transkripsjonen sendes til OpenRouter (Claude-modell) for uttrekk av forslag til tittel, sammendrag, show notes og kapittler.
|
|
5. **Manuell Godkjenning & Fletting (SvelteKit):**
|
|
* *For nye episoder:* Presenteres som et ferskt utkast.
|
|
* *For oppdateringer:* Viser AI-ens nye forslag side-om-side med eksisterende metadata. Redaksjonen kan da velge hva som skal beholdes eller flettes (merge).
|
|
6. **Publisering (PostgreSQL):** Ved "Godkjenn" lagres metadataene permanent i databasen.
|
|
7. **RSS-Generering:** SvelteKit-appen genererer en oppdatert `/feed.xml`.
|
|
|
|
## 3. Spesialhåndtering: Oppdatering av eksisterende episoder (Cache-busting)
|
|
Podcast-apper (Apple, Spotify) og CDN-er cacher innhold aggressivt. For at en endring i f.eks. "Introepisoden" skal slå gjennom hos lytterne, MÅ følgende tekniske regler følges:
|
|
|
|
* **Filnavn-versjonering (Viktigst!):** Den nye lydfilen skal *aldri* overskrive det gamle filnavnet på disken. Systemet må legge til en hash, UUID eller et tidsstempel (f.eks. `intro_v2_1710289000.mp3`). Dette tvinger appene til å laste ned filen på nytt.
|
|
* **RSS `<guid>` (Global Unique Identifier):** Denne taggen MÅ forbli 100% statisk/uendret fra originalepisoden. Den forteller appene at "Dette er fortsatt samme episode, ikke lag en duplikat".
|
|
* **RSS `<enclosure>`:** URL-en i `enclosure`-taggen (som peker på `.mp3`-filen) oppdateres i databasen til å reflektere det *nye* filnavnet.
|
|
* **RSS `<pubDate>`:** SvelteKit-grensesnittet skal gi redaksjonen en toggle-knapp ved oppdatering:
|
|
* Alternativ A: "Behold opprinnelig dato" (Episoden oppdateres i det stille for nye lyttere).
|
|
* Alternativ B: "Sett dato til NÅ" (Episoden spretter til toppen av feeden som en ny utgivelse).
|
|
|
|
## 4. Instruks for Claude Code
|
|
* **Lydfiler:** Håndter filopplasting i SvelteKit strømmende (streaming) for filer >100MB for å unngå minne-lekkasjer.
|
|
* **Feilhåndtering:** Hvis OpenRouter timer ut eller Whisper feiler, må oppgaven flagges med status `error` i databasen slik at brukeren kan trigge jobben på nytt manuelt via UI.
|
|
* **Opprydding (Disk):** Når en fil oppdateres vellykket, skal den gamle/foreldede `.mp3`-filen enten slettes fra Hetzner-serveren automatisk, eller flyttes til en `/archive/`-mappe basert på en miljøvariabel. |