Transcriber

How it works

Read the header. Hold the credits. Do the work. Give the rest back.

Per-minute pricing has an awkward requirement: you have to know the minutes before you can name a price. Everything about the way this runs follows from solving that honestly.

The pipeline

Five steps, and you are only charged for the fourth.

Everything before the transcription exists so the price is right, and everything after it exists so you get the difference back.

chunk 1chunk 2chunk 300:00:00.0001:12:04.86one timeline0102030405
01

Read the header

Two ranged requests pull the container's metadata to find the real length. That is the number you are quoted.

02

Hold the credits

Reserved up front on that length, never on a cap. Nothing is spent yet.

03

Split if needed

Over 22 MB the audio is cut on frame boundaries with a three-second overlap, so no word falls in a gap.

04

Transcribe

Each piece is transcribed with word-level timings, then stitched back onto one timeline.

05

Settle the difference

Billed on the length actually transcribed. The rest goes straight back to your wallet.

The two hard parts

Knowing the length, and surviving the split.

01

Duration, from the file itself

There is no media toolchain running on a serverless function, so the length has to come out of the container's own metadata. Two ranged requests — the first half-megabyte and the last quarter — are enough for every format we accept.

WAV states its byte rate. MP3 carries a frame count in its Xing header. MP4 keeps a timescale in mvhd, which sits at the end of the file unless it was written for streaming — which is why the last quarter-megabyte is fetched too.

When a file genuinely will not say, you are told: the quote comes back marked as an estimate, and the charge still lands on the real length.

02

Splitting without losing a word

The transcription rail refuses uploads over 25 MB, which at podcast bitrates is about twenty-six minutes. Longer files are cut on MPEG frame boundaries, so every piece is a valid file on its own and every piece states its own exact duration.

Each cut overlaps the one before it by three seconds, because a hard cut lands mid-word and both sides then mis-hear it. The duplicate is removed afterwards by asking which chunk holds most of each word — so a word straddling the join survives exactly once instead of being dropped by both.

Timings are reassembled from word-level timestamps, not from segment guesses, which is what keeps a subtitle file in sync an hour in.

Exports

One transcript. Whatever file you actually needed.

Subtitles, plain text, or structured JSON — all four are the same words with the same timings, serialized differently. Exporting is free, and it stays free however many times you come back for a different one.

.srt
Premiere, Resolve, YouTube
Numbered cues, comma milliseconds.
.vtt
The web, <track> elements
WEBVTT header, dot milliseconds.
.txt
Reading and pasting
One timestamped line per cue.
.json
Anything programmatic
Segments with start, end, text.
transcript1 cue · 00:00:04.12 → 00:00:06.90.srt100:00:04,120--> 00:00:06,900we can ship it.vttWEBVTT00:00:04.120--> 00:00:06.900we can ship it.json{"start": 4.12,"end": 6.9,"text": "we can…"}same words · same timings · 0 creditsGET /api/jobs/<id>/export?format=srt

End to end

Four calls, three of them free.

# 1 — ask what it will cost. Free, and it reads the real file.
curl -X POST https://transcribe.ounie.com/api/quote \
  -H "Authorization: Bearer trx_live_…" \
  -d '{"url":"https://example.com/ep-104.mp3"}'
# → { "credits": 186, "minutes": 62, "duration_estimated": false }

# 2 — submit it.
curl -X POST https://transcribe.ounie.com/api/jobs \
  -H "Authorization: Bearer trx_live_…" \
  -d '{"url":"https://example.com/ep-104.mp3"}'
# → 202 { "job": { "id": "8f2c…", "status": "queued" } }

# 3 — poll. Free, and polling drives the job forward.
curl https://transcribe.ounie.com/api/jobs/8f2c… \
  -H "Authorization: Bearer trx_live_…"
# → { "status": "succeeded", "text": "…", "segments": [ … ] }

# 4 — take the file you needed. Also free.
curl "https://transcribe.ounie.com/api/jobs/8f2c…/export?format=srt" \
  -H "Authorization: Bearer trx_live_…" -o ep-104.srt