Insights & Use Cases
August 25, 2026

Batch Transcribe Thousands of Audio Files at Once in Python

Large-scale audio transcription converts thousands of audio files into accurate, searchable text quickly. Process hours of content efficiently with batch tools.

Reviewed by
No items found.
Table of contents

Large-scale audio transcription converts thousands of pre-recorded audio files into accurate, searchable text concurrently rather than one at a time. Because the work runs asynchronously, total completion time is governed by your longest file—not the sum of all of them—so an entire podcast catalog or years of call recordings can finish in roughly the time it takes to process a single file. Jobs run with unlimited concurrency and no rate limits, so throughput is bounded by how fast you can submit rather than by a queue we impose. Unlike real-time transcription, which processes live audio streams, batch transcription prioritizes throughput over latency.

This guide shows you how to architect and implement production-ready batch transcription in Python against the current Speech-to-Text API. You'll learn when batch processing beats real-time, how to optimize audio for accuracy, and how to build resilient systems that handle thousands of concurrent jobs—including diarization, confidence scoring, export, and error handling that scales from hundreds of files to millions.

What is large-scale audio transcription and when do you need it?

Large-scale audio transcription is the practice of transcribing thousands of pre-recorded audio files simultaneously instead of sequentially. This batch approach handles entire audio libraries—from years of customer service recordings to complete podcast catalogs—with total completion time determined by your longest file, the key benefit of an asynchronous architecture.

You need batch processing when sequential processing creates unacceptable delays. The indicators are boring and reliable:

  • Volume threshold: you're processing 100+ audio files regularly
  • Time constraints: you need results in minutes, not days
  • Business applications: media asset management, call center analytics, podcast transcription, compliance review

Batch systems eliminate bottlenecks by processing all jobs concurrently. For a deeper comparison of when each model fits, see real-time speech-to-text and the broader speech-to-text guide.

What architecture handles hours of audio efficiently?

Term Definition Practical impact
Asynchronous processing Multiple tasks run simultaneously Process 1,000 files in the time of your longest file
Concurrent job submission Submit all jobs at once No waiting for previous jobs to complete
Status polling Check job completion periodically Know when results are ready without constant monitoring

The core idea is asynchronous processing versus synchronous processing. Synchronous processing is like washing dishes one by one—you finish one completely before starting the next. Asynchronous processing is like loading a dishwasher: you put everything in at once and it all gets cleaned in parallel.

Here's what makes async batch transcription work:

  • Concurrent job submission: upload and start processing thousands of files at the same time
  • Status monitoring: check which jobs are done without stopping the ones still running
  • Result collection: gather transcripts as they finish, in any order
  • Error handling: retry failed jobs without affecting successful ones

You have two ways to track progress: polling and webhooks. Polling means you periodically check job status yourself. Webhooks mean the service notifies you when jobs complete.

Method Best use case Complexity Reliability
Polling Simple setups, direct control Low High — no external setup needed
Webhooks Event-driven systems, real-time notifications Medium High — requires a stable public endpoint

The SDK's transcribe call polls for you. Webhooks are the robust alternative for custom or event-driven architectures—they eliminate periodic checks by notifying your application the moment jobs complete, which is usually more efficient once your pipeline is running unattended.

Audio preprocessing for optimal transcription accuracy

Preprocessing improves accuracy and reduces the number of transcripts you end up reviewing by hand. Two areas matter.

File format. Compressed formats like MP3 and M4A balance quality and file size for most use cases. Lossless formats like FLAC and WAV preserve maximum fidelity when storage isn't a concern. In practice the difference is small compared to what the microphone did.

Audio quality. Apply noise filtering before submission where you can, and process separate channels individually when you have them—dual-channel call recordings give you speaker separation for free, before diarization is even involved. If you don't have channels, speaker diarization handles it on the model side.

How to implement async batch transcription in Python

You'll build this in three steps. Every sample below targets Python SDK 1.0.0, which shipped August 14, 2026 and unified the async, streaming, and sync clients behind one shape—pre-recorded work now imports from assemblyai.prerecorded.v2. If you're on a 0.6x release, upgrade before copying any of this; the import surface changed.

Set up the AssemblyAI Python SDK and authenticate

Install the SDK:

pip install "assemblyai>=1.0.0"

Set your API key as an environment variable rather than in code:

export ASSEMBLYAI_API_KEY="your_api_key_here"

Then create your script and configure the client:

