Skip to content

Troubleshooting

zhanglinghao edited this page Oct 3, 2026 · 4 revisions

English · 中文

Symptom, cause and fix for problems the repo documents. Start with bin/vh doctor. If you installed a few days ago, run git pull first: many fixes (Linux, audio, rendering) are on main but not yet in a tagged release.

Install and setup

Symptom Cause Fix
install.sh stops with "✗ node is required" (or ffmpeg, or git) a prerequisite is missing Install git, Node.js ≥ 22 and FFmpeg, then re-run
The installer prints skip <repo> (clone failed) an upstream reference repo was unreachable; it is skipped rather than aborting the install Re-run references/fetch.sh later, or references/fetch.sh <dir> for a single repo
npm ci in styles/_swatch fails on registry.npmmirror.com an older lockfile pinned that mirror git pull (fixed), then cd styles/_swatch && npm ci
doctor shows "✗ chrome" no Chrome or Chromium found macOS: install Google Chrome. Linux: sudo apt install chromium or npx playwright install chromium. Or set CHROME_PATH
doctor shows "! no WebGL with the GPU flags" headless Chrome has no usable GPU Render with node render.mjs --soft-gl (software WebGL). If doctor reports no WebGL with --soft-gl either, WebGL scenes won't render on that machine
doctor shows "! AGENTS.md out of sync" CLAUDE.md changed without regenerating AGENTS.md bin/vh sync-agents
Downloads (npm, PyPI, Hugging Face, Chrome) are slow or fail the first runs fetch from servers abroad Mirrors for each are on the China network page; for GitHub itself, install with --no-refs and fetch references one at a time
Asking for a video in another folder doesn't reach the harness the agent hasn't reloaded its skills Restart Claude Code or Codex after bin/vh install-skill
Linux: bin/vh new … --effort studio still writes standard; swatch renders die after rendering; the determinism check fails on md5 older versions used macOS-only sed -i '', stat -f and md5 -q git pull: fixed on main
bin/vh setup -h starts the whole install, bin/vh sync-agents -h rewrites AGENTS.md, or a command takes -h as a file name older versions passed -h and --help on to the command git pull: bin/vh <command> -h now prints that command's usage and exits without running it

Rendering

