🔀

AI Podcast Production Pipeline

Medium5 tools

Automated podcast creation from topic ideas to published episodes with show notes.

ClaudeElevenLabsSuno AIFFmpegSpotify for Podcasters API

Workflow Steps

  1. 1

    Script Writer Agent creates engaging podcast scripts with multiple hosts

  2. 2

    Voice Generation Agent produces natural-sounding dialogue

  3. 3

    Music Generation Agent creates intro/outro music

  4. 4

    Audio Assembly Agent mixes dialogue, music, and effects

  5. 5

    Show Notes Writer Agent creates episode descriptions and timestamps

  6. 6

    Publisher Agent uploads to podcast platforms

Download

Documentation

AI Podcast Production Pipeline

Overview

An automated workflow for producing full podcast episodes from topic ideas or articles. This pipeline handles script writing, voice generation, intro/outro music, episode assembly, and publishing — enabling creators to produce professional podcasts without recording equipment or editing skills.

The workflow is optimized for solo podcasters, content repurposing, and high-frequency publishing. It can transform blog posts, articles, or raw ideas into complete podcast episodes in under an hour.

Difficulty

Medium — Requires coordination of several AI tools but each step is well-documented.

Tools Required

ToolPurpose
Claude / GPT-4Script writing and show notes
ElevenLabsNatural voice generation
Suno / UdioAI music generation for intro/outro
FFmpegAudio assembly and mixing
Spotify for Podcasters APIPublishing to podcast platforms
WhisperOptional: transcribe existing audio

Workflow Steps

Step 1: Script Generation

import anthropic

client = anthropic.Anthropic()

def generate_podcast_script(topic: str, style: str = "conversational") -> dict:
    """Generate a complete podcast script with intro, segments, and outro."""
    response = client.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=4000,
        messages=[
            {"role": "user", "content": f"""Create a podcast script about: {topic}

Style: {style}
Duration: ~15-20 minutes

Structure:
1. INTRO (30 seconds) - Hook the listener, introduce the topic
2. SEGMENT 1 (5 min) - Deep dive into the first aspect
3. SEGMENT 2 (5 min) - Second aspect with examples
4. SEGMENT 3 (5 min) - Practical takeaways and tips
5. OUTRO (30 seconds) - Summary, call to action, teaser for next episode

Include:
- Natural conversational dialogue (as if two hosts are chatting)
- Smooth transitions between segments
- Engaging hooks and cliffhangers
- Clear call to action at the end
- Timestamp markers for each segment

Format each section as:
[SEGMENT: name]
[HOST_A]: dialogue
[HOST_B]: dialogue
[TRANSITION]: brief bridge text"""}
        ]
    )
    
    # Parse into structured format
    script = parse_script(response.content[0].text)
    return script

def parse_script(raw_script: str) -> dict:
    """Parse raw script into structured segments."""
    import re
    
    segments = {}
    current_segment = None
    
    for line in raw_script.split("\n"):
        segment_match = re.match(r'\[SEGMENT: (.+?)\]', line)
        if segment_match:
            current_segment = segment_match.group(1)
            segments[current_segment] = []
        elif current_segment:
            segments[current_segment].append(line)
    
    return segments

Step 2: Voice Generation

def generate_podcast_audio(script: dict, host_a_voice: str, host_b_voice: str) -> list[dict]:
    """Generate audio for each segment with different voices."""
    import requests
    
    audio_segments = []
    
    for segment_name, lines in script.items():
        for line in lines:
            if line.startswith("[HOST_A]:"):
                text = line.replace("[HOST_A]:", "").strip()
                audio = generate_voice(text, host_a_voice)
                audio_segments.append({
                    "segment": segment_name,
                    "speaker": "HOST_A",
                    "audio": audio,
                    "duration": estimate_duration(text)
                })
            elif line.startswith("[HOST_B]:"):
                text = line.replace("[HOST_B]:", "").strip()
                audio = generate_voice(text, host_b_voice)
                audio_segments.append({
                    "segment": segment_name,
                    "speaker": "HOST_B",
                    "audio": audio,
                    "duration": estimate_duration(text)
                })
    
    return audio_segments

def generate_voice(text: str, voice_id: str) -> bytes:
    """Generate voice audio using ElevenLabs."""
    url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"
    
    response = requests.post(url, json={
        "text": text,
        "model_id": "eleven_multilingual_v2",
        "voice_settings": {
            "stability": 0.4,
            "similarity_boost": 0.8,
            "style_exaggeration": 0.3
        }
    }, headers={
        "xi-api-key": "YOUR_ELEVENLABS_API_KEY"
    })
    
    return response.content

def estimate_duration(text: str) -> float:
    """Estimate audio duration based on word count."""
    words = len(text.split())
    return words / 2.5  # ~150 words per minute

Step 3: Music Generation

def generate_podcast_music(style: str = "upbeat", duration: int = 30) -> bytes:
    """Generate intro/outro music using Suno or Udio."""
    
    # Using Suno API
    response = requests.post(
        "https://api.suno.ai/v1/generate",
        headers={"Authorization": f"Bearer {SUNO_API_KEY}"},
        json={
            "prompt": f"Upbeat podcast intro music, professional, {duration} seconds, no vocals",
            "style": style,
            "duration": duration
        }
    )
    
    music_url = response.json()["audio_url"]
    return requests.get(music_url).content

