Repository navigation
feat(droid-control): render showcases with fframes instead of Remotion - #55
Open
factory-droid-dev[bot] wants to merge 4 commits into
Open
factory-droid-dev[bot] wants to merge 4 commits into
factory-droid-dev[bot] wants to merge 4 commits into
Conversation
…emotion
The showcase composition now renders through fframes, a Rust SVG video
framework, instead of Remotion + headless Chrome. Every layer of the
Showcase composition is ported 1:1 (presets, palettes, title card, window
chrome and layouts, zoom/spotlight/callout effects, keystrokes, sections,
code annotations, all five transition styles, noise/grade/watermark, Droid
outro), checked frame by frame against Remotion stills.
The droid-showcase binary owns what render-showcase.sh used to do in bash
and Python: props validation and defaults, clip staging, .cast conversion
via agg, probing, rendering on every core, the H.264 encode, and work-dir
cleanup on exit or SIGINT/SIGTERM. render-showcase.sh keeps its CLI and
becomes a thin build-and-exec wrapper. The resolved render plan is printed
as one `showcase plan: {...}` stderr line, which the helper tests assert on
against the real binary instead of an npx shim.
Rendering no longer needs Node, npm deps or Chrome, embeds Geist so output
is identical across machines, and drops the Remotion company license
requirement.
Co-authored-by: factory-ain3sh <ainesh@factory.ai>
…parallel Rendering the 25 s demo on a 2-core (4-thread) box goes from 3m17s to 15.6s wall, with the same pixels within 1-2 levels (PSNR vs the previous stills 49-56 dB, vs the previous video 53-59 dB per plane). - Frames are composited in Rust on 8-bit premultiplied pixels: the background, grade (grain, tint, vignette), windows, shadows and clip are blended in fixed point, compiled for every SIMD level with runtime dispatch (multiversion). Only vector chrome and overlays go through svgr. - Static layers are baked once (shadows, blurred with the Rust box blur that matches svgr's) and resampled once to the pixels they cover. Window chrome and clip frames are reused while the window holds still. - Frosted backdrops downscale and blur just the region a panel shows. - Render workers convert frames to yuv420p themselves, so ffmpeg only runs x264 and the pipe carries 3 MB per frame instead of 8 MB. - Casts are staged losslessly with the ultrafast preset: no second lossy encode, and staging drops from ~8 s to ~1.5 s of CPU. Co-authored-by: factory-ain3sh <ainesh@factory.ai>
The ASCII art inherited from Remotion drew D as a square box (reading as O) and gave R a one-character-wide leg. D now has a flat stem and a stepped curve, O has rounded corners on both sides, and R has a closed bowl with a full-weight diagonal leg. Letter gaps are uniform and the block no longer carries leading spaces that pushed it off-centre. Co-authored-by: factory-ain3sh <ainesh@factory.ai>
The square O reads heavier next to the redrawn D and R, which still keep their distinct shapes. Co-authored-by: factory-ain3sh <ainesh@factory.ai>
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.
Description
What
This PR moves the droid-control showcase renderer from Remotion (React and headless Chrome) to fframes (Rust and SVG), with the same composition, props contract and
render-showcase.shflags. Existing props JSON and render commands work unchanged. On the 761-frame 1080p demo the render takes 15.6s on 4 threads, and its output matches stills compared frame by frame against Remotion renders of the same props.remotion/(React, Node, npm deps, Chrome)fframes/crate,droid-showcasebinaryrender-showcase.sh.castvia agg, ffprobe, parallel render, libx264 encode, cleanuprender-showcase.shcargo build(a no-op once built) andexec, same flagsnpxexitedspotlighteffectnpm install, ChromeWhere the 17k lines are. Most of the diff is the deleted Remotion app and two lockfiles. 23 files carry behavior.
remotion/package-lock.jsonfframes/Cargo.lockfframescrate and the wrapper scripttests/test_render_showcase.py, rewritten against the real binaryAlso binary: seven Geist font files added and the background image moved into
fframes/media/.The 28% that carries behavior, grouped by the change it makes:
main.rs,props.rs,clips.rs,stage.rs,timing.rs,render.rs,Cargo.toml,lib.rs, andrender-showcase.sh(273 to 32 lines). The binary validates props, stages clips, probes durations, renders frames on every core and encodes them.showcase.rs,scenery.rs,title.rs,content.rs,overlays.rs,transition.rs,outro.rs,code.rs. Each is the port of one or more Remotion components.svg.rs,composite.rs,raster.rs,motion.rs,theme.rs,fonts.rs. These hold SVG helpers, the Rust compositor, easing, palettes and presets, and font loading.Why
The migration off Remotion was requested with no loss of functionality or tooling. Rendering no longer needs a browser or a Node toolchain, the output looks the same on every machine because the fonts ship with it, and the Remotion team license no longer applies.
How
showcase.rsis the single fframesVideo. It composes the layer modules from typed props (props.rs: defaults and validation with field-named errors). Effects with no SVG equivalent are composited in Rust instead of rasterized as SVG filters: the colour grade, layer blending, the frostedbackdrop-filtercard, and shadows baked once with a box blur.render.rsrenders blocks of frames on every core, converts each frame toyuv420pin its worker, and pipes frames in order to ffmpeg.Related Issue
None. Requested in Slack by @factory-ain3sh.
Reviewer Guide
Diff shape: see the composition table above. 4,795 lines in 23 files are the review; the rest is deletions, lockfiles and docs.
Three passes:
74280b5, the port):props.rsagainst the deletedremotion/src/lib/schema.ts, thenmain.rs,stage.rsandrender.rsfor the pipeline. Check that every props field keeps its default and validation.b42fb6d, perf):composite.rsandraster.rs, then howcontent.rsandsvg.rscall them. Check that cached chrome and clip frames are keyed on everything that changes them.content.rsandtransition.rsin full, spot-check the rest against their Remotion components.Review depth: Deep. This is a full renderer rewrite.
Read order:
fframes/src/showcase.rs: how the layers compose per frame.fframes/src/props.rs: the props contract.fframes/src/main.rs,stage.rs,render.rs: the pipeline from CLI to encoded mp4.fframes/src/composite.rs,raster.rs: the Rust compositor and blur.tests/test_render_showcase.pyand the unit tests in each module.Deliberate behavior changes:
spotlightnow dims the frame (see the table above).clipsandclipDurationare ignored if present. Clips come only from the positional arguments and the binary probes their durations, as before.GlitchTitle,ActiveInputPulse,DynamicShadowParallax,GlowLines,WindowReflection) are not ported.GlitchTitlewas documented as needing a custom composition.Risk & Impact
cargo build. Without themrender-showcase.shfails at the build step before staging anything. README, theshowcaseatom, and CI list the new prereqs.Performance Evidence
Workload: the 761-frame 1920x1080 demo: one 17.85s
.castclip,factorypreset,compactfidelity, with keystrokes, sections, a callout, zoom, spotlight, a code annotation and thelight-leaktransition.Conditions: 2 cores / 4 threads (Xeon), wall time for the whole
render-showcase.shrun including staging and encode.yuv420pconversion in render workersultrafastx2644bb3857)Per-frame render time on one thread fell from about 872ms to about 36ms (about 19ms on frames where only the clip changes). Most of the remaining time is the final libx264 encode (about 19s of CPU spread across cores).
Quality: PSNR against output from before the perf commit is 49 to 56 dB on stills and 53 to 59 dB per plane on the full video, the level of encoder noise.
Rerun:
scripts/render-showcase.sh --props demo.json --output /tmp/demo.mp4 demo.cast.Verification
Behavior verified @
4bb3857: the demo renders 761yuv420pframes at 1920x1080 in 15.65s.Behavior verified @
0344b9a: the outro still shows the redrawn D and R next to a square O.Behavior verified @
74280b5: stills compared frame by frame with Remotion renders of the same props: title, content, overlays, everytransitionStyleat its midpoint, outro, and the side-by-side macOS layout.Regression coverage:
tests/test_render_showcase.py(8 tests, real binary): same-basename clip staging and work-dir cleanup; fidelity mapping to size, CRF and preset, including the--fidelityoverride; refused inputs fail before staging; concurrent renders keep separate work dirs; SIGTERM cleanup;.casttimeline preserved through agg; and real encodes (pixel format, BT.709 tags, exact frame counts, first and last clip-frame colours, content shorter than a transition).composite::tests::blur_matches_svgr_gaussian_blurpins the Rust blur to svgr's), and yuv conversion.Not tested: the five unported components (never rendered by the composition).
Standard validators:
cargo fmt --check,cargo clippy --all-targets --release -- -D warnings,cargo test --releaseand the Python suite pass locally and in CI.