import os
import threading

from assemblyai.prerecorded.v2 import Transcriber, TranscriptionConfig

transcriber = Transcriber(api_key=os.environ["ASSEMBLYAI_API_KEY"])

config = TranscriptionConfig(
    speech_models=["universal-3-5-pro", "universal-2"],
    speaker_labels=True,
    punctuate=True,
    format_text=True,
)

Never put your API key directly in your code. Environment variables keep the credential out of your source history, which matters more than it sounds like it does the first time a repo goes public.

Submit and transcribe your batch of audio files

The documented multi-file pattern is a thread per file around a shared Transcriber. Each thread submits one job and blocks until that job finishes, so the whole batch runs concurrently and your wall-clock time tracks the slowest file rather than the sum.

audio_urls = [
    "https://example.com/calls/0001.mp3",
    "https://example.com/calls/0002.mp3",
    # ... thousands more
]

transcripts = [None] * len(audio_urls)

def transcribe_one(url, index):
    try:
        transcripts[index] = transcriber.transcribe(url, config=config)
    except Exception as exc:            # network, auth, unreachable URL
        transcripts[index] = exc

threads = [
    threading.Thread(target=transcribe_one, args=(url, i))
    for i, url in enumerate(audio_urls)
]
for t in threads:
    t.start()
for t in threads:
    t.join()

for url, result in zip(audio_urls, transcripts):
    if isinstance(result, Exception):
        print(f"submission failed: {url}: {result}")
    elif result.status == "error":
        print(f"transcription failed: {url}: {result.error}")
    else:
        print(f"{url}: {len(result.text.split())} words")

The try/except inside the worker is the important part. Catch per file and store the exception in the results slot, and one unreachable URL in ten thousand costs you one transcript instead of the whole run. At genuinely large batch sizes, put the work through a bounded thread pool rather than starting one OS thread per file—the API doesn't mind, your machine will.

What the configuration is doing:

  • speech_models=["universal-3-5-pro", "universal-2"]: prioritizes Universal-3.5 Pro, which covers 18 languages with native code-switching, and falls back to Universal-2 ($0.15/hr, 99 languages) for anything outside the flagship's 18. Universal-3.5 Pro costs $0.06/hr more, and what that buys is code-switching, better diarization, and contextual prompting.
  • speaker_labels=True: identifies who's speaking when.
  • punctuate=True and format_text=True: punctuation and sentence casing.

Export transcripts in multiple formats

Format Use case Speaker info Timestamps
JSON Data analysis, searching Full speaker details Word-level precision
TXT Simple reading None None
SRT Video subtitles Limited Segment-level
VTT Web video captions Limited Segment-level

Write each completed transcript out in whatever your downstream system consumes:

from pathlib import Path

out = Path("transcripts")
out.mkdir(exist_ok=True)

for index, result in enumerate(transcripts):
    if isinstance(result, Exception) or result.status == "error":
        continue
    stem = f"{index:05d}"
    (out / f"{stem}.txt").write_text(result.text)
    (out / f"{stem}.srt").write_text(result.export_subtitles_srt())
    (out / f"{stem}.vtt").write_text(result.export_subtitles_vtt())

Skipping the failures rather than crashing on them is the whole difference between a script and a pipeline.

Start Batch Transcription in Python

Get an API key and submit your first thousand files concurrently. Speaker labels, punctuation, and export to TXT, SRT, VTT, or JSON are all one config away.

Sign up free

How much does it cost to transcribe one hour of audio?

One hour of audio costs the per-hour list rate for the model you selected, billed per second with no minimums. Universal-3.5 Pro, the flagship async model, is $0.21/hour; Universal-2 is $0.15/hour. Because billing is duration-based, a thousand hours of audio costs the same whether you process it in one batch or a hundred—concurrency affects speed, not price. Current rates for every model and add-on are on the pricing page.

How to plan throughput and cost for large batches

Batch size Typical completion time Estimated cost (flagship async, $0.21/hr)
100 files (1 hour each) 15-20 minutes $21
1,000 files (30 minutes each) 10-15 minutes $105

Planning a batch means understanding two things: how long it takes and how much it costs. The good news on the first is that processing time barely increases with more files.

Because jobs run in parallel rather than in sequence, your wall-clock time tracks your longest single file rather than the sum of the batch. A thousand files and a hundred files finish in roughly the same window if the longest file in each is the same length.

