Repository navigation
perf(producer): chunks read remote videos from their link instead of copying them - #5449
robinebers wants to merge 1 commit into
Conversation
d5780fb to
415cfd9
Compare
|
What changed since the first version Code-reviewed by GPT-6 Astra and human-reviewed with a short AWS Lambda test. The review found four problems; all are fixed:
One more thing came up while testing: Bun's Lambda test of this exact commit: 1,000 frames of 4K from two 50-minute HEVC recordings on signed S3 links. Cost $0.119, a 1 MB plan with no video copied, and the same decoded picture and sound as the first version. The description is updated with the details. |
…d of shipping them A distributed plan that defers extraction now leaves a remote <video> source at its URL. Each chunk reads only the byte ranges of the frames it renders, and its page never fetches the video. The planner no longer downloads the source, and no copy of it is shipped to any chunk. A URL is read in place only when it is public HTTPS, answers a range request without redirecting, carries a strong entity tag and holds an MP4, MOV, Matroska or WebM file, so never a playlist whose segments FFmpeg would fetch itself. The plan asks once per URL, so compile, probe, extraction and audio agree on the answer. Anything else is downloaded exactly as before. Local renders are unchanged. FFmpeg never reads the URL itself. Each process serves the sources it reads in place from a relay on 127.0.0.1, which fetches them with the downloader's checks on every redirect hop and with If-Match on every request, so a redirect cannot reach a private or plain-HTTP address, and a source replaced mid-render fails instead of mixing two versions. A relayed read that fails partway fails the FFmpeg or FFprobe run that made it, even when FFmpeg exits cleanly with what it had. The relay asks for growing windows of the range FFmpeg wants, so a read FFmpeg stops early stops the transfer within one window. Co-authored-by: Cursor <cursoragent@cursor.com>
415cfd9 to
320023b
Compare
|
Minor follow-up from a second review, pushed as 320023b:
Checked locally: the same final video as |
|
this has ballooned a little too much. closing this, reworking, and opening a new one. |
What
When a render is split into chunks (the AWS Lambda path), a
<video>given as an HTTPS link is no longer downloaded by the planner and copied to every chunk. Each chunk reads only the part of the video it shows, from the link.Local renders on one machine are unchanged.
Why
Today the planner downloads the whole video, and every chunk that shows it gets its own copy, even when the chunk only shows a few seconds. With long recordings, that copying is most of the render's time and cost.
On a 20-minute 4K edit made from 50 minutes of screen and camera recordings, rendered on AWS Lambda:
mainRelated work
Refs #5290. Its notes leave this as a follow-up: "Reading only the byte ranges a chunk needs would cut that and is left for a follow-up."
How
The planner checks each video link once. It asks for the first 512 bytes. The link is read in place only if all of these hold:
Anything else is downloaded exactly as it is today.
The plan stores the link and its ETag instead of a file path, so nothing is copied to the chunks.
FFmpeg never reads the link itself. Each process (the planner and each chunk) starts a small relay on
127.0.0.1, and FFmpeg reads the video from there. The relay fetches the real link and:If-Matchon every request, so a file replaced mid-render fails instead of mixing old and new frames;The chunk's browser is told not to fetch those exact links. The chunk supplies the frames itself, as it already does for extracted videos.
The link is checked once per render. Compile, probe, frame extraction and audio all share one answer, so they always agree on which links are read in place.
Review
If-Match. Now every read goes through the relay withIf-Match, so it fails instead.If-Match, so old video could be paired with new audio. Same fix.Questions you might have
Will this break anything that works today?
No. A link that fails any check is downloaded as before. A render on one machine never runs the check.
Why a relay instead of handing the link to FFmpeg?
FFmpeg follows redirects with no way to check where they go. And the first version only added
If-Matchon some reads, which is how findings 2 and 3 slipped in. The relay is one place that does both, for every read: frames, the duration probe and audio.Is the relay reachable from outside?
No. It listens on
127.0.0.1only, serves only the links this render chose to read in place (each under a random path), and only answersGET.What if the video changes during the render?
Every read carries the ETag, so a changed file fails the render with a clear error instead of producing a mix. Weak ETags (
W/...) don't qualify, becauseIf-Matchnever matches them; those links are downloaded.What about signed links that expire?
This is the one new requirement. A signed link now has to stay valid until the last chunk finishes, not just until planning ends. If it expires mid-render, the chunk fails with an error; it doesn't render wrong frames.
Does it put more load on the media host?
Far fewer bytes, a few more requests. Each chunk now makes a handful of range requests instead of the planner downloading the whole file.
Why read in growing pieces?
FFmpeg asks for "everything from here on" and hangs up once it has enough. Node's
fetchslows down when nobody reads, but Bun's reads the whole rest of the file anyway (the Cloud Run image runs on Bun). Reading 3 seconds from the middle of a 73 MB file:What about the frame cache?
Frames read from a link skip the local frame cache, because that cache is keyed by local files. Downloaded sources still use it.
How big is it?
About 590 lines of code (the relay file is 300 of them) and 550 lines of tests, across 27 files, plus one docs sentence in
docs/deploy/aws-lambda.mdx.Test plan
Same render on
mainand on this branch. A local HTTPS server with range and ETag support served a 73 MB video. The render was a 12-second clip in 4 chunks, using the plan v2 path, run under Bun (the worst case for the relay, see above).mainmainOn AWS Lambda. A 1,000-frame 4K render (40 seconds, two 50-minute HEVC recordings read from signed S3 links) of the version before the second review. The second review's fixes were checked locally: same final video as
main. It also carried the 25 fps support from #5423, which that footage needs.The full 20-minute edit in the table at the top was rendered with the first version of this change.
New unit tests.
If-Match, passes a 412 through, refuses redirects to a private address or to plain HTTP (without fetching them), reads in growing pieces, cuts the connection when the link sends less than it promised, and serves only links it was given. A link that fails partway is reported to the run that read it; FFmpeg hanging up normally is not.<video>links and downloads every other source. The probe doesn't load the videos read in place.Existing suites. Typecheck, lint, format and the pre-commit checks pass. On my machine, 7 frame-sampling and colour tests and 1 audio-level test fail, and they fail the same way on
main(most likely my local FFmpeg build).