HomeBlog → How to transcribe a recording that does not fit one request

How to transcribe a recording that does not fit one request

Published 2026-08-20 · 5 min read

A four-hour conference recording, a day-long dictation dump, a webinar with screen capture — none of them fit into a single request. The job breaks into three steps: compress, split on pauses, merge the text back. Here is the working recipe with code.

Compress before you split

Try compression first; it is often enough on its own. An hour of speech in opus is about 11 MB, so a two-hour recording fits the limit whole:

ffmpeg -i conference.wav -vn -ac 1 -ar 16000 -c:a libopus -b:a 24k conference.ogg

Splitting only makes sense when the compressed file is still too large, or when you want parallel processing for speed.

Where to cut so nothing breaks

Cutting at fixed intervals is easy and will sooner or later slice a word in half, leaving garbage at the seam. Cutting on silence is safer. First find the pauses:

ffmpeg -i long.ogg -af silencedetect=noise=-35dB:d=1 -f null - 2>&1 | grep silence_end

Then cut at the pause nearest your target length:

ffmpeg -i long.ogg -ss 0 -to 912.4 -c copy part001.ogg

A practical compromise is 10–15 minute chunks: convenient to send in parallel, and a bad seam costs very little.

Process chunks in parallel

Chunks are independent, so send them at once and keep order by filename:

import concurrent.futures as cf, pathlib
from openai import OpenAI

client = OpenAI(base_url="https://voicesscribe.com/v1", api_key="your key")

def one(path):
    with path.open("rb") as f:
        return path.name, client.audio.transcriptions.create(model="whisper-1", file=f).text

parts = sorted(pathlib.Path(".").glob("part*.ogg"))
with cf.ThreadPoolExecutor(max_workers=4) as pool:
    result = dict(pool.map(one, parts))

full = "\n".join(result[p.name] for p in parts)
pathlib.Path("conference.txt").write_text(full, encoding="utf-8")

Match the worker count to the request-rate limit of your plan: overshoot it and you collect 429 responses and repeat the work.

Continuous timestamps

If you need navigation rather than plain text, ask for segments and add each chunk's offset:

offset = 0.0
for path in parts:
    with path.open("rb") as f:
        r = client.audio.transcriptions.create(
            model="whisper-1", file=f, response_format="verbose_json")
    for seg in r.segments:
        print(round(seg["start"] + offset, 1), seg["text"].strip())
    offset += r.duration

Timestamps then stay aligned with the original recording and can drive a player.

Try it on your own recordings. Sign-up takes a minute, and the free minutes are enough to judge the quality.

Get a free API key

Frequently asked questions

What is the file size limit?

25 MB per request. In opus that is roughly two hours of speech, so compression alone usually removes the need to split.

What does a 413 error mean?

The file exceeds the allowed size. Compress to opus or a low-bitrate mp3, or split it into parts.

Is meaning lost at chunk boundaries?

Not if you cut on silence. Fixed-interval cuts can drop a word at the seam, which is why finding pauses is worth the extra step.

Can chunks be processed at the same time?

Yes, they are independent. The only constraint is the requests-per-second limit of your plan.

Related reading