Concurrency is unlimited and there are no rate limits, so the shape of your batch matters more than its size. One distinction worth internalizing while you plan: concurrency and traffic shaping are separate mechanisms. They get conflated constantly, and they behave differently.

That combination—accuracy that holds at operational volume, and throughput you don't have to negotiate for—is what teams processing large libraries are actually buying. Sabba Keynejad and Tim Mamedov of Veed put the benefit in terms of what it freed them to do:

"Assembly allowed our team to focus on what they are best at: Building a collaborative, browser-based video editor and distributing that product at speed and at velocity to our user base."

Here's how to estimate cost before you submit anything:

FLAGSHIP_ASYNC_RATE = 0.21  # USD per hour of audio, Universal-3.5 Pro

def estimate_batch_cost(durations_seconds, rate_per_hour=FLAGSHIP_ASYNC_RATE):
    """durations_seconds: iterable of per-file audio durations."""
    total_hours = sum(durations_seconds) / 3600
    return round(total_hours * rate_per_hour, 2)

print(estimate_batch_cost([3600] * 100))   # 100 one-hour files
print(estimate_batch_cost([1800] * 1000))  # 1,000 half-hour files

Worth knowing where you sit relative to everyone else solving this. In AssemblyAI's 2026 Voice Agent Report, built on 455 responses fielded across Q4 2025 and Q1 2026, 62% of builders named cost-effectiveness as a primary decision driver, and 42.5% named high costs as an active challenge. At batch scale, the difference between those two groups is usually configuration rather than pricing.

Cost optimization, in rough order of how much money it saves:

  • Only enable what you need. Diarization, keyterms prompting, and Speech Understanding features are separate add-ons. They're inexpensive individually and they add up across a million files.
  • Use the right model. Universal-3.5 Pro is the highest-accuracy option at $0.21/hr and covers 18 languages with native code-switching. Universal-2 is $0.15/hr and remains the fallback for the long tail of 99 languages—worth routing to deliberately if a chunk of your corpus is outside the flagship's languages.
  • Group similar content. Processing similar audio types together keeps your configuration consistent and your quality checks meaningful.
  • Build in retry logic. Wrap submission in your own retry for network and file-access failures. The SDK handles transient API errors; it can't fix an S3 bucket policy.

If your data can't leave Europe, the same pipeline runs against api.eu.assemblyai.com at the same price, with audio and transcripts staying in the EU.

Spot-Check One File Before You Build the Pipeline

Run a representative recording through the playground and look at the speaker labels and the proper nouns. Thirty seconds now beats a re-run across ten thousand files later.

Try playground

Advanced configuration options for production transcription

Production systems need more than the defaults.

Accuracy optimization. Keyterms prompting boosts recognition of specific terms, names, and industry jargon—up to 1,000 terms on the Universal Pro line, 200 on Universal-2, for +$0.05/hr. Natural language prompting lets you hand the model context and instructions instead of a term list, which works better for tone, formatting, and domain framing.

You can set both on the same request—they do different jobs. keyterms_prompt tells the model which exact strings to expect; prompt tells it what kind of audio this is. One caveat if you route through Pipecat: that plugin does not accept both in a single request, so scope your config per integration rather than assuming the async behavior carries over.

Diarization tuning. If you know how many speakers are in a recording, speakers_expected improves accuracy. When the count varies across your corpus—which it usually does—speaker_options=SpeakerOptions(min_speakers_expected=2, max_speakers_expected=6) gives the model a range instead of a wrong guess.

Quality control. Flag transcripts below a confidence threshold for human review rather than trusting the whole batch equally, and route anything with an error status into a retry queue automatically.

For summaries, action items, and chapters, don't reach for the legacy transcription parameters. auto_chapters and summarization are Universal-2 only, and on Universal-3.5 Pro they cause silent 500 errors—the request fails, and nothing in the response tells you which parameter did it. Use the speech_understanding request object through the Speech Understanding API for summaries and action items, and LLM Gateway for chapters and anything custom. We walk through the pattern in summarizing audio and video at scale.

Monitoring and debugging large-scale transcription workflows

At a thousand files, failures stop being exceptions and start being a rate. Plan for them.

Common error patterns:

  • Invalid URLs: files moved, expired pre-signed links, or bucket permissions that changed under you
  • Format issues: unsupported file types or corrupted audio, usually clustered in one part of an archive
  • Network timeouts: transient, and the reason exponential backoff exists

