Skip to main content

AudioPod Python SDK

Add speech-to-text with speaker labels, text-to-speech, voice cloning, stem separation / vocal removal, audio-to-MIDI, music generation and noise reduction to a Python app with one package and one API key.

pip install audiopod
export AUDIOPOD_API_KEY=ap_...   # https://audiopod.ai/dashboard/account/api-keys
from audiopod import Client
job = Client().transcription.transcribe(url="https://example.com/talk.mp3", speaker_diarization=True, wait_for_completion=True)
print(job["id"], job["status"])
Job Method Guide
Speech to text, speaker diarization, subtitles client.transcription.transcribe(...) transcription
Text to speech (500+ voices, inline directing) client.voice.generate_speech(...) text-to-speech
Voice cloning client.voice.create_voice(..., wait_for_ready=True) voice cloning
Stem separation, vocal remover, karaoke client.stem_extraction.separate(...) stems
Audio to MIDI client.midi.convert(...) MIDI
Music generation client.music.generate(...) music
Noise reduction client.denoiser.denoise(...) noise reduction
Speaker separation client.speaker.diarize(...) speakers

Billing: API-key requests are paid from a prepaid USD API wallet first and, when it can't cover a job, from your account's plan or pay-as-you-go credits. Your first API key comes with a $1 starter credit in the wallet (verified email). See wallet rates with client.wallet.get_pricing(); top up the wallet from the API keys page or add credits at audiopod.ai/pricing. Coding agents: read AGENTS.md.

This SDK is the Platform (API + Agent) surface of AudioPod, alongside the Node.js SDK, the audiopod CLI, and the MCP server.

Run in Postman

Want to see a response before installing anything? The Getting Started collection reaches a real 200 in two requests with no account and no API key. More about the collections.

Quick start: one call per task

Set AUDIOPOD_API_KEY (or pass api_key="ap_..."), then each task is one call that waits for the job and returns its output links.

Transcribe with speaker labels

from audiopod import Client
client = Client()
job = client.transcription.transcribe(url="https://example.com/interview.mp3", speaker_diarization=True, wait_for_completion=True)
for seg in client.transcription.get_transcript(job["id"])["segments"]:
    print(seg.get("speaker_label"), seg["text"])

Split a song into stems

from audiopod import Client
client = Client()
job = client.stem_extraction.separate(file="song.mp3", mode="four")  # vocals, drums, bass, other
for stem, link in job["download_urls"].items():
    print(stem, link)

Text to speech

from audiopod import Client
client = Client()
job = client.voice.generate_speech(voice_id=368, text="Welcome to AudioPod.", wait_for_completion=True)
print(job["output_url"])

Generate music

from audiopod import Client
client = Client()
track = client.music.generate(prompt="lo-fi hip hop, 80 BPM, soft piano", duration=60, wait_for_completion=True)
print(track["output_url"])

Audio to MIDI / noise removal

from audiopod import Client
client = Client()
print(client.midi.convert(file="song.mp3")["merged_midi_url"])
print(client.denoiser.denoise(file="voice-memo.m4a")["output_url"])

Step-by-step guides for each task start at docs.audiopod.ai/quickstarts/transcription.

Using with AI agents

  • Coding agents (Claude Code, Cursor, Copilot, Windsurf): tell the agent to use the audiopod package and point it at docs.audiopod.ai/llms.txt. Every docs page is also served as Markdown: add .md to its URL.
  • Agents as tools (MCP): connect https://mcp.audiopod.ai/core (transcribe, stems, cleanup, MIDI) or https://mcp.audiopod.ai (adds speech, voices and music). Sign-in is OAuth; an X-API-Key header works for CI.
  • Claude Code plugin: /plugin marketplace add AudiopodAI/claude-plugin, then /plugin install audiopod@audiopod.
  • ChatGPT: add https://mcp.audiopod.ai/core as a connector in developer mode.

Setup for every client, plus copy-paste prompts: AudioPod for AI agents.

Text-to-Speech

500+ voices across 85+ languages, with inline directing written straight into the text.

# Emotion, non-verbal sounds, pauses, and pronunciation — all inline in `text`
job = client.voice.generate_speech(
    voice_id=368,
    text='[warm, unhurried] Good evening. [breathe] Tonight, a story. '
         '<break time="600ms"/> It begins in Worcester /ˈwʊstər/.',
    wait_for_completion=True,
)
  • Emotion / delivery — a leading bracket per segment: [whispering, tense] …
  • Non-verbal sounds — [laugh] [sigh] [clear throat] [breathe] [cough] [yawn] [chuckle] [gasp] [groan]
  • Pauses — <break time="500ms"/> (≤10s each, ≤20 per request)
  • Pronunciation — inline IPA between slashes: Worcester /ˈwʊstər/

