How to Generate Audio Overviews with Different Formats in NotebookLM-Py

Use the generate_audio method on the ArtifactsAPI class, passing the audio_format parameter with values from the AudioFormat enum (DEEP_DIVE, BRIEF, CRITIQUE, or DEBATE) to create podcast-style summaries in distinct styles.

The notebooklm-py library provides a Pythonic interface to Google's NotebookLM service, enabling developers to programmatically generate AI-powered audio overviews from notebook sources. Whether you need an in-depth analysis, a quick briefing, a critical review, or a debate-style discussion, the library's asynchronous generate_audio method in src/notebooklm/_artifacts.py supports four distinct formatting options controlled through the AudioFormat enum defined in src/notebooklm/rpc/types.py.

Understanding Audio Overview Formats

The AudioFormat enum in src/notebooklm/rpc/types.py defines four distinct podcast styles, each mapped to an integer value that the backend uses to select the appropriate generation template:

  • DEEP_DIVE (value 1): Produces a full-length, comprehensive podcast that explores topics in detail with extensive context and analysis.
  • BRIEF (value 2): Generates a concise summary podcast that hits the key points quickly, ideal for time-constrained listeners.
  • CRITIQUE (value 3): Creates a critical analysis podcast that examines the sources with a skeptical, evaluative lens.
  • DEBATE (value 4): Structures the content as a debate-style discussion podcast, presenting multiple viewpoints and counterarguments.

Additionally, you can control the duration using the AudioLength enum: SHORT (~2-3 minutes), DEFAULT (~5-7 minutes), or LONG (>10 minutes).

Generating Audio Overviews with the Python API

The primary entry point is the generate_audio method on the ArtifactsAPI class. This asynchronous method accepts your notebook ID and optional parameters to customize the output.

Deep-Dive Format

Use AudioFormat.DEEP_DIVE for comprehensive, in-depth analysis:

import asyncio
from notebooklm import NotebookLMClient, AudioFormat, AudioLength

async def generate_deep_dive():
    async with await NotebookLMClient.from_storage() as client:
        status = await client.artifacts.generate_audio(
            notebook_id="nb_12345",
            audio_format=AudioFormat.DEEP_DIVE,
            audio_length=AudioLength.LONG,
            language="en"
        )
        print(f"Deep-dive task started: {status.task_id}")

asyncio.run(generate_deep_dive())

Brief Format

Use AudioFormat.BRIEF for quick summaries:

from notebooklm import AudioFormat, AudioLength

# Inside your async function

status = await client.artifacts.generate_audio(
    notebook_id="nb_12345",
    audio_format=AudioFormat.BRIEF,
    audio_length=AudioLength.SHORT,
    instructions="Focus on key action items only."
)

Critique Format

Use AudioFormat.CRITIQUE for skeptical, evaluative analysis:

status = await client.artifacts.generate_audio(
    notebook_id="nb_12345",
    audio_format=AudioFormat.CRITIQUE,
    audio_length=AudioLength.DEFAULT,
    language="en",
    instructions="Evaluate the methodology and identify potential flaws."
)

Debate Format

Use AudioFormat.DEBATE for multi-perspective discussions:

status = await client.artifacts.generate_audio(
    notebook_id="nb_12345",
    audio_format=AudioFormat.DEBATE,
    audio_length=AudioLength.LONG,
    instructions="Present arguments for and against the main thesis."
)

Specifying Audio Length

Control duration by passing AudioLength alongside any format:

from notebooklm import AudioLength

# Options: AudioLength.SHORT, AudioLength.DEFAULT, AudioLength.LONG

status = await client.artifacts.generate_audio(
    notebook_id="nb_12345",
    audio_format=AudioFormat.DEEP_DIVE,
    audio_length=AudioLength.SHORT  # ~2-3 minutes

)

Selecting Specific Sources

By default, generate_audio uses all sources in the notebook. To limit the scope, pass specific source_ids:

status = await client.artifacts.generate_audio(
    notebook_id="nb_12345",
    source_ids=["src_001", "src_042"],  # Only these sources

    audio_format=AudioFormat.CRITIQUE
)