Symptom Cause Fix
A HyperFrames render hangs with an empty log and no error a CDN import (GSAP, three.js) with no network when the page loads Install dependencies into the project (npm i -D --save-exact) and point the script tag or importmap at node_modules. bin/vh hf-init does this for GSAP and warns about other CDN links. Wrap long renders in a watchdog
A HyperFrames render sits at 5 % "Compiling composition", or snapshot and check print nothing a font in the stack has no @font-face, so HyperFrames asks Google Fonts for it on every run (cached font files don't stop the request), and the request hangs where Google Fonts is blocked. Names in HyperFrames' alias list (Arial, Helvetica Neue, Menlo …) without an @font-face are swapped for Inter or JetBrains Mono and fetched too Declare every font with @font-face and src: local(…); projects scaffolded by bin/vh hf-init since #35 already do. To self-host a web font through npm, see the 国内网络 section of README.zh-CN.md
The first hyperframes render shows only "Checking browser…" for a long time it is downloading HyperFrames' own chrome-headless-shell (about 100 MB, 200 MB unpacked, into ~/.cache/hyperframes/chrome) and a non-interactive shell prints no progress; having Google Chrome installed doesn't skip it Run npx hyperframes browser ensure once in a HyperFrames project before the first render: it says what it fetches and how big. If it can't download, see the mirror settings above
bin/vh new prints "hyperframes init failed (offline?)" the scaffold is fetched with npx When online, re-run bin/vh hf-init <project> with portrait, landscape or square
HyperFrames skills appear in ~/.claude/skills its init and skills update install globally export HYPERFRAMES_SKIP_SKILLS=1 before any npx hyperframes command, and never run npx hyperframes skills update. bin/vh hf-init sets it for you
font-weight: 800 is in the spec, but PingFang SC renders no bolder than 600 macOS's PingFang SC has six weights (100–600); 700, 800 and 900 fall back to 600, pixel-identical, with no error Write 600 and note it in STYLE.md. For a real 800 bring a font that has it (Noto Sans SC), or use a system font with heavier weights (Songti SC has 900)
--format png-sequence frames have a transparent background, and the psnr command reads about 1.25 dB high the PNGs are RGBA and the html, body and root backgrounds aren't painted (alpha 0), so an mp4 made from them has a black background; the alpha channel counts as an error-free fourth component in psnr Keep it in mind for determinism checks; a per-pair loop with format=rgb24 is in playbook/02
hyperframes snapshot sends the frames to Gemini with GEMINI_API_KEY (or GOOGLE_API_KEY) in the environment, snapshot describes every frame by default, so the frames leave your machine and are billed Always pass --describe false; the repo's docs and hints already do. check isn't affected
Every HyperFrames render is suddenly about 3× slower HyperFrames switched this machine to a slower capture path Set HF_DE_PARALLEL_ROUTER=true
A stretch of frames is stuck on the t=0 picture, yet the render "succeeded" an exception inside renderAt, e.g. a const read before it is declared Compare every frame with frame 0 (PSNR), or keep a time readout on screen in drafts; fix the exception
The first 1–2 frames of each worker's chunk are empty frames captured before an async build finished Register a ready promise synchronously in a classic <script> and resolve it after the first frame is drawn
Three.js video screens render black the VideoTexture isn't updated Set texture.needsUpdate = true every frame; seek the video by t and wait for the seek
Text goes soft after a camera push-in will-change: transform rasterized it at the small size Remove will-change from elements that get zoomed, or lay them out at the zoomed size
Monospace text renders proportional in the MP4, though snapshots looked right ui-monospace, monospace passes lint but not the renderer Declare the font with @font-face and src: local("SF Mono"), local("Menlo"); judge fonts on rendered frames
The picture is cut short, or the last frames go missing, when adding audio ffmpeg's -shortest Mux with bin/vh mux, which pads or trims the audio to the video
Saturated colours look different in the browser or on a phone than in ffmpeg or an editor the mp4 has no colour tags, or BT.601 tags: the old hand-drawn engine wrote bt470bg, which browsers read wrongly (24–40 levels off on saturated colours) while ffmpeg reads it right Encode limited-range BT.709 and write all four tags; bin/vh check flags anything else. The ffprobe check and the ffmpeg command are in playbook/02
You review an old render by mistake a stale output file Delete old outputs before rendering, or check the file's modification time
bin/vh check flags black, frozen or silent stretches dark backgrounds, deliberate holds and silent films trigger it by design Look at each hit and decide

Determinism

Symptom Cause Fix
The same frame differs between runs Math.random(), Date.now(), CSS transitions or @keyframes, or state carried between frames Use a seeded hash(i) and compute everything from t
With --soft-gl, frames differ on every launch (about 39 dB) Chrome's canvas readback noise Fixed on main; run git pull
Two renders compared as MP4s look non-deterministic (about 42 dB) x264 amplifies tiny GPU rasterization differences Compare lossless PNG frames: pixel-identical, or ≥ 45 dB PSNR with no visible difference, passes
Two renders of the same HyperFrames project differ in a few text-edge pixels, or an encode flips between two sizes at a size cap GPU text rasterisation differs from one Chrome process to the next, and x264 with frame threads isn't repeatable under a bitrate cap hyperframes render --no-browser-gpu (CPU, slower) makes the pixels repeatable, and -threads 1 the x264 stream. The swatch renderer does both: research note 03 has the measurements
Still objects jitter in a hand-drawn scene a moving object shifted the shared random stream Give each element its own boilSeed()

Fonts

Symptom Cause Fix
Chinese characters on a canvas are missing or in a system font, although document.fonts.ready resolved CJK web fonts arrive as subsets, fetched only when a character is first drawn Call document.fonts.load(…) once per weight with every character the film uses, and fail loudly on a rejection, an empty result or a timeout
The first frame uses a fallback font and the layout jumps the frame was captured before web fonts loaded await document.fonts.ready before the first capture
HyperFrames lint rejects a Chinese font Noto Sans SC isn't in its automatic font list Add a Google Fonts <link>, or put the font file in assets/ with an @font-face rule

Blender

From the smoke tests and the intro film's opening; more in engines/blender.md.

Symptom Cause Fix
A Blender render prints nothing for about two minutes at the start, and a watchdog kills it the first Metal render compiles its kernels silently (about 110 s) Allow a longer silence for Blender (the swatch renderer allows 300 s)
Under the sandbox every Metal frame takes 13 s instead of 2 s Blender can't keep its compiled shaders in its folder of the per-user cache Allow writes to $(getconf DARWIN_USER_CACHE_DIR)org.blenderfoundation.blender
Rendering frame by frame in one process, an object goes black for a stretch of frames but renders fine on its own render.use_persistent_data carries state from frame to frame Turn it off when a script changes the scene before every frame, or compare frames re-rendered out of order
A long render stops halfway when run as an agent's background task Claude Code ends background tasks after 30 minutes Render in chunks of fresh processes that skip finished frames, detached with nohup caffeinate -i … & disown, as showcase/04-intro-film/tools/bl_render.sh does
Stars smear into blotches the OIDN denoiser Turn denoising off for star fields and rely on samples
Stacked glass cards render as black blocks rays run out of transmission bounces Drop the glass on cards that don't need it
The camera twists and jitters when it looks almost straight down to_track_quat is unstable near vertical Build the rotation from your own forward and up vectors, and keep consecutive quaternions on the same side (negate when q.dot(prev) < 0)
Text in Blender comes out in the wrong weight bpy.data.fonts.load() reads only the first face of a .ttc Write the face you need out as its own font file (styles/_swatch/blender_prep.py does it with fontTools)

Voice and mix

Symptom Cause Fix
A short English line from qwen mumbles on for seconds Qwen3-TTS 0.6B run-on, worst with the Ryan voice Aiden is now the default. Add --align gemini to flag such lines, then re-run them, use a 1.7B model (QWEN_TTS_MODEL) or gemini
say or qwen fails on Linux say is macOS-only; qwen needs Apple Silicon Use edge or a cloud provider
--align gemini pauses for about a minute, then carries on Gemini Tier 1 allows 10 transcriptions a minute (HTTP 429) Nothing to do: it waits as the API asks and retries up to 5 times. A 429 asking for more than 90 s is a daily quota and fails at once
--align gemini stopped halfway (a daily quota, the network) a transcription failed for good The take is kept and the command exits 1 with the reason. Run the same command with --resume: it redoes only what's missing and doesn't pay twice for lines that already succeeded.
"set GEMINI_API_KEY" the key isn't in the environment export GEMINI_API_KEY=… in your shell, never in a file in the repo
bin/vh tts <p> --provider edge fails with "No such file or directory: 'edge-tts'" older bin/vh chose dependencies only from the positional provider git pull (fixed), or write the provider positionally: bin/vh tts <p> edge
bin/vh qa fails on digital silence mid-film a dramatic stop made of true silence Keep a bed (sub or pad), close the filter, drop the drums, swell into the next hit
bin/vh qa reports pumping, or the music drops out between lines the ducker keyed on every SFX, or a high duck_ratio Use the defaults (duck=voice, duck_ratio=1.6); with duck=on keep the ratio at 2–3. Pass --voice voiceover.wav to qa so the designed dip under narration isn't counted
bin/vh qa prints a mix report with LOW, HIGH, OVER-VOICE, MASKS-VOICE or BURIED a profile= mix has a line, a sound effect or a word outside its range; BURIED means a cue is found but can't be heard Read the "why" column first. Fixes by flag are in playbook/04 ("怎么读混音报告"): re-record or ease the score under a quiet line, move or reclassify the effect (role), raise gain_db, or add a 1–4 kHz layer to a low-frequency hit instead of gain
The AAC-encoded file's true peak is over −1.5 dBTP an AAC encode adds to the true peak, up to about +1.4 dB at 128k on dense music Measure the encoded file with ffmpeg -i final.mp4 -af ebur128=peak=true -f null - and mix again with a lower tp=; the swatch renderer does this by itself
A browser waits for the whole video to download before it plays the index (moov) sits at the end of the file Re-mux with bin/vh mux, which now writes it first
A player switches a subtitle track on over burned-in captions MP4 always enables the first subtitle track when none is marked default bin/vh mux --subs-off
bin/vh readcheck fails burned-in captions that repeat the narration they were checked by the on-screen rule, which assumes slower reading Mark them data-read="subtitle", on the clip or on the scene around it, and they are checked at subtitle reading speed
A caption flashes by in under 1.8 s the spoken line is short Run bin/vh captions again: it lengthens short cues into the silence after them, up to the next caption or the end of the picture
bin/vh qa lists clicks a machine can't tell a designed sharp attack from a fault These are warnings: listen to the 10 worst by ear
bin/vh qa warns that a sound repeats the same sound came back three or more times in a row: a pinned variant, or the same file Unpin the variant, rotate two or three takes, or use another transition family; bin/vh sfx audition plays the options
bin/vh mix reports many limiter peaks SFX or voice peaks are too hot Lower sfx_db instead of leaning on the limiter

Not listed here? Open an issue with the command, its output and the result of bin/vh doctor.

Clone this wiki locally