Word-level timestamps (for follow-along / karaoke UIs) and Voice Design (create a voice from a text description) are available via the REST API — see the docs.

Voice Cloning

# Instant clone from a 5–30s reference clip. A new clone is PENDING while it
# processes; wait_for_ready=True returns once it is COMPLETED and usable.
voice = client.voice.create_voice(name="My Voice", audio_file="sample.wav", wait_for_ready=True)

# Reuse the clone for TTS
job = client.voice.generate_speech(
    voice_id=voice["id"], text="Now in my own voice.", wait_for_completion=True
)

Voice conversion (voice-to-voice) is available via the REST API — see Voice Changer.

Music Generation

# Duration is not tier-capped (10s–10min)
result = client.music.generate(
    prompt="upbeat synthwave, 120 BPM, driving bassline",
    duration=60,
    wait_for_completion=True,
)

Every plan now gets the highest-quality music model at the standard rate, so the old quality= argument is no longer needed. It is still accepted for compatibility and is only sent when you pass it.

Score-first music (v3)

AudioMusic v3 writes the song as an editable score (ABC notation) first and renders the audio from that score, so you can read and change the music itself before paying for a recording. There is no duration: length follows the lyrics and the score.

caps = client.music.v3_availability()  # {"available": bool, "revise": bool}
if caps["available"]:
    # 1. Write the score only (no audio). Bring your own lyrics, or describe
    #    the song and AudioPod writes the lyrics first.
    plan = client.music.compose(
        description="a hopeful folk song about leaving a harbour town at dawn",
        target_seconds=150,
        wait_for_completion=True,
    )

    # 2. Optional: change it in plain English (when enabled for your account)
    if caps.get("revise"):
        plan = client.music.revise_score(
            source_job_id=plan["job_id"],
            instruction="make the chorus higher",
            section="chorus",
            idempotency_key="my-retry-safe-key",
            wait_for_completion=True,
        )
        print(plan["note"], plan["score_comparison"]["changed_bars"])  # {"Vocal": [[9, 16]]}

    # 3. Record the score as audio (omit abc to record the score as it is)
    song = client.music.record_score(source_job_id=plan["job_id"], wait_for_completion=True)
    print(song["audio_url"])
Method Endpoint
v3_availability() GET /api/v1/music/v3/availability
compose(style=None, lyrics=None, description=None, target_seconds=None, language=None, ...) POST /api/v1/music/v3/plan (score only)
revise_score(source_job_id, instruction, section=None, bars=None, idempotency_key=None, ...) POST /api/v1/music/v3/revise (score only)
record_score(source_job_id, abc=None, ...) POST /api/v1/music/v3/edit (renders audio)
generate_v3(style, lyrics=None, abc=None, ...) POST /api/v1/music/v3/generate (score + audio)
get_v3_job(job_id) / get_score(job_id) GET /api/v1/music/v3/jobs/{id} / .../score
list_v3_jobs(workflow=None, source_job_id=None) GET /api/v1/music/v3/jobs
wait_for_v3_job(job_id) polls until COMPLETED

Checked client-side before any request (ValidationError): lyrics and description are mutually exclusive, style is required without a description, target_seconds is 30–300, instruction is 1–500 characters, section at most 60, bars 1–10000 with start ≤ end, and idempotency_key (sent as the Idempotency-Key header) at most 200.

Server error codes (in the APIError message; nothing is charged for any of them): LYRICS_FAILED (422), LYRICS_BUSY (503), DESCRIPTION_NOT_ALLOWED (422) on compose; REVISE_FAILED (422), REVISE_TARGET_NOT_FOUND (422), REVISE_IN_FLIGHT (409), IDEMPOTENCY_KEY_REUSED (422), REVISE_RATE_LIMITED (429), REVISE_UNAVAILABLE (503) on revise_score; SCORE_ALREADY_RECORDING (409) on record_score.

Stem Separation

# Extract stems (vocals, drums, bass, other)
job = client.stem_extraction.extract_stems(
    audio_file="song.mp3",
    stem_types=["vocals", "drums", "bass", "other"],
    wait_for_completion=True,
)
for stem, url in job["download_urls"].items():
    print(f"{stem}: {url}")

