Pulse-of-Motion Model Loader
The two-widget loader that tells you the real frame rate of any video
- model
This is the unglamorous half of the ComfyUI-Pulse-of-Motion pack: a loader that does nothing visible except hand a model object to its one real sibling, the PhyFPS Detector. If that sounds boring, it is - but it's also the node that lets you answer a genuinely weird question: what frame rate is this video actually depicting, regardless of what the file says?
Here's the background in one paragraph. Video generators train on clips shot at very different real-world speeds and squash them all into standard container frame rates, so a "24fps" Wan output might depict motion that only looks physically right at ~36fps. That mismatch - "chronometric hallucination," from the Pulse-of-Motion paper - is why AI video so often reads as slow motion or oddly sped-up. The Visual Chronometer model behind this pack recovers the physical FPS straight from the pixels. This loader loads that model; the detector does the measuring.
What it actually does
Pulse-of-Motion Model Loader builds the fixed vc_common Visual Chronometer architecture (30-frame clips, 216×216), loads the checkpoint you downloaded, and returns a PULSE_OF_MOTION_MODEL object. It's a two-widget loader with a custom model type - same pattern as any checkpoint loader, just for a model nobody else loads.
The checkpoint is a PyTorch Lightning .ckpt, so the loader unwraps the state_dict, remaps the vae.* keys the original model carried, loads it strict=False in float32, and flips it to eval mode. In other words: there is one correct model file, in one correct folder, and everything else is plumbing.
The two inputs
- model_name - a dropdown listing every model in
ComfyUI/models/visual_chronometer/. If that directory is empty (or ComfyUI wasn't restarted after you filled it), the dropdown shows the telltale placeholder:[No models found - download from GitHub]. That string is your signal to go download, not to poke at the node. - device -
auto,cuda, orcpu.autopicks the best available in the order CUDA → MPS → CPU. Leave it on auto; the only reason to forcecpuis debugging.
Output
- model (
PULSE_OF_MOTION_MODEL) - not pixels, not a tensor, a bundle of model weights + device info. It only plugs into the PhyFPS Detector'smodelsocket. Trying to wire it anywhere else fails type-checking, which is the correct behavior.
Install
The pack ships as one repo (and the repo's README is upfront that it's vibe-coded - expect rough edges, but the two nodes work):
cd ComfyUI/custom_nodes
git clone https://github.com/DiXiaoO/ComfyUI-Pulse-of-Motion.git
Then the model, which is the part that actually matters:
mkdir -p ComfyUI/models/visual_chronometer
# download vc_common_10_60fps.ckpt from
# https://huggingface.co/xiangbog/Visual_Chronometer (Apache-2.0)
# place it in the folder above, restart ComfyUI
The folder auto-registers on load, so restarting after dropping the file in is what makes the dropdown populate. Install via ComfyUI Manager (search "ComfyUI-Pulse-of-Motion") or clone manually. About requirements.txt: it pins torch and torchvision, which your ComfyUI already has - running pip install -r inside ComfyUI's venv risks disturbing that. The node code actually imports einops and safetensors; opencv-python and av are listed but the shipped nodes never touch them. If Manager doesn't resolve everything, pip install einops safetensors is the surgical fix. (Also note the README's install line references ComfyUI-PulseOfMotion/requirements.txt, which doesn't match the actual clone folder name - one of those vibe-coded typos.)
Common issues
- Dropdown stuck on
[No models found - download from GitHub]- the.ckptisn't inComfyUI/models/visual_chronometer/, or you added it without restarting. The node registers that folder at import time, so it has to exist and be scanned before the dropdown builds. - Slow first run. Building the 30-frame architecture and parsing the Lightning checkpoint takes a few seconds and loads in float32, so don't expect fp16 speed. It's a one-time-per-run cost on a tiny model - nothing to optimize.
- A checkpoint that errors on load. The
strict=Falseload tolerates key mismatches, but if you grabbed the wrong file (or a half-finished download), you'll get missing/unexpected key warnings in the console. Redownload and verify the file size. It's a demo checkpoint by upstream's own admission - good enough to measure FPS in the 10–60 range, not their internal best.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| model_name | COMBO | [No models found - download from GitHub] | Select a Visual Chronometer model from the models/visual_chronometer directory |
| device | COMBO | auto | Select device: 'auto' chooses best available (CUDA > MPS > CPU) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | PULSE_OF_MOTION_MODEL | — |