When source_ids is provided, the method skips the automatic source discovery step implemented in src/notebooklm/_artifacts.py lines 74-76.

Using the CLI to Generate Audio Overviews

The command-line interface in src/notebooklm/cli/generate.py provides convenient shortcuts for all formats:


# Brief format (default length)

notebooklm generate audio --format brief

# Deep-dive with long duration

notebooklm generate audio --format deep-dive --length long

# Critique with custom instructions

notebooklm generate audio \
    --format critique \
    --instructions "Focus on methodological weaknesses."

# Debate format

notebooklm generate audio --format debate --length default

The CLI parser maps string arguments like "brief" or "deep-dive" to the corresponding AudioFormat enum values before calling the underlying generate_audio method.

How the generate_audio Method Works

Understanding the internal implementation in src/notebooklm/_artifacts.py helps debug issues and extend functionality.

The method signature at line 52 accepts your configuration parameters:

async def generate_audio(
    self,
    notebook_id: str,
    source_ids: list[str] | None = None,
    language: str = "en",
    instructions: str | None = None,
    audio_format: AudioFormat | None = None,
    audio_length: AudioLength | None = None,
) -> GenerationStatus:

The method constructs a nested list structure (params) that matches Google's internal batchexecute RPC protocol. Key implementation details:

  1. Source ID nesting: The RPC expects source IDs wrapped in triple nested lists ([[[sid]]]) for the source list parameter and double nested lists ([[sid]]) for the source IDs list parameter, as seen in the params construction around lines 89-102.

  2. Enum encoding: The audio_format and audio_length values are extracted using .value (e.g., AudioFormat.DEEP_DIVE.value → 1) and inserted into the RPC payload at specific indices in the nested array structure.

  3. RPC dispatch: The assembled parameters are passed to _call_generate, which invokes _core._make_rpc_call to communicate with the NotebookLM backend, returning a GenerationStatus containing a task_id for polling.

The AudioFormat and AudioLength enums are defined in src/notebooklm/rpc/types.py at lines 47 and 56 respectively, ensuring type safety when selecting format options.

Summary

  • Four distinct formats: Use AudioFormat.DEEP_DIVE, BRIEF, CRITIQUE, or DEBATE to control the podcast style, each mapped to specific integer values (1-4) in src/notebooklm/rpc/types.py.
  • Length control: Combine any format with AudioLength.SHORT, DEFAULT, or LONG to set duration (~2-3 min, ~5-7 min, or >10 min).
  • Implementation location: The generate_audio method in src/notebooklm/_artifacts.py handles parameter encoding and RPC dispatch, while the CLI wrapper in src/notebooklm/cli/generate.py provides command-line access.
  • Source selection: Pass specific source_ids to limit scope, or omit to include all notebook sources automatically.
  • Async workflow: All methods return GenerationStatus with a task_id requiring polling via get_status until completion.

Frequently Asked Questions

What is the difference between the Deep-Dive and Brief audio formats?

Deep-Dive (AudioFormat.DEEP_DIVE) generates a comprehensive, in-depth podcast that explores topics with extensive context and detailed analysis, typically running longer than standard overviews. Brief (AudioFormat.BRIEF) produces a concise summary that hits only the key points quickly, designed for listeners who need rapid information consumption. Both formats accept the same audio_length parameter, but Deep-Dive content naturally tends toward the LONG setting while Brief pairs well with SHORT.

How do I check if my audio generation task completed successfully?

After calling generate_audio, you receive a GenerationStatus object containing a task_id. Poll the status using client.artifacts.get_status(task_id) until the status field equals "completed" or "failed". In the completed state, retrieve the artifact via client.artifacts.get(result.artifact_id) to access the download_url. The CLI handles this polling automatically, but Python API users must implement the loop as shown in the async examples using asyncio.sleep between checks.

Can I generate a Debate format audio overview from specific sources only?

Yes. Pass the source_ids parameter as a list of specific source identifiers to limit the generation scope to only those documents. When source_ids is provided, the generate_audio method in src/notebooklm/_artifacts.py skips the automatic discovery of all notebook sources and uses your specified list directly. This works with any format including AudioFormat.DEBATE, allowing you to create targeted debate-style discussions between specific documents in your notebook.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →