Repository navigation
perf(infra): finish a short transcript in one workflow step - #4147
Merged
Merged
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Member
Author
|
hey @greptileai, please re-review the PR |
|
Sandchest reviewed Sandchest reviews every change for vulnerabilities an attacker could use · 12 credits · Review details |
…-fast-path # Conflicts: # apps/web/__tests__/unit/developer-transcript-docs.test.ts
Member
Author
|
hey @greptileai, please re-review the PR |
Member
Author
|
hey @greptileai, please re-review the PR |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

A short transcript now completes in one workflow step instead of five, which should take about 3 seconds off every transcript up to 30 minutes long, from about 5.1 s to about 2.0 s for a short file. Billing, holds, limits and failure codes are unchanged.
#4134 (captions), #4143 (transcript abuse fixes) and #4150 (URL sources refused from their first bytes) have landed and main is merged in, so the diff is only this change: the workflow, one helper in
lib/developer-transcript-run.tsand tests. The URL check from #4150 sits in the shared prepare body, so the fast step and the prepare step both run it.Why it was slow
On production, a short transcript does about 1.4 s of work, spread over six steps. Each step waits about 0.6 s to be scheduled and queued, so most of the time to complete is overhead.
Production medians from 22 runs:
The shape
One new step,
runTranscriptFastPath, runs claim, prepare, extract, transcribe and settle back to back in one function. It passes the extracted audio straight to transcription instead of reading it back from storage. Cleanup and the caption write stay separate steps after complete is written.The fast step stops and reports where it stopped whenever the normal path would do something other than move on:
The workflow then carries on from that stage with the existing steps, unchanged: the same sleeps and waits, the same raises, the same retries and the same failure handling. A transcript that needs none of this completes in the one step.
I chose this over starting the work from the create request with
after(), the way videos do:after()would save only the first wait, about 0.5 s more. In exchange it would run downloads and speech calls in the API request's function, outside the runId fencing, with the workflow as a watchdog that could run the same work again.Step time limit
Workflow steps are deployed with the plan's maximum duration, 800 s on this plan.
Skipping extraction for audio the speech service accepts: not done
The speech service accepts most audio and video containers, but it reports the length it transcribed only after the work is done. So its duration cannot be what the hold is checked against before we pay for the call.
Today the hold is safe because of extraction itself. It re-encodes the audio at a fixed bitrate and caps it at what the hold covers, so what the speech service receives is bounded and measured by us.
Skipping it would mean trusting our reading of the original file. Local tests show that reading can be far from what a decoder plays:
The second file would be held and charged for 10 seconds while the speech service transcribes 130. The best case saving was about 0.4 s of extract time on MP3 sources only, so the step stays.
Measured
In-process, on the scratch database, the local object store, local ffmpeg and a local stand-in for the speech service, with no step overhead, the work is the same in both versions. Median of 8 runs, 4 for 30 minutes:
The small saving is the audio no longer being read back from storage. The win is the step overhead. Modelled with the production medians above, start to complete:
Applied to the production runs: 10 s files 3.5 to 5.3 s would become about 1.5 to 2.2 s, and 30 minutes 9.6 and 14.9 s about 6.5 and 11.8 s. The production matrix should be run again after merge.
Proof
runTranscriptFastPathis registered, and the transcribe module in the flow bundle has no database codeThe fast path tests cover:
The existing tests still show:
Two delete tests changed. One triggered its delete on the audio read-back, which no longer happens, so it now triggers on the last storage call before the speech service. The other expected the workflow to throw when the speech call failed after a delete. Its transcription is now handed to the transcription step, which sees the delete and ends the transcript with nothing charged. That is what production already does once the runtime retries the step.
Not covered
After review
If the worker stopped after the fast step's settle was saved but before the step's own result was recorded, the step ran again, found the transcript no longer claimable and the workflow ended without cleanup or the caption write. A run that already finished its transcript now goes straight to cleanup and captions. A transcript its own settle ended for lack of credit is cleaned up as not completed, and one owned by another run is still left alone. A repeat delivery of the same run therefore reports completed and repeats only the cleanup, with no second charge or speech call.
Two review threads asked for hosted player captions. Those belong to the playback work, not this PR, which only carries the captions diff of feat(infra): transcribe a stored video by id and write its captions #4134. The player claim in the docs has been reworded on feat(infra): transcribe a stored video by id and write its captions #4134 to what ships today.
Whole web suite: 8,197 pass. The only failures are two files that fail on this machine and pass in CI. Real MySQL: 46 of 46.
Merged main after feat(infra): transcribe a stored video by id and write its captions #4134, fix(infra): bind upload tokens to their key, cap part numbers, sniff past ID3 tags #4138, perf(web): cut Cap Infra billing reads on the console, usage API, ledger and storage cron #4142, fix(infra): charge transcripts deleted during speech and cap running transcripts per app #4143 and fix(infra): refuse a URL transcript source that is not media from its first bytes #4150 landed. Only the docs test conflicted; main's version is kept. Developer, infra and agent unit suites 2,555 pass, fast path tests 18 of 18, real MySQL 46 of 46. The workflow bundle builds,
runTranscriptFastPathis registered and the transcribe module in the flow bundle has no database code.A retry of the whole fast step now resumes from what the earlier attempt saved, as the separate steps did. If the audio was already measured and saved, it skips the source-size hold and goes to transcription, so a retry never asks for more credit than extraction left held. A row this run owns that was deleted while processing is settled from its saved result (charged once, hold released) or, with no result, ended free. Only a row this run never claimed is left alone.
So that a saved result survives until that retry, deleting a transcript that is still processing leaves its files to its run, which removes them when it ends. The 6 hour expiry removes them if the run never returns. Queued, uploading, complete and failed transcripts lose their files at once as before.
Developer, infra and agent unit suites 2,561 pass, real MySQL 46 of 46, workflow bundle builds. The five new tests fail on 713b72f.


Confidence Score: 5/5
The PR appears safe to merge; no new actionable issue was established.Summary
Short transcripts now claim, prepare, extract, transcribe, and settle in one workflow step. Longer work and interrupted stages continue through the existing separate steps.
Reviews (7) · Last reviewed commit: "Merge branch 'main' into perf/infra-tran..." · Reviewed by Greptile