What to build: log every job ID alongside its source URL and error text, retry with exponential backoff rather than immediately, and send webhook notifications on failure so you find out from a queue rather than from a customer. And log the confidence score alongside each transcript, because at this volume the useful question stops being "did it work" and becomes "which two percent do I need to look at."

Batch, streaming, or sync: which path fits

Path Best for Price Timing behavior
Batch / async Pre-recorded libraries, throughput-optimized $0.21/hr flagship, $0.15/hr Universal-2 Completion governed by your longest file
Streaming Live audio, captions, voice agents $0.45/hr base Partials in a few hundred milliseconds
Sync API Short clips needing one request and one response Not listed on the public pricing page Single call, no submit-and-poll loop

Is batch always the right choice? No. If you're processing pre-recorded audio at volume, it's the most efficient method by a wide margin. If you need live captions or a voice agent, you need streaming instead. And if you're transcribing a short clip and don't want a polling loop at all, the Sync API returns a transcript in one request.

Hybrid architectures are common and sensible. An AI meeting assistant might run streaming transcription for live notes during a call, then run a batch job on the final recording to produce a richer transcript with diarization, plus summaries and action items through Speech Understanding. Same API key, same billing, two different latency profiles.

If you just need a tool, not a pipeline

Worth saying plainly, because a lot of people land on this page looking for something else: if you have one folder of recordings and no intention of writing Python, you don't need any of the above. Upload the files in the playground and export the transcripts. That's a legitimate answer, it takes minutes, and building a pipeline for a one-off batch is the engineering equivalent of buying a forklift to move a couch.

The pipeline earns its keep when the batch recurs—when new audio arrives weekly, when transcripts feed something downstream, or when someone other than you depends on the output being there.

What actually governs your batch

The counterintuitive thing about batch transcription at scale is that the model is almost never your bottleneck. Unlimited concurrency, no rate limits, completion governed by your longest file—the transcription itself is the fast part.

What actually governs your wall-clock time is everything around it: how quickly you can hand the API a list of reachable URLs, how you handle the two percent of files that fail for reasons that have nothing to do with speech, and how fast the thing consuming your transcripts can absorb them. Architect for that, and the transcription layer stops being a project and becomes a parameter.

Planning a Thousand-Hour-a-Month Pipeline?

Bring your monthly hours and your peak shape and we'll size the architecture with you—webhooks, retries, monitoring, and cost modeling included.

Talk to AI expert


Frequently asked questions

How much does it cost to transcribe one hour of audio?

AssemblyAI bills per second of audio with no minimums, so one hour of audio costs the flagship async list rate of $0.21 for that hour, or $0.15 on Universal-2. Because billing is duration-based, a thousand hours costs the same whether you process it in one batch or many—concurrency affects speed, not price. Add-ons like diarization and keyterms prompting are priced separately.

How can I transcribe 1 hour of audio quickly?

Submit it to the async API and poll for the result, or use the Sync API if the clip is short enough to want a single round trip. If you have many files, submit them concurrently rather than sequentially—total completion time is governed by your longest single file, not the sum of all of them.

Can I process more than 10,000 audio files at once?

Yes. Concurrency is unlimited and there are no rate limits, so a batch of ten thousand is a submission-throughput question on your side rather than a quota question on ours. Note that concurrency and traffic shaping are separate mechanisms, and they are easy to confuse when you are debugging a slow batch.

What happens if some audio files fail to transcribe during batch processing?

Failed jobs return an error status and message you can retry automatically without affecting successful transcriptions. Routing error-status jobs to a retry queue with exponential backoff is the standard production pattern, and catching exceptions inside each worker thread keeps one unreachable file from taking down the whole batch.

What is the easiest way to transcribe a large batch of audio recordings?

For a one-off batch, upload the files in the playground and export the transcripts. For anything recurring, use the Python SDK with a thread per file—a few dozen lines gets you concurrent submission, polling, error handling, and export to TXT, SRT, VTT, or JSON.

Can I combine batch and real-time transcription in the same system?

Yes, and many teams do. Use streaming transcription—Universal-3.5 Pro Realtime is the highest-accuracy real-time option—for live captions or voice agents during a call, then run a batch job on the final recording for richer summaries and analytics. Both paths run on the same platform, so they share API keys, billing, and tooling.

Title goes here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Button Text
Speech-to-Text
Automatic Speech Recognition