Long recordings are where a transcription pipeline first breaks. A single upload has a practical ceiling, and a two-hour interview will exceed it. The fix is ordinary once you see it: cut the audio into chunks, transcribe each chunk, then put the timed output back together with the right offsets. This guide covers the cut, the stitch, and the retry.

1. Confirm the limit before you engineer around it

Start by reading the current documented limit for POST /v1/audio/transcriptions. Do not hard-code a number you found in a blog post, including this one: limits change, and a stale constant is a silent failure. Read the limit at startup or from config, and treat "file exceeds the limit" as an expected, handled case rather than an exception.

2. Cut the audio into chunks

Two ways to pick a chunk boundary:

  • By duration. Split every N minutes. Simple and predictable, and it maps cleanly to duration-based billing.
  • By size. Split when the encoded file crosses a byte threshold. More robust across codecs with very different bitrates.

Either way, cut on a near-silent point where you can, and overlap adjacent chunks by a second or two. Overlap costs a little extra transcription but prevents a word being sliced in half at the boundary and lost from both sides.

Keep the original start time of every chunk. That offset is the whole game in step 3.

3. Stitch the timed output back together

Ask for a timed format (srt or vtt) so each segment carries a timestamp. Then, for each chunk, add the chunk's start offset to every timestamp in its output before you append it to the final file. A chunk that starts at 00:30:00 contributes segments whose local 00:00:12 becomes 00:30:12.

Watch two details:

  • Overlap de-duplication. The overlap region appears at the end of one chunk and the start of the next. Drop the duplicated lines once, not twice.
  • Segment indices. srt numbering restarts in every chunk. Renumber sequentially as you append, or your player will show gaps.

verbose_json gives you segment objects directly, which is easier to offset and re-emit than parsing and rewriting srt text.

4. Retry a failed chunk safely

A long job means many requests, and one of them will eventually fail. Design for it:

  • Retry per chunk, not per file. A failed chunk should cost you one chunk, not the whole recording.
  • Make the retry idempotent. Key each chunk by file id plus offset, and write its transcript to durable storage before you move on. A retry then overwrites the same slot instead of appending a duplicate.
  • Bound the retries. A few attempts with backoff, then mark the chunk failed and surface it. Do not retry forever.

5. A note on cost

Transcription is billed by audio duration, so your bill scales with minutes, not tokens. Overlap adds a small amount of duplicated audio per boundary; keep the overlap short and the cost impact is negligible. For a cost estimate, use the calculator at https://webwright.ai/tools/cost-calculator.

6. The shape in code

The pipeline is the same in any language. In Python, with the OpenAI SDK pointed at the OpenAI-compatible base URL:

from openai import OpenAI

client = OpenAI(base_url="https://webwright.ai/v1", api_key=WREN_API_KEY)

def transcribe_chunk(path, offset_seconds):
    with open(path, "rb") as f:
        resp = client.audio.transcriptions.create(
            model="whisper-large-v3-turbo",
            file=f,
            response_format="verbose_json",
        )
    # Shift every segment's start/end by offset_seconds, then return the segments.
    return offset(resp.segments, offset_seconds)

# For each chunk, retry a bounded number of times and persist the result keyed by
# (file_id, offset) so a retry overwrites rather than duplicates.

The exact fields on the response follow the verbose_json format documented on the API page.

7. When to book a consult

If you would rather not design the chunking, retry and cost model alone, that is what the consult is for. One working session maps your recording sizes, your volume, and what good looks like, and you leave with a pipeline design and a rough cost.

The WebWright Team