Podcast render pipeline v2 — 2026-10-15 (Eva)
Podcast render pipeline v2 — 2026-10-15 (Eva)
What changed and why
The renderer (/home/ubuntu/pulse-site/scripts/render_podcast.py) now produces
human-paced audio instead of machine-gun delivery. Three generations:
- v0 (original): whole-section TTS + 0.8s silence pads,
-c copyconcat. Worked while scripts were short, but delivery was flat. - v1 (14 Oct evening, BROKEN): stuffed
...into text for pauses + added a 2s fade withafade=t=out:st=0. Two bugs: Edge reads...as a multi-second hole, andst=0fades out from second zero — the 15 Oct episode was "good morning then silent" (Whisper: 21 chars). Backups kept on prod:render_podcast.py.bak-20261014,.bak-20261014-pauses,.bak-20261014-v1pauses. - v2 (15 Oct, VERIFIED): the recipe below. 15 Oct re-rendered: 800 chars by
Whisper, full brief, interjection audible. Backup:
render_podcast.py.bak-20261015-concatfade.
The v2 recipe (all in render_podcast.py on prod)
- Punctuation stays as written.
add_breaths()only collapses accidents (...→.,,,→,, whitespace→single space). Commas = Edge's natural SHORT pause; full stops keep their mark. - LONG pauses come from structure: each sentence renders as its own TTS call, with 250ms of generated silence glued between sentences in a section.
- Breathe room: 1.8s of silence between thematic sections (Young's 1.5–2s rule). Last section flows straight into the fade — no pad.
- Graceful stop: 2.5s fade-out starting at
(duration − 2.5s), computed via ffprobe at render time. NEVER hardcodest=0. - Co-host pacing:
Yeah,/Right,/Hmm,auto-inserted before contrast turns (But/And/So/Now/Looking/Still/Meanwhile), never inside number reads. - Concat-safe audio: silence clips at 24kHz mono (Edge outputs 24kHz);
concat re-encodes (
-ar 24000 -ac 1 -acodec libmp3lame), never-c copy.
Verify every render (no exceptions)
- Duration sane:
ffprobe -show_entries format=duration(≈60–75s for ~1100 chars). - Loudness trace:
ffmpeg -af ebur128=peak=true -f null— speech must appear past the 5s, 30s, 60s marks, not just the first second. - Whisper transcription of the MP3 must return the full brief (700+ chars for a morning show). "Good morning" + fragments = silent-file bug, do NOT publish.
- Publish by overwriting
public/podcast/episode-<DATE>-<show>.mp3; keep the broken file as.bak-broken-<reason>for before/after.
Voice
Natasha (en-AU-NatashaNeural), +25% rate. ONE VOICE rule: chat TTS and podcast
share it. edge-tts must be ≥7.3.0 on the cron PM venv AND prod (see skill
edge-tts-403-recovery); older versions 403 on the Microsoft handshake.
Provenance
- Skill:
devops/podcast-render-quality(operator procedure, loads on symptom). - Pipeline reference:
pulse-site-ops→references/podcast-render-pipeline.md. - Cron jobs:
0c33d1a9c94a(7am),437b22df5daf(4pm),f5158977f6ec(Fri 5pm). - 15 Oct fixed episode verified 800 chars; broken original kept on prod as
episode-2026-10-15-am.mp3.bak-broken-fade.
Market Pulse Brief by Eva — Episode 1
Voice: Natasha (as Eva) Duration: ~5 min Format: Daily podcast script — CommSecTV-style warm briefing (Young 2026-08-13: more human, attract listeners) Style notes: warm open, direct address, contractions, plain numbers, natural transitions, human sign-off. No jargon, no lecturing.
TTS Formatting Rules — Podcast Lane (Compliance)
Owner: Eva (podcast lane). Set as card t_dc7f9b0e, 2026-10-21.Authoritative sources (ground truth for every rule below):

