- Multi-provider TTS service (OpenAI, Piper, macOS say) - Supabase Storage integration for audio files - RSS 2.0 feed with iTunes extensions for podcast distribution - Web audio player at /podcast page - Integration with daily digest workflow - Manual TTS generation script - Complete documentation in PODCAST_SETUP.md
8.4 KiB
Podcast Setup Guide
This guide covers setting up and using the podcast feature for the Daily Digest blog.
Overview
The podcast feature automatically converts Daily Digest blog posts into audio format using Text-to-Speech (TTS) and provides:
- 🎧 Web Player - Listen directly on the blog
- 📱 RSS Feed - Subscribe in any podcast app (Apple Podcasts, Spotify, etc.)
- 🔄 Auto-generation - TTS runs automatically when new posts are created
- 💾 Audio Storage - Files stored in Supabase Storage (free tier)
Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Daily │────▶│ TTS API │────▶│ Supabase │
│ Digest │ │ (OpenAI/ │ │ Storage │
│ Post │ │ Piper) │ │ │
└─────────────┘ └─────────────┘ └──────┬──────┘
│
▼
┌─────────────┐
│ RSS Feed │
│ (/api/ │
│ podcast/ │
│ rss) │
└──────┬──────┘
│
▼
┌─────────────┐
│ Podcast │
│ Apps │
│ (Apple, │
│ Spotify) │
└─────────────┘
Quick Start
1. Configure Environment Variables
Add to your .env.local and .env.production:
# Enable TTS generation
ENABLE_TTS=true
# Choose TTS Provider: "openai" (paid, best quality) or "macsay" (free, macOS only)
TTS_PROVIDER=openai
# For OpenAI TTS (recommended)
OPENAI_API_KEY=sk-your-key-here
TTS_VOICE=alloy # Options: alloy, echo, fable, onyx, nova, shimmer
2. Update Database Schema
Run this SQL in your Supabase SQL Editor to add audio columns:
-- Add audio URL column
ALTER TABLE blog_messages
ADD COLUMN IF NOT EXISTS audio_url TEXT;
-- Add audio duration column
ALTER TABLE blog_messages
ADD COLUMN IF NOT EXISTS audio_duration INTEGER;
-- Create index for faster RSS feed queries
CREATE INDEX IF NOT EXISTS idx_blog_messages_audio
ON blog_messages(audio_url)
WHERE audio_url IS NOT NULL;
3. Create Supabase Storage Bucket
The app will automatically create the podcast-audio bucket on first use, or you can create it manually:
- Go to Supabase Dashboard → Storage
- Click "New Bucket"
- Name:
podcast-audio - Check "Public bucket"
- Click "Create"
4. Deploy
npm run build
vercel --prod
5. Subscribe to the Podcast
The RSS feed is available at:
https://blog-backup-two.vercel.app/api/podcast/rss
Apple Podcasts:
- Open Podcasts app
- Tap Library → Edit → Add a Show by URL
- Paste the RSS URL
Spotify:
- Go to Spotify for Podcasters
- Submit RSS feed
Other Apps: Just paste the RSS URL into any podcast app.
TTS Providers
Option 1: OpenAI TTS (Recommended)
Cost: ~$2-4/month for daily 5-minute episodes
Pros:
- Excellent voice quality
- Multiple voices available
- Simple API integration
- Fast processing
Cons:
- Paid service
- Requires API key
Setup:
TTS_PROVIDER=openai
OPENAI_API_KEY=sk-your-key-here
TTS_VOICE=alloy # or echo, fable, onyx, nova, shimmer
Option 2: macOS say Command (Free)
Cost: $0
Pros:
- Free, built into macOS
- No API key needed
- Works offline
Cons:
- Lower voice quality
- macOS only
- Limited to macOS deployment
Setup:
TTS_PROVIDER=macsay
TTS_VOICE=Samantha # or Alex, Victoria, etc.
Option 3: Piper TTS (Free, Local)
Cost: $0
Pros:
- Free and open source
- High quality neural voices
- Runs locally (privacy)
- No rate limits
Cons:
- Requires downloading voice models (~100MB)
- More complex setup
- Requires local execution
Setup:
-
Install Piper:
brew install piper-tts # or download from GitHub -
Download voice model:
mkdir -p models cd models wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/lessac/medium/en_US-lessac-medium.onnx wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/lessac/medium/en_US-lessac-medium.onnx.json -
Configure:
TTS_PROVIDER=piper PIPER_MODEL_PATH=./models/en_US-lessac-medium.onnx
Usage
Automatic Generation
When ENABLE_TTS=true, audio is automatically generated when a new digest is posted via the /api/digest endpoint.
Manual Generation
Generate audio for a specific post:
npm run generate-tts -- <post_id>
Generate audio for all posts missing audio:
npm run generate-tts:all
Force regeneration (overwrite existing):
npm run generate-tts -- <post_id> --force
API Endpoints
GET /api/podcast/rss
Returns the podcast RSS feed in XML format with iTunes extensions.
Headers:
Accept: application/xml
Response: RSS 2.0 XML feed
POST /api/digest (Updated)
Now accepts an optional generateAudio parameter:
{
"date": "2026-02-23",
"content": "# Daily Digest\n\nToday's news...",
"tags": ["daily-digest", "ai"],
"generateAudio": true // Optional, defaults to true
}
Database Schema
The blog_messages table now includes:
| Column | Type | Description |
|---|---|---|
audio_url |
TEXT | Public URL to the audio file in Supabase Storage |
audio_duration |
INTEGER | Estimated duration in seconds |
File Structure
src/
├── app/
│ ├── api/
│ │ ├── digest/route.ts # Updated with TTS trigger
│ │ └── podcast/
│ │ └── rss/route.ts # RSS feed endpoint
│ ├── podcast/
│ │ └── page.tsx # Podcast web player page
│ └── page.tsx # Updated with audio player
├── lib/
│ ├── tts.ts # TTS service abstraction
│ ├── storage.ts # Supabase storage helpers
│ └── podcast.ts # RSS generation utilities
└── scripts/
└── generate-tts.ts # Manual TTS generation script
Cost Analysis
OpenAI TTS (Daily Digest ~5 min)
- Characters per day: ~4,000
- Cost: $0.015 per 1,000 chars (tts-1)
- Monthly cost: ~$1.80
- HD voice (tts-1-hd): ~$3.60/month
Supabase Storage
- Free tier: 1 GB storage
- Audio files: ~5 MB per episode
- Monthly storage: ~150 MB (30 episodes)
- Well within free tier
Total Monthly Cost
- OpenAI TTS: ~$2-4/month
- Supabase Storage: $0 (free tier)
- RSS Hosting: $0 (Next.js API route)
- Total: ~$2-4/month
Troubleshooting
TTS not generating
- Check
ENABLE_TTS=truein environment variables - Check
TTS_PROVIDERis set correctly - For OpenAI: Verify
OPENAI_API_KEYis valid - Check Vercel logs for errors
Audio not playing
- Check Supabase Storage bucket is public
- Verify
audio_urlin database is not null - Check browser console for CORS errors
RSS feed not updating
- RSS is cached for 5 minutes (
max-age=300) - Check that posts have
audio_urlset - Verify RSS URL is accessible:
/api/podcast/rss
Future Enhancements
- Background job queue for TTS generation (using Inngest/Upstash)
- Voice selection per post
- Chapter markers in audio
- Transcript generation
- Podcast analytics