agentleFS
Imaginative-PromptingImaginative-Prompting/claude-video-skills/skills/rendering/SKILL.md

rendering

Skill9 starsChanged 12 days agoMITView on GitHub

Render, export, master, 4K, draft, stills, chunk, motion blur, shutter samples, BT.709, color tags, mux, AAC, ffmpeg, concat, join, blank frames, audio lag: use when rendering drafts, stills or masters of a Remotion + three.js video, joining render chunks, muxing the song, or when renders come out blank, shifted in color, out of sync or a frame off. Runs one GPU job at a time through a queue, renders in short chunks, separates drafts from finals, makes motion blur from shutter samples, keeps BT.709 everywhere, muxes a muted picture with the WAV, and joins frame-exactly.

4 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

5 rules. 0 are common, 2 are distinctive, and 3 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Every render, from a single still to the 4K master, and every join or mux.

    line 10
  2. Very specific:

    Pin Remotion: Every remotion and @remotion/* package at one exact version.

    line 21
  3. Very specific:

    No -shortest: when putting audio under a copied picture: pad or trim the audio, then count the output's frames.

    line 88
  4. Distinctive:

    After every render, before posting it (these take seconds):

    line 104
  5. Distinctive:

    Every join, frame by frame, against its source parts.

    line 111

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Rendering

When to use

Every render, from a single still to the 4K master, and every join or mux. The checks on what comes out are in render-checks.

Before you queue

  • Prove it renders on the CPU first. Typecheck, load every module, bundle the whole project (not just your scene), and actually render the React tree once. A timeline scene with no component behind it threw at frame 1, after more than two hours waiting in the queue.
  • Render from a frozen copy. A queued render renders the code as it is when it starts, not when it was queued. For anything long, copy the project (an APFS clone on macOS, cp -c -R, shares the file data until something changes), give the copy its own id, and render from it.
  • Pin Remotion. Every remotion and @remotion/* package at one exact version.
  • Fonts: static font instances, loaded through one manifest that holds the frame until they're ready. A font loader started inside a component held its render open until the timeout on every frame.
  • Bake heavy meshes ahead of time. A scene build longer than the render's load timeout (30 s by default) fails.
  • Whole pixels: a scale that gives 720.036 lines is refused by the stitcher. Use exact fractions.

One GPU job at a time

  • Two headless Chrome renders at once lost their WebGL contexts and blanked frames. Run every render, stills batch, bench and in-browser scene probe through one queue: a lock, plus a waiting list that the director can reorder. Light checks of an ordinary web page can run beside it.
  • Stills go ahead of renders. Keep each render ticket to about 15 minutes and each stills ticket to about 5, so nobody waits long behind anyone.
  • Log every job's full output to a file. Never pipe it through tail -1: the error scrolls away and costs another round in the queue.

Drafts and finals

  • Drafts: 720p, with the shutter capped (8 samples worked).
  • Finals: full resolution and full samples.
  • Trust a draft shortcut only after a draft still matches a full-size still of the same frame. Rendering drafts at a lower pixel ratio darkened an ambient-occlusion pass and showed up as a pop at a join.
  • Before a 4K master, render 4K stills of a frame in every world and effect, downscale them to 1080p and compare them with 1080p stills. Anything sized in output pixels (grain, line widths, bloom radius, glints, canvas text) changes; scale it by the frame's height ÷ 1080 so 1080p stays identical.

Motion blur

  • Real motion blur comes from shutter samples: render several sub-frame samples per frame across a 180° shutter (half the frame interval) and average them. Whether the samples sit centered on the frame or trail it is your renderer's choice: know which, and log the actual sample times. Fast whips and sharp lettering need more samples: letters stay sharp at about 4 px of movement per sample, not 12.
  • Prove the mixer. Render a test where each frame shows its own number: the mix for frame k must show only k's samples. An old ffmpeg's frame mixing averaged forward and showed frames k and k+1 at once.
  • Movies and stills can sample different times. In one film no movie sample ever fell on a whole frame, while a still was exactly the frame, so a bug that showed only in movies lived at sub-frame times. Render single samples as stills to find one.
  • Render speed (three.js in Remotion): don't re-render the whole frame after every canvas-texture draw. Calling React Three Fiber's advance() on each texture draw rendered every frame 4–5 times. Instead, hold the capture after a draw and render once more after every draw in the frame's commit: two renders a frame instead of 4–12. Never skip that last render: a version that skipped it captured canvases cleared after the first render as pure white frames.

Chunks and joins

  • Pre-roll every chunk. A chunk's first frames can come out cold, with post-processing and lighting missing until the scene warms up. Start each chunk about 12 frames early and drop the run-in, and compare the first frames after every boundary with the frame before it, in color as well as brightness.
  • 4K chunks as ProRes 422 HQ (-c:v prores_ks -profile:v 3 -pix_fmt yuv422p10le): intra-frame, so they join with no seam.
  • Never join parts by stream copy (concat -c copy). It started one picture 21 ms late and gave other parts irregular packet durations that players turned into repeated and dropped frames. Decode in order and encode once: -vf setpts=N/(30*TB) -fps_mode cfr -r 30 (put your own frame rate in place of 30).
  • Splicing a partial re-render: everything the change adds must be out of frame at the splice frame, or it pops. Prove the seam by comparing the old and new frames just outside the kept span.

Color

  • BT.709 everywhere. ffmpeg 8 keeps the frames' own color tags over the output flags, so stamp them in the filter chain: setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709. Then check all three tags with ffprobe.
  • PNG → mp4 needs scale=out_color_matrix=bt709, or it's encoded as BT.601 (a green shift against everything else).
  • Raw frames piped into an encode: tag the input (-colorspace bt709 -color_range tv before -i -), or the scaler guesses and lifts the levels.

Audio

  • Render the picture muted, then mux the master WAV from time 0 in a separate step. Remotion's own AAC came out 42.7 ms late in these renders.
  • No -shortest when putting audio under a copied picture: pad or trim the audio, then count the output's frames.

Failure modes

  • A pass that hides garbage: a 720p draft with 55 of 101 frames blank passed its QC. Scan every render.
  • The wrong scene rendered: missing props drew an old version of a section, and it passed its checks. Diff a patch's pre-roll frames against the cut before handing it over.
  • A mount gate added for speed changed the picture on every frame it covered. Render one frame inside the gated span before and after, and diff it.
  • Canceling a render by stopping its shell left npm, node and Chrome rendering outside the queue. Kill the whole process tree, then confirm the queue is free.
  • Frame-exact extraction: -ss isn't frame-exact. Use select=eq(n\,k) with -fps_mode passthrough, and assert the number of frames you got.

Verify

After every render, before posting it (these take seconds):

  • ffprobe: the frame count, avg_frame_rate exactly 30/1 (or your rate), color tags bt709 / bt709 / bt709 with tv range, start_time 0 on both streams.
  • A blank, frozen, black and magenta frame scan (render-checks).

Then, before it's spliced into the cut or used for a master:

  • The first frames after every chunk boundary against the frame before it.
  • Every join, frame by frame, against its source parts.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.