blixvip/NullMotion

Play a finished motion-graphics ad in sync with the rough drafts it grew from, and export the breakdown as MP4.

Null Motion — What It Is

Null Motion is a free, local tool that shows you how a finished motion-graphics ad was built, draft by draft, frame by frame. It puts the final film on top of the screen and its rough black-and-white drafts underneath, all synced to the same timeline. You can study the breakdown or export it as a single MP4 video.

What It Does

  • Final film on top — the full ad plays on a loop, full width.
  • Drafts underneath — each section of the ad (Hook, Reveal, App, End card…) has a plain HyperFrames scene: black-and-white, Arial text, flat shapes, one simple move. It shows the idea before the polish.
  • Everything in sync — a playhead runs across the drafts. The draft for the section currently on screen follows the film frame for frame and gets an orange outline. The other drafts keep looping their own part.
  • One-click export — Download → Whole preview renders the film and its drafts frame by frame into a 1920-wide, 24 Mbps MP4 with the film's audio.

Quick Start

git clone https://github.com/blixvip/NullMotion.git && cd NullMotion
npm start                # Node 22+, nothing to install

Then open http://127.0.0.1:4343, pick a reference, and press Download → Whole preview (Chrome or Edge) to get the MP4.

No npm install, no API keys, no account. Three references ship with the repo, so it works on the first run.

Not the same as Null Studio. This repo is the free, local launch-film preview. Pause cuts, captions, and YouTube, Twitch, and Kick clips are Null Studio, a separate hosted product at nullmotion.com. They are not in this code.

Showcase

The repo ships three references with their drafts, ready to play:

Reference Length Drafts
Infinite · Global payments 0:30 7
SaaS · Launch sequence 1:02 8
Motion study 08 0:03 3

These clips come from other creators and are used as examples. They are not claims of commissioned work.

How It Works

  1. Sections. scripts/plan-sections.mjs splits each reference into 3–8 sections at real scene changes (using FFmpeg scene detection) and keeps every cut. Two-beat drafts switch at the exact moment the film cuts.
  2. Drafts. public/drafts.mjs is a small HyperFrames engine: each draft is a 640×360 HTML scene on a paused GSAP timeline. A section is described by one or two beats (text, logo, phone, window, input, chat, cards, list, chart, cloud…), written to match the real frame's layout, text, and timing.
  3. Playback. The page drives every draft's timeline from the film's clock. The active section follows the film, the others loop.
  4. Export. A hidden copy of the film plays at half speed. requestVideoFrameCallback captures every decoded frame, the drafts are drawn at that frame's exact time, and WebCodecs encodes it at 24 Mbps with the frame's own timestamp. The audio is copied from the reference, and mp4-muxer writes the MP4. Nothing is recorded in real time, so no frames are dropped.

Requirements

Needed for
Node.js 22+ Running the local server (npm start). No dependencies to install.
Chrome or Edge MP4 export (WebCodecs + requestVideoFrameCallback). Playback works in any modern browser.
FFmpeg / ffprobe (optional) Importing your own references, planning sections, rebuilding the showcase, and extracting audio for imported references.
Python 3 (optional) scripts/import-motionclone.py.

Bring Your Own References

With Python, FFmpeg, and ffprobe installed:

python scripts/import-motionclone.py --source /path/to/MotionClone
node scripts/plan-sections.mjs      # sections + scene cuts + contact sheets

Imported media stays local in .local-media/ and public/references/ (both ignored by Git) and takes precedence over the showcase. Describe each section's beats in public/references/drafts.json. Undescribed sections get placeholder drafts. npm run showcase rebuilds showcase/ from the local library.

The importer creates non-destructive segments, extracts thumbnails, and hard-links the source videos when they are on the same drive as this repo (otherwise it copies them). Original files are only read. The server streams byte ranges, so seeking never reads a whole video into memory.

FAQ Highlights

  • Export needs Chrome or Edge — Firefox and Safari can play the preview but can't export.
  • Export takes at least 2× the film's length — the film renders at half speed so no frame is skipped. Keep the tab in front while it renders.
  • No sound on export? — For your own imported references, the server extracts audio with FFmpeg on first export, so FFmpeg must be on your PATH.
  • Import failed with "Invalid cross-device link" (EXDEV)? — Pull the latest main; the importer now copies the video when a hard link isn't possible.
  • "No data/ folder" when importing? — --source must point at the MotionClone project folder (the one containing data/), not a single video.
  • Port 4343 in use? — Set PORT and/or HOST, e.g. PORT=5000 npm start or HOST=0.0.0.0 npm start.
  • "Generation not connected"? — That's intentional. Generation, rendering services, and Premiere are not connected in this repo; the server answers those calls with 501 NOT_CONNECTED. The drafts are authored, not AI-generated.
  • Vertical clips, pause cuts, captions? — No. Those are Null Studio features.

Project Layout

public/demo.html · demo.mjs · demo.css   the preview page and exporter
public/drafts.mjs                        HyperFrames draft engine (beat kinds)
public/scraps.mjs                        hand-built drafts for the Interface reference
public/editor.*                          the earlier launch editor, at /editor
showcase/                                the three published references
scripts/                                 import, sections, showcase, waveforms, checks
server.js · media.js                     static server, media streaming, audio extraction
test/                                    server, media and editor tests
npm run dev     # restart on change
npm run check   # UI file checks
npm test        # node --test

Notes

  • The browser only calls this project's own origin.
  • The earlier launch editor (reference timeline, trimming, brand overlay) is at /editor, and the original Null Motion template gallery is at /index.html.
  • Bundled GSAP and mp4-muxer keep their licenses; see THIRD_PARTY_NOTICES.md. Brand artwork and reference footage belong to their respective owners and are not covered by the project license.

Contributing

Null Motion is small, has zero dependencies, and runs with npm start. They're looking for contributors:

  • Good first issues — small, scoped, with files to look at.
  • Help wanted — new draft beat kinds, export options, cross-platform testing.
  • Ideas and questions — Discussions or Discord.

Comment on an issue to claim it; pull requests are reviewed within a couple of days. Every contributor is credited in the release notes.

License

MIT. Bundled GSAP and mp4-muxer keep their own licenses (see THIRD_PARTY_NOTICES.md). Reference footage and third-party brand marks belong to their owners.

Community

Questions, help, feedback, release news, and your renders all go in the Discord. If Null Motion helped you, a ⭐ helps other people find it.

Related

  • Project
  • Project
  • Project
  • Project
  • Project