Install
openclaw skills install @tobewin/paper-collage-remotionCreate, revise, or render layered paper-cutout / collage animations in Remotion. Use for videos where backgrounds, characters, props, and foreground decorations need to be independent PNG layers with staged entrances, parallax, cut-paper outlines, occlusion, captions, narration, and audio effects; especially historical explainers, knowledge videos, brand stories, and city or character narratives.
openclaw skills install @tobewin/paper-collage-remotionBuild depth from independently movable layers, not by applying camera motion to a single flattened illustration. Use Imagegen or another image model only for source assets; use Remotion as the timing, compositing, and rendering system.
For a new project, copy assets/remotion-starter/ into the project root. Fill script.json, add public assets at the declared paths, and run scripts/validate_project.py script.json public before opening Remotion Studio. Use examples/tang-dynasty/ only as a concrete visual reference, never as a required subject or style.
Turn the script into a shot list. For every shot, record: narrative beat, duration, focal subject, viewpoint, subject order, layer list, and caption/audio cue. Design around one dominant subject per shot.
Use this depth order unless the shot has a deliberate exception:
Do not put a main character into the background plate. Generate each character/prop as a complete, standalone layer; keep head, hands, feet, and held props inside the canvas.
Generate background plates without people. For each cutout, request a solid chroma background, a defined facing direction, no text/watermark/shadow, and a light paper outline. Prefer a source sheet only when it improves character consistency.
For a green-screen source, remove green before splitting. Tune tolerance against the actual source and inspect hair, sleeves, and thin props:
python "$CODEX_HOME/skills/paper-collage-remotion/scripts/key_to_alpha.py" \
public/assets/source/close-six-green.png public/assets/source/close-six-alpha.png --tolerance 92
Then split the transparent sheet:
python "$CODEX_HOME/skills/paper-collage-remotion/scripts/split_sheet.py" \
public/assets/source/close-six-alpha.png public/assets/layers close 6
It supports either --columns or --rows for non-square grids, --padding for a shared gutter, and --no-trim when every cell must retain the same dimensions. Inspect several outputs for clipped limbs and non-transparent backgrounds before animating.
Use an asset manifest in the project rather than scattering raw paths:
type LayerRole = "primary" | "secondary" | "tertiary" | "foreground";
type Layer = {src: string; role: LayerRole; x: number; y: number; width: number; delay: number; z: number};
Use the starter's script.json as the manifest. Keep all scene duration, copy, background paths, and layer values in that file; use code only for reusable rendering behavior. This makes the same animation system usable across subjects.
Place all layers at their final positions without entrances. Make the primary subject visibly largest; decrease size, contrast, and motion with narrative importance. Verify that feet share a plausible ground line, faces and props remain unobscured, and foreground objects create intentional overlap.
Give cutouts a consistent outline and elevation shadow:
filter: "drop-shadow(4px 0 #f5eedc) drop-shadow(-4px 0 #f5eedc) drop-shadow(0 4px #f5eedc) drop-shadow(0 18px 9px rgba(20,15,12,.32))"
Reference all public assets through staticFile() and render images with Remotion's Img component. Keep all movement frame-driven with useCurrentFrame() and interpolate(); do not use CSS transitions or keyframe animations.
Ensure the project entry file calls registerRoot(RemotionRoot); pass that entry file (commonly src/index.ts) to the Remotion CLI, rather than a component file.
Stage the build: primary first, then supporting characters, then distant/foreground details. Offset every entrance; avoid a full cast appearing on the same frame. Use Sequence from={delay} for audio/entrance coordination.
Start from these visual ranges at 30 fps and tune to the shot, not to an arbitrary formula:
| Role | Entrance travel | Rise | Start scale |
|---|---|---|---|
| primary | 78 px | 55 px | 0.86 |
| secondary | 58 px | 38 px | 0.90 |
| tertiary | 38 px | 22 px | 0.95 |
| foreground | 50 px | 30 px | 0.92 |
Use eased interpolation for an entrance and a small continuous bob after landing. Keep background drift and push-in near 1%; foreground may move slightly faster than the subject to make parallax readable. Keep positional values inline in the relevant style block when Studio editability matters.
const local = frame - layer.delay;
const roleMotion = {
primary: {distance: 78, rise: 55, startScale: 0.86},
secondary: {distance: 58, rise: 38, startScale: 0.90},
tertiary: {distance: 38, rise: 22, startScale: 0.95},
foreground: {distance: 50, rise: 30, startScale: 0.92},
};
const enter = interpolate(local, [0, 14], [0, 1], {
easing: Easing.bezier(0.16, 1, 0.3, 1),
extrapolateLeft: "clamp", extrapolateRight: "clamp",
});
const travel = roleMotion[layer.role].distance;
const bob = local > 14 ? Math.sin((local - 14) / 11) * 3 : 0;
<Img src={staticFile(layer.src)} style={{
position: "absolute", left: layer.x, top: layer.y, width: layer.width, zIndex: layer.z,
opacity: enter,
translate: `${(1 - enter) * travel}px ${roleMotion[layer.role].rise * (1 - enter) + bob}px`,
scale: interpolate(enter, [0, 1], [roleMotion[layer.role].startScale, 1]),
filter: paperCutoutFilter,
}} />
Let narration duration set each scene duration. Use one caption track at the bottom; keep it away from feet and key props. Mix music below narration. Align impact sounds with primary entrances, whooshes with secondary entrances, and light ticks/pops with tertiary details. Use Audio from @remotion/media and staticFile() for local audio.
Use Remotion Studio for timing and a still render for a fast layout check. Render the MP4 only after reviewing static composition and entrances.
npx remotion studio
npx remotion still <composition-id> --frame=150 --scale=0.25
npx remotion render <composition-id> out/final.mp4
ffprobe -v error -show_streams -show_format out/final.mp4
ffmpeg -ss 5 -i out/final.mp4 -frames:v 1 check-05.png
Check: no cut limbs; correct facing directions; clear size hierarchy; correct z-order; staggered entrances; captions unobstructed; sound onset on its intended frame; audio stream, dimensions, and duration valid.
Run the bundled validator before rendering. It checks the scene schema, asset paths, PNG alpha channels, layer bounds, required role motion, and expected duration.
python "$CODEX_HOME/skills/paper-collage-remotion/scripts/validate_project.py" script.json public
Treat warnings as review items: an intentional off-screen entrance is fine; a final position outside the frame, missing alpha, or absent asset is not.