# How to Configure Episode and Speaker Profiles for Multi-Speaker Podcast Generation in Open Notebook

> Learn to configure Episode and Speaker Profiles in Open Notebook for automated multi-speaker podcast generation via REST API. Create reusable podcast templates and voice definitions.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Open Notebook uses `EpisodeProfile` and `SpeakerProfile` models to declaratively configure reusable podcast templates and voice definitions, enabling fully automated multi-speaker audio generation through REST API endpoints.**

Open Notebook provides a structured approach to multi-speaker podcast generation through two complementary data models that separate episode configuration from voice characteristics. By defining reusable profiles in [`open_notebook/podcasts/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/models.py), you can create consistent podcast templates without hard-coding speaker details for each generation request. This architecture supports complex multi-speaker scenarios while maintaining clean separation between content structure and voice synthesis configuration.

## Understanding the Profile Architecture

### EpisodeProfile

The `EpisodeProfile` model acts as a reusable podcast template stored in [`open_notebook/podcasts/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/models.py). It contains the episode structure, language settings, and references to both the speaker configuration and the LLM models used for outline and transcript generation. According to the source code, validation ensures that `num_segments` falls between 3 and 20 (lines 82-86).

### SpeakerProfile

The `SpeakerProfile` model defines the voice cast for your episodes, supporting 1-4 speakers per profile. Each speaker requires a dictionary with mandatory keys: `name`, `voice_id`, `backstory`, and `personality`. The validator enforces both the speaker count limit and required field presence (lines 60-68). Profiles may also specify a shared TTS model via `voice_model` or legacy fields for backward compatibility.

## Creating Speaker Profiles via REST API

To define a multi-speaker setup, POST to the speaker profiles endpoint defined in [`api/routers/speaker_profiles.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/speaker_profiles.py). Each speaker needs distinct voice characteristics and backstory to drive personality-driven dialogue generation.

```python
import requests

profile = {
    "name": "TechTalk",
    "description": "Four-person tech round-table",
    "voice_model": "model://tts/openai/whisper-v2",
    "speakers": [
        {
            "name": "Host",
            "voice_id": "voice_01",
            "backstory": "Seasoned tech journalist",
            "personality": "Curious, friendly"
        },
        {
            "name": "Engineer",
            "voice_id": "voice_02",
            "backstory": "Senior software engineer",
            "personality": "Analytical, dry"
        },
        {
            "name": "Designer",
            "voice_id": "voice_03",
            "backstory": "UX designer with a flair for storytelling",
            "personality": "Creative, enthusiastic"
        },
        {
            "name": "Investor",
            "voice_id": "voice_04",
            "backstory": "Venture capitalist",
            "personality": "Strategic, confident"
        }
    ]
}

resp = requests.post("http://localhost:5055/speaker-profiles", json=profile)
print(resp.json())

```

The validator rejects any profile with fewer than 1 or more than 4 speakers, ensuring the generation system can manage dialogue complexity effectively.

## Defining Episode Profiles

Episode profiles link to speaker configurations and specify generation parameters. The `speaker_config` field references your speaker profile by name, while `outline_llm` and `transcript_llm` point to model record IDs that get resolved via `_resolve_model_config` during generation.

```python
episode = {
    "name": "AI Futures",
    "description": "Exploring upcoming AI trends",
    "speaker_config": "TechTalk",
    "outline_llm": "model://llm/openai/gpt-4o",
    "transcript_llm": "model://llm/openai/gpt-4o-mini",
    "language": "en-US",
    "default_briefing": "Discuss the impact of AI on society in 5 minutes.",
    "num_segments": 5
}

resp = requests.post("http://localhost:5055/episode-profiles", json=episode)
print(resp.json())

```

Episode profile endpoints live in [`api/routers/episode_profiles.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/episode_profiles.py). The `num_segments` value must be between 3 and 20, as enforced by the Pydantic validator in the model definition.

## Triggering Multi-Speaker Podcast Generation

When you trigger generation via [`api/routers/podcasts.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/podcasts.py), the backend orchestrates the resolution process before handing configurations to the podcast-creator library.

```python
payload = {
    "episode_name": "AI Futures – Episode 1",
    "episode_profile": "AI Futures"
}

resp = requests.post("http://localhost:5055/podcasts/generate", json=payload)
print(resp.json())

```

The generation pipeline executes four critical steps:

1. **Profile Retrieval**: Calls `EpisodeProfile.get_by_name` to load the template and `SpeakerProfile.get_by_name` to resolve the linked voice configuration.
2. **Model Resolution**: Invokes `resolve_outline_config` and `resolve_transcript_config` to convert stored model IDs into concrete provider-model-config tuples using `_resolve_model_config`.
3. **TTS Configuration**: For each speaker, calls `SpeakerProfile.resolve_tts_config` to obtain the TTS provider, model, and credentials.
4. **Orchestration**: Passes all resolved configurations to the podcast-creator library for multi-speaker synthesis.

The main orchestration logic also resides in [`commands/podcast_commands.py`](https://github.com/lfnovo/open-notebook/blob/main/commands/podcast_commands.py), which builds safe output directories and creates `PodcastEpisode` records during processing.

## Migration Considerations

If upgrading from legacy versions, the migration script in [`open_notebook/podcasts/migration.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/migration.py) (line 66) converts string-based model references to the new record-ID schema. This ensures existing profiles remain compatible with the current resolution system without manual intervention.

## Summary

- Open Notebook separates podcast configuration into `EpisodeProfile` (templates) and `SpeakerProfile` (voices) models defined in [`open_notebook/podcasts/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/models.py).
- Speaker profiles support 1-4 speakers with mandatory fields: `name`, `voice_id`, `backstory`, and `personality`.
- Episode profiles validate `num_segments` between 3-20 and link to speaker configs via the `speaker_config` field.
- The generation pipeline in [`api/routers/podcasts.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/podcasts.py) resolves model IDs and TTS configurations before passing data to the podcast-creator library.
- Legacy migrations are handled automatically via [`open_notebook/podcasts/migration.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/migration.py).

## Frequently Asked Questions

### How many speakers can I configure in a single SpeakerProfile?

The `SpeakerProfile` model in [`open_notebook/podcasts/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/models.py) enforces a limit of 1-4 speakers per profile (lines 60-68). Each speaker must include the mandatory fields `name`, `voice_id`, `backstory`, and `personality` to ensure the generation system can create distinct voice characteristics and dialogue patterns.

### What validation rules apply to episode segments?

According to the source code at lines 82-86 of [`open_notebook/podcasts/models.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/podcasts/models.py), the `num_segments` field in `EpisodeProfile` must be between 3 and 20. This validation ensures that generated episodes maintain a reasonable narrative structure without becoming too fragmented or excessively long.

### How does Open Notebook resolve model references during generation?

When processing a request in [`api/routers/podcasts.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/podcasts.py), the system calls `resolve_outline_config` and `resolve_transcript_config` on the episode profile, which internally use `_resolve_model_config` to convert stored model IDs into concrete provider-model-config tuples. For text-to-speech, it calls `SpeakerProfile.resolve_tts_config` to obtain provider credentials and voice settings for each speaker.

### Can I reuse the same speaker profile across multiple episode templates?

Yes, the architecture is designed for reusability. You create a `SpeakerProfile` once via [`api/routers/speaker_profiles.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/speaker_profiles.py), then reference it by name in multiple `EpisodeProfile` configurations using the `speaker_config` field. This allows you to maintain consistent voice casting across different podcast series or episode formats while varying the LLM models or segment counts.