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
| Source | What it discusses |
|---|---|
| Topic | A subject the host raises. |
| Paste text | Any material you paste — NotebookLM-style. |
| URL | A web page (fetched SSRF-guarded, readable-text extracted). |
| Journal entry | Your own entry — the guest reflects on their own words. |
| Story / season | A 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/addaccepts 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
- Script —
services/podcast-discussion.ts:generateDiscussionScript(source, opts)(claude-sonnet-4-6, JSON). Pure, golden-testedparseDiscussionScriptnormalizes the LLM output (speaker coercion, alternating fallback, empty-drop, clamps). - Audio —
renderDiscussionAudiorenders each line viattsSegment, stitches withconcatMp3Buffers, stores viauploadAudio(season-assets). All reused fromseason-audio.ts. - URL extraction —
fetchReadableText/extractReadableTextinlink-preview.ts(reuses the hardened SSRF-guarded fetch). - Routes —
routes/podcast-discussion.ts:POST /api/podcast-discussion/script(cheap) +POST /api/podcast-discussion/render(spends ElevenLabs; gated onELEVENLABS_API_KEY→ 503). Both creator-gated (requireCreator). - Voice cloning —
services/lovio-voice.tscreateVoiceClone(takes asamples[]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).