- Fix TTS text pipeline: new caps handling (spell out unknown acronyms, lowercase
emphasis words), action-word lookahead for parenthetical stripping, abbreviation
expansions (US→United States, NM→New Mexico), pronunciation fixes
- Inworld TTS: camelCase API fields, speakingRate per-voice overrides, retry logic
with exponential backoff (3 attempts)
- Footer redesign: SVG icons for social/podcast links across all pages
- Stats page: show "Rate us on Spotify" instead of "not public" placeholder
- New voices, expanded caller prompts and problem scenarios
- Social posting via Postiz, YouTube upload in publish pipeline
- Episode transcripts 15-25, terms page, sitemap updates
- Fix invoice script: match Timing totals using merged Task+App intervals
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- On-air toggle uploads status.json to BunnyCDN + purges cache, website
polls it every 15s to show live ON AIR / OFF AIR badge
- Publish script downloads Castopod's copy of audio for CDN upload
(byte-exact match), removes broken slug fallback, syncs all episode
media to CDN after publishing
- Fix f-string syntax error in publish_episode.py (Python <3.12)
- Enable CORS on BunnyCDN pull zone for json files
- CDN URLs for website OG images, stem recorder bug fixes, LLM token
budget tweaks, session context in CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New stem recording system captures 5 time-aligned WAV files (host, caller,
music, sfx, ads) during live shows. Standalone postprod.py processes stems
into broadcast-ready MP3 with gap removal, voice compression, music ducking,
and EBU R128 loudness normalization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Primary model gets 15s, then auto-falls back through gemini-flash,
gpt-4o-mini, llama-3.1-8b (10s each)
- Always returns a response — canned in-character line as last resort
- Reuse httpx client instead of creating new one per request
- Remove asyncio.timeout wrappers that were killing requests before
the LLM service could try fallbacks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 30s timeout to all frontend fetch calls (safeFetch)
- Add 20s asyncio.timeout around lock+LLM in chat, ai-respond, auto-respond
- Reduce OpenRouter timeout from 60s to 25s
- Reduce Inworld TTS timeout from 60s to 25s
- Return graceful fallback responses on timeout instead of hanging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove gpt-4o-realtime (WebSocket-only) from OpenRouter models
- Increase OpenRouter timeout to 60s and max_tokens to 150
- Handle empty LLM responses
- Fix publish_episode.py for current Castopod API fields
- Add port conflict check and graceful shutdown to run.sh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace aggressive sentence-count limiting with ensure_complete_thought()
which only trims if the LLM was actually cut off mid-sentence
- Softer prompt guidance for natural brevity instead of rigid sentence count
- max_tokens at 100 as natural length cap
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- max_tokens back to 150 so LLM can finish thoughts
- New limit_sentences() keeps only first 2 complete sentences
- Never cuts mid-sentence — always ends at punctuation
- Applied to both chat and auto-respond paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reduce max_tokens from 100 to 75 for shorter output
- Add truncate_to_complete_sentence() to trim at last punctuation
- Applied to both chat and auto-respond paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Much stronger prompt language: "no more than 2 sentences EVER"
- Added "DO NOT ramble" instruction
- Reduced max_tokens back to 100 as hard limit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Increase max_tokens from 100 to 150 to avoid mid-sentence truncation
- Tighten prompt to 1-2 short sentences with emphasis on completing them
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>