← All Engineering Notes

When a Remotion Render Passes but the Video Is Still Wrong

A 526-second film rendered cleanly while its pictures drifted away from the words. Every check it had could confirm the film was produced; none compared picture against narration.

Working practicelessonsocraticblockUpdated

VerificationVideoTestingProcess

The film: 526 seconds, 15,780 frames, and a PASS verdict from its own gate.

“Narration moves, the picture doesn’t.”

That was the complaint about a film described in Remotion (https://www.remotion.dev/), a framework for making videos with code instead of an editing timeline. The film ran 526 seconds (just under nine minutes) at 1920 by 1080, 15,780 frames at 30 frames per second. It rendered without errors, and it passed the checks it was built with. None of that was ever in dispute. The trouble was that at some moments the picture and the words were describing different things.

The interesting part was not that something had gone wrong. It was that the checks in place could not have noticed.

What a render does and does not establish

A video described in code is a composition: its dimensions, frame rate and duration, plus the components that decide what appears at each frame. The renderer supplies a frame number, and the code decides what belongs at that number.

For this film the material came from a game project that really existed. One continuous narration track ran the whole length, the visuals were arranged around it, and captions were drawn across the film rather than inside each scene.

That arrangement means one timeline exists in several forms at once. There is the audio, where words begin at moments that can be measured. There are the narration segments written beside it. There is the structure of visual beats, each one a planned shot paired with a particular piece of speech. And there are the rendered frames with their captions.

Each of those comes from a different step, and each can be right while another is wrong. A successful render establishes that the film was produced. It says nothing about whether the picture on screen belongs with the words being spoken at that moment. Those are two different claims, and only the first one comes for free.

The gap in the middle of a passing run

The same gap can open in any film described this way. A line of narration belongs with a particular shot. The audio can be right, the shot can render correctly, the total duration can be exactly as declared, yet that shot can still arrive a moment early or a moment late.

Nothing about any single file shows it. Watching from start to finish, a short separation between word and picture can look like a deliberate cut; someone sees a transition and keeps watching. A check aimed at one moment asks a narrower thing: whether this shot belongs with this line, at this position.

The film’s own checks were sharp in a way worth showing, because it is what a useful failure looks like. One recorded failure read, in full:

FAIL frames look entirely black outside any declared near-black shot: [15, 43]

That is a claim someone can re-check. It names a range of frames and a reason, and it says where to look. A passing check can be just as specific: frames 222 to 243 correspond to frames 360 to 381 of the source material.

“Something seems out of sync” is not yet a diagnosis. A position, a file, or a version is where the work of finding out can begin.

Building the comparisons that were missing

The correction was not a new renderer. It was a chain of comparisons between the several forms of one timeline.

The structure of visual beats was checked against the narration segments, so a shot planned for one part of the speech could not sit under another part. Sampled frames were compared against the narration lines expected at those positions, which turns “this looks about right” into “the expected thing is here”. Quoted narration was compared exactly against its source text, because a film presenting real material cannot paraphrase it and stay honest. The captions were checked against the frames and their timing.

Each of those checks reported a position when it failed, and that is what made them worth having. A failure that names frames, a file or a version hands the next person a place to start instead of an impression to argue with.

The checks did not remove the need to watch the film. A sampled comparison sees only the positions it was given, and it can evaluate only the conditions it was written with. So the film was also watched once, at normal speed, with sound, by someone who had not built it.

The renderer was the obvious suspect

When picture and word drift apart, the renderer is the first thing anyone suspects. Perhaps it cannot hold a composition this long. Perhaps another tool would do better.

The conclusion recorded at the time was narrower and less convenient: nothing in the complaint came from an engine limit. Producing a film and verifying what it means are two different jobs, and no renderer supplies the comparison between them.

Remotion was kept, not because it had beaten the alternatives, but because it had been proven against this film: the frames had been rendered through the gate, and the comparisons that were missing now existed as measured checks. The improvements with real return lay elsewhere: narration aligned to the measured starts of spoken clauses rather than to timecodes someone typed in, visuals faithful to material that actually exists, and verification that pairs a mechanical check with a person watching the result.

The same question, asked of the paperwork

The next piece of work kept the film’s machinery as a set of files a later film could start from: a minimal composition that really renders, the rendering gate, the verification scripts, the design tokens, and the notes on engine choice. That kit carries its own paperwork, and the same question applies to it. Because it was not its own git repository, its version identity lived in a generated file that lists every file with its hash. That list is what makes one version of the kit distinguishable from another.

Reviews ran under a written contract: the requirements to be tested, the evidence expected for each one, and a rule that the author could not approve their own work. Reviewers worked read-only, and any requirement needing an operation no one had carried out had to be marked UNVERIFIED, along with what would settle it.

Five review rounds followed, each under a larger contract. One class of finding appeared in three of them.

The first contract froze the kit and described the file list as holding 22 files. By the end it held 31. A pin file advertised a hash for the kit, and by the time a report was read the list had been regenerated, so the hash described an earlier version. In another round, a report described one hash while a newer file sat beside it.

None of those findings showed the kit behaving incorrectly. Each was a record that was accurate about a version that no longer existed, sitting beside the files that had replaced it. A hash can describe an old version precisely. A report can describe a check that really ran. Neither tells you about the thing in front of you now.

What the kit does about it

The kit’s answer to that class of failure is a deliberate duplication with a check across it. The timeline is declared in the composition code, because the renderer requires it there. The deliverable (output path, codec, quality settings, audio floor) is declared in a separate contract file that the render script reads. Two places, on purpose. When the two disagree, the gate fails, and that failure is the point: the disagreement is the signal, not a fault in the checker.

Nothing falls back to a built-in default. A contract that is missing, unreadable, or simply not this kit’s contract is a hard failure in every case. A declaration no one wrote is not a contract, and no verdict is printed for a file no one declared anything about.

Two of the kit’s rules came straight out of this film. A check that passes at exactly its threshold has not passed: the first version cleared its own silence check at exactly -45.0 LUFS, which is a number to fix rather than a number to admire. And a gate that cannot run is a failure rather than a skip: being unable to check is itself a result.

The pin works the same way. The kit’s self-test verifies that the file list still matches the files, so it fails on a kit that was edited without regenerating the pin. The easy move in that moment is to regenerate the pin and clear the failure, which removes the check instead of the problem. The kit’s own instruction is to avoid that move.

The kit also carries a short list of the specific things this film got wrong, so the next one does not rediscover them: a frame total that was wrong in a way that surfaced only as black frames at the end, a shot that held one static panel across three separate spoken ideas, a check that passed with no margin, and a generator that paraphrased a quotation rather than refusing to invent it.

What a machine cannot settle

The film’s gate says the boundary better than any commentary, and it says it in its own output: every requested check passed, and that is a mechanical pass only. It cannot tell you the video is good, and it does not replace watching the film at normal speed.

That is the line. A mechanical check can compare two declared things with precision, and it cannot judge whether the result is worth watching. Both are needed, and neither stands in for the other. The same boundary decides who can approve the work: the person who approves a film has to be someone other than the person who made it.

The same line runs through acceptance. The kit’s final fixes were applied and tested, but its final revision has not been through a fresh independent audit, and that gap is written down rather than covered over by a passing run. A completed fix and a closed finding are different claims: the first describes work that happened, and the second needs evidence that the problem is no longer there. Deciding that the second is true belongs to the owner, not to the person who made the fix.

There is one more move in the same family, and it is the cheapest of them. Proof that a check ran is not proof that it checked the relationship that matters. A check can be real, its result can be honest, and its subject can still be the wrong pair of things.

The lasting lesson

A record can be entirely correct about itself and wrong about the thing it describes. The frames existed, the hashes were right, the report was honest about the check it ran, yet none of that made the film correct.

So the question worth asking is not only whether a check passed. It is which two things that check compared.