Audio to MIDI

Convert a mix — or stems you already separated — into MIDI (bass, vocals, piano by default; guitar is opt-in/experimental). It's a starting-point transcription: tidy timing/lengths in your DAW, drums aren't transcribed yet, and dynamics are approximate.

# Standalone: split + transcribe in one call (default stems: bass, vocals, piano)
job = client.midi.convert(file="song.mp3")
print(job["merged_midi_url"])

# Add-on: transcribe stems you already separated (bills the add-on rate only)
job = client.midi.convert_from_stem_job(stem_job_id=job["id"])
for stem, url in (job["midi_urls"] or {}).items():
    print(f"{stem}: {url}")

Transcription

# Speaker labels + word timestamps
result = client.transcription.transcribe(
    audio_file="podcast.mp3",
    speaker_diarization=True,
    wait_for_completion=True,
)
print(result["transcript"])

Premium-accuracy transcription and real-time streaming are also supported — see Speech-to-Text.

Other Audio Services

# Speaker separation / diarization
speakers = client.speaker.diarize(audio_file="interview.wav", wait_for_completion=True)

# Noise reduction
clean = client.denoiser.denoise(audio_file="noisy.mp3", mode="studio", wait_for_completion=True)

# Translate / dub speech into another language
dubbed = client.translation.translate(audio_file="clip.mp3", target_language="es")

# Audiobook production (manuscript → ACX-ready export)
project = client.audiobook.create_project(title="My Book", author="J. Doe")

OpenAI-Compatible Endpoints

Already have OpenAI-shaped audio code? Point it at AudioPod — set the client base URL to https://api.audiopod.ai/api/v1 and Authorization: Bearer ap_.... The /audio/speech, /audio/transcriptions, and /audio/translations endpoints behave like their OpenAI counterparts. See OpenAI compatibility.

API Wallet

# Balance and cost estimate
balance = client.wallet.get_balance()
estimate = client.wallet.estimate_cost("text_to_speech", duration_seconds=180)

# Top up
checkout = client.wallet.create_topup_checkout(amount_cents=2500)  # $25
print(f"Pay at: {checkout['url']}")

Async Support

import asyncio
from audiopod import AsyncClient

async def main():
    async with AsyncClient() as client:
        balance = await client.wallet.get_balance()
        print(f"Balance: {balance['balance_usd']}")

asyncio.run(main())

Error Handling

from audiopod import Client
from audiopod.exceptions import (
    AuthenticationError,
    InsufficientBalanceError,
    RateLimitError,
    APIError,
)

try:
    client = Client()
    job = client.voice.generate_speech(voice_id=368, text="Hello")
except AuthenticationError as e:
    print(e)  # says to set AUDIOPOD_API_KEY and where to create a key
except InsufficientBalanceError as e:
    print(e)  # explains the API wallet and how to top it up
    print(f"required {e.required_cents} cents, available {e.available_cents}")
except RateLimitError:
    print("Rate limit exceeded, try again later")
except APIError as e:
    print(f"API error ({e.status_code}): {e}")

Documentation

License

MIT

Metadata

Release files for audiopod 2.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for audiopod 2.11.0
File Size Uploaded
audiopod-2.11.0.tar.gz 70.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for audiopod 2.11.0
File Interpreter ABI Platform
audiopod-2.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 138.5 kB

Release files / audiopod-2.11.0.tar.gz

Download URL audiopod-2.11.0.tar.gz
Size 70.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1694fc88eef44c2ad71bdb0352c1d7f6e5b0f53636568c4c517d2aa2ed410df8
BLAKE2b-256 checksum
How to use checksums
9ebc7c4f7b05113aa2501da0f2fcc7d5ed0f00ce263454bd63565b6f2bc1d413
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / audiopod-2.11.0-py3-none-any.whl

Download URL audiopod-2.11.0-py3-none-any.whl
Size 67.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5ab8f5f34c1e1d0c5b79c943a51a9ef3bfa2ef23e4a89989bcdc91a788eecee1
BLAKE2b-256 checksum
How to use checksums
545eb688a785a64fa346cb0e53f895c9b2a28c2bd86d6aa086ddedba4626613a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

2.12.0

2 release files

This release

2.11.0 This release

2 release files

2.10.1

2 release files

2.9.0

2 release files

2.8.2

2 release files

2.8.1

2 release files

2.7.0

2 release files

2.5.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page