Step 4: Audio Assembly

import subprocess

def assemble_podcast(audio_segments: list, intro_music: bytes, outro_music: bytes, output_path: str):
    """Assemble the complete podcast episode."""
    
    # Save all audio segments
    temp_files = []
    
    # Intro music
    with open("intro.mp3", "wb") as f:
        f.write(intro_music)
    temp_files.append("intro.mp3")
    
    # Silence after intro (2 seconds)
    subprocess.run(["ffmpeg", "-y", "-f", "lavfi", "-i", "anullsrc=r=48000:cl=stereo",
                    "-t", "2", "-c:a", "libmp3lame", "silence.mp3"])
    temp_files.append("silence.mp3")
    
    # Audio segments
    for i, seg in enumerate(audio_segments):
        path = f"seg_{i}.mp3"
        with open(path, "wb") as f:
            f.write(seg["audio"])
        temp_files.append(path)
        
        # Add brief pause between speakers
        if i < len(audio_segments) - 1:
            subprocess.run(["ffmpeg", "-y", "-f", "lavfi", "-i", "anullsrc=r=48000:cl=stereo",
                            "-t", "0.5", "-c:a", "libmp3lame", f"pause_{i}.mp3"])
            temp_files.append(f"pause_{i}.mp3")
    
    # Outro music
    with open("outro.mp3", "wb") as f:
        f.write(outro_music)
    temp_files.append("outro.mp3")
    
    # Create concat list
    with open("concat.txt", "w") as f:
        for tf in temp_files:
            f.write(f"file '{tf}'\n")
    
    # Assemble
    subprocess.run([
        "ffmpeg", "-y", "-f", "concat", "-safe", "0",
        "-i", "concat.txt",
        "-c:a", "libmp3lame", "-b:a", "192k",
        output_path
    ], check=True)
    
    return output_path

Step 5: Generate Show Notes

def generate_show_notes(script: dict, topic: str) -> str:
    """Generate podcast show notes with timestamps and links."""
    import anthropic
    
    client = anthropic.Anthropic()
    
    response = client.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=2000,
        messages=[{
            "role": "user",
            "content": f"""Generate podcast show notes for episode about: {topic}

Script segments:
{script}

Include:
- Episode title (catchy, under 60 characters)
- Brief description (2-3 sentences)
- Timestamped chapter markers
- Key takeaways (bullet points)
- Links to resources mentioned
- Call to action for listeners
- Tags for SEO

Format for podcast hosting platforms."""}
        ]
    )
    
    return response.content[0].text

Step 6: Publish

def publish_podcast(audio_path: str, show_notes: str, title: str):
    """Publish to Spotify for Podcasters (formerly Anchor)."""
    
    # Upload episode
    response = requests.post(
        "https://api.spotify.com/v1/podcast-episodes",
        headers={
            "Authorization": f"Bearer {SPOTIFY_ACCESS_TOKEN}",
            "Content-Type": "multipart/form-data"
        },
        files={"audio": open(audio_path, "rb")},
        data={
            "title": title,
            "description": show_notes,
            "language": "en",
            "is_explicit": "false"
        }
    )
    
    episode_url = response.json()["external_urls"]["spotify"]
    return episode_url

Example Usage

def create_podcast_episode(topic: str, output_file: str = "episode.mp3"):
    # Step 1: Generate script
    script = generate_podcast_script(topic, style="conversational")
    print(f"Generated script for: {topic}")
    
    # Step 2: Generate audio
    audio_segments = generate_podcast_audio(
        script,
        host_a_voice="Rachel",  # Female voice
        host_b_voice="Adam"     # Male voice
    )
    print(f"Generated {len(audio_segments)} audio segments")
    
    # Step 3: Generate music
    intro_music = generate_podcast_music(style="upbeat", duration=15)
    outro_music = generate_podcast_music(style="upbeat", duration=10)
    
    # Step 4: Assemble
    assemble_podcast(audio_segments, intro_music, outro_music, output_file)
    print(f"Podcast saved to {output_file}")
    
    # Step 5: Generate show notes
    show_notes = generate_show_notes(script, topic)
    print(f"Show notes:\n{show_notes}")
    
    # Step 6: Publish (optional)
    # episode_url = publish_podcast(output_file, show_notes, f"AI Podcast: {topic}")
    
    return output_file

# Run it
create_podcast_episode("The Rise of AI Agents in 2026")

Pros

  • ✅ Produces professional-quality podcasts without recording
  • ✅ Consistent voice and quality across episodes
  • ✅ Fast production (under 1 hour per episode)
  • ✅ Supports multiple languages and voices
  • ✅ Easy to scale for high-frequency publishing
  • ✅ Repurposes written content into audio

Cons

  • ❌ AI voices still lack true human nuance
  • ❌ Music generation quality varies
  • ❌ Multiple API costs
  • ❌ Limited emotional range in voices
  • ❌ No spontaneous conversation feel
  • ❌ Requires good script writing

When to Use

  • Content repurposing — Turn blog posts into podcasts
  • High-frequency publishing — Daily or weekly episodes
  • Multilingual podcasts — Same content in multiple languages
  • Educational content — Course lectures, tutorials
  • News podcasts — Daily briefings, industry updates
  • Accessibility — Audio version of written content

Resources