Skip to content

China Network

zhanglinghao edited this page Oct 3, 2026 · 1 revision

China network

The first runs reach servers abroad: npm, PyPI, Hugging Face, the Chrome that HyperFrames uses, GitHub, and, while rendering, sometimes Google Fonts. Where those are blocked or slow (mainland China, for example), set the mirrors below. This page used to be part of the Chinese README; it moved here on 2026-10-04. 中文

The addresses and variable names were checked against each provider's documentation on 2026-10-01. Mirrors move; if one stops working, go by the official page.

Mirrors

What How Docs
npm packages: the engines' dependencies, each HyperFrames project's node_modules export npm_config_registry=https://registry.npmmirror.com npmmirror, npm config
Python packages: the sound tools and contact sheets, installed by uv on first use export UV_DEFAULT_INDEX=https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple (Tsinghua), or https://mirrors.aliyun.com/pypi/simple/ (Alibaba Cloud) Tsinghua PyPI, Alibaba Cloud PyPI, uv environment variables
The Qwen3-TTS model (about 2 GB, from Hugging Face) export HF_ENDPOINT=https://hf-mirror.com hf-mirror, huggingface_hub environment variables

Set the variables before running install.sh or bin/vh: in ~/.zshrc to keep them, or for one command, for example the installer:

curl -fsSL https://raw.githubusercontent.com/ZLHad/OpenVideoHarness/main/install.sh | npm_config_registry=https://registry.npmmirror.com bash

Details:

  • npm. The repo's package-lock.json files record registry.npmjs.org addresses; npm swaps the host for the registry you set (replace-registry-host defaults to npmjs), so npm ci goes through the mirror too (tested: no request reached npmjs.org). To keep it: npm config set registry https://registry.npmmirror.com.
  • uv and pip. UV_INDEX_URL is the old name, deprecated in uv's docs; use UV_DEFAULT_INDEX. To keep it, put it in ~/.config/uv/uv.toml (the same place on macOS and Linux; environment variables win over the file):
    [[index]]
    url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
    default = true
    With pip directly: pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple. Tsinghua's other domain, https://pypi.tuna.tsinghua.edu.cn/simple, works too. Alibaba Cloud's page shows http:// with trusted-host; https:// works as well.
  • Hugging Face. HF_ENDPOINT is the variable huggingface_hub reads, and it's what bin/vh tts uses to download Qwen3-TTS. hf-mirror doesn't support logging in: a gated model needs an Access Token from huggingface.co first, passed with --token (see hf-mirror's front page). The default Qwen3-TTS model is public, so none of that applies to it.
  • HyperFrames' Chrome. The first hyperframes render downloads chrome-headless-shell from storage.googleapis.com (0.8.82 pins 152.0.7977.30). When that is blocked, the terminal spins on "Checking browser…" and finally fails with Failed to download chrome-headless-shell. Install it from npmmirror's binary mirror to where HyperFrames looks, from any HyperFrames project or from styles/_swatch:
    npx browsers install chrome-headless-shell@152.0.7977.30 \
      --path ~/.cache/hyperframes/chrome --base-url https://cdn.npmmirror.com/binaries/chrome-for-testing
    npx hyperframes browser path then prints it, and renders stop downloading it (tested: the render log shows Browser: cache). If that fails too, export HYPERFRAMES_BROWSER_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" (macOS; on Linux, the path of google-chrome or chromium) uses your installed Chrome: it renders, but through the slower screenshot path, which this repo hasn't tested for determinism.
  • GitHub. install.sh and references/fetch.sh clone from GitHub, and tools/fetch_media.sh downloads the showcase videos from a GitHub release. If GitHub is unreliable, install with bash install.sh --no-refs and fetch reference repos one at a time when a doc points at them (references/fetch.sh <name>); git can also go through a proxy: git config --global http.proxy http://127.0.0.1:<port>.

Rendering may call Google Fonts

A few things request fonts.googleapis.com while rendering:

  • engines/ClaudeAnimationBase/studio.html requests Permanent Marker for handwriting; hand-drawn and music-video projects (bin/vh new handdrawn, mv) and showcase/01 are copied from it. render.mjs waits for the network to go idle before rendering: if the request hangs, it exits after 30 s with Navigation timeout of 30000 ms exceeded; if it fails at once, it prints one Failed to load resource line and renders anyway, with the handwriting in the fallback font (Comic Sans MS).
  • showcase/02-short-leo-doppler/index.html, and vertical science shorts modeled on it: Noto Sans SC at weights 500 and 800.
  • HyperFrames itself: any font in a stack that isn't declared with @font-face is requested from Google Fonts on every render, snapshot and check, even when it's cached in ~/.cache/hyperframes/fonts. Names its linter accepts (Arial, Helvetica Neue, Menlo and others) are on that list too: they're swapped for Inter and JetBrains Mono and fetched. A stack that starts with a generic family such as sans-serif gets Inter put in front of it. When the request hangs, render stops at 5 % "Compiling composition" and snapshot and check print nothing (tested: still waiting after 90–150 s). When it fails at once there is no warning, and Inter is left with only the 400, 700 and 900 weights HyperFrames ships, so a 600 title renders at 700. bin/vh hf-init now replaces the scaffold's default Inter with local fonts declared with local() (option 1 below), so new projects make no Google Fonts requests; change older projects the same way.

Three ways to keep fonts local, easiest first:

  1. System fonts, no network. The style-sample renderer and the bin/vh hf-init scaffold do this: declare @font-face in the page's <style> with a local() source, for example @font-face { font-family: "PingFang SC"; src: local("PingFangSC-Semibold"), local("PingFang SC Semibold"); font-weight: 600; }. Every font in a stack needs such a declaration, and the first one must be declared. Ready-made declarations are in styles/_swatch/fonts.css; on another machine, python3 styles/_swatch/fonts.py regenerates them from the fonts installed there. Which weights each font has: the "字体" section of styles/_swatch/README.md.
  2. Font files in the project. Put them in assets/fonts/, declare @font-face { font-family: "…"; src: url("assets/fonts/….woff2") format("woff2"); } in <style>, and record their source and license in NOTES.md. HyperFrames doesn't fetch a font the page declares itself (tested: no requests).
  3. From npm. Fontsource packages Google Fonts for npm, so the npm mirror above applies:
    • The hand-drawn engine: npm i -D @fontsource/permanent-marker (0.1 MB), then replace the fonts.googleapis.com <link> in studio.html with <link rel="stylesheet" href="node_modules/@fontsource/permanent-marker/index.css">. Tested with Google Fonts blocked: the font loads within a second.
    • Noto Sans SC: npm i -D @fontsource-variable/noto-sans-sc (a variable font of about 5 MB covering weights 100–900), <link rel="stylesheet" href="node_modules/@fontsource-variable/noto-sans-sc/wght.css"> in the page, and font-family: "Noto Sans SC Variable". Showcase 02 changed this way renders pixel-identical HyperFrames snapshots (tested at three moments); snapshot prints [StaticGuard] … Font family used without @font-face declaration, but the font is loaded and the warning can be ignored.

Clone this wiki locally