product

Podcast discussions

Turn a topic — or your own writing — into a two-person podcast conversation, and render it to audio in your own voice.

Status: shipped, creator-facing. Both the discussion generator and voice cloning are available to creators (requireCreator = super_admin OR is_creator); audio render is bounded per creator by the TTS quota.


What it does

You give it a source; an LLM writes a natural back-and-forth between a HOST (a warm AI co-host) and a GUEST (you); it optionally renders the script to a single MP3 — host voice + your cloned voice.

Console: /dashboard/podcast (creator-gated).

Sources

SourceWhat it discusses
TopicA subject the host raises.
Paste textAny material you paste — NotebookLM-style.
URLA web page (fetched SSRF-guarded, readable-text extracted).
Journal entryYour own entry — the guest reflects on their own words.
Story / seasonA story's premise + setting + genre.

Your voice

The guest voice is your ElevenLabs clone, trained once at /dashboard/lovio/voice-setup (the same clone that reads Lovio capsules). Two tiers:

  • Quick — one 60-second reading. Instant.
  • Studio — upload several minutes of clean audio (multiple files). Still instant (ElevenLabs voices/add accepts many files), noticeably richer.

Guest-voice resolution in the render path: explicit override → the caller's own Lovio clone → PODCAST_GUEST_VOICE_ID env → a stock stand-in. So once you've recorded a clone, discussions are in your voice with zero config. Host default is Matilda / PODCAST_HOST_VOICE_ID.

A full read-aloud recording script lives in the "voice-training-script" Artifact.


How it's built

  • Scriptservices/podcast-discussion.ts: generateDiscussionScript(source, opts) (claude-sonnet-4-6, JSON). Pure, golden-tested parseDiscussionScript normalizes the LLM output (speaker coercion, alternating fallback, empty-drop, clamps).
  • AudiorenderDiscussionAudio renders each line via ttsSegment, stitches with concatMp3Buffers, stores via uploadAudio (season-assets). All reused from season-audio.ts.
  • URL extractionfetchReadableText / extractReadableText in link-preview.ts (reuses the hardened SSRF-guarded fetch).
  • Routesroutes/podcast-discussion.ts: POST /api/podcast-discussion/script (cheap) + POST /api/podcast-discussion/render (spends ElevenLabs; gated on ELEVENLABS_API_KEY → 503). Both creator-gated (requireCreator).
  • Voice cloningservices/lovio-voice.ts createVoiceClone (takes a samples[] array) + /api/lovio/voice/setup.

Env

ELEVENLABS_API_KEY (required to render). Optional: PODCAST_GUEST_VOICE_ID, PODCAST_HOST_VOICE_ID.


Deferred (product_tasks)

  • True async Professional Voice Cloning (/v1/voices/pvc, trained over hours) — only if the Studio clone isn't enough.
  • A public / creator-facing surface (currently super-admin only).
PODCAST DISCUSSIONS — Docs | HiveJournal