Files
wehub-resource-sync 85453da49f
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:58:35 +08:00

113 lines
3.2 KiB
Markdown

# Font translation
Fonts are the dominant non-translation noise floor. Same `font-weight: 800`
renders perceptibly bolder on HF's `chrome-headless-shell` than on
Remotion's bundled Chromium when there's no real font installed. Validation
showed this costs ~0.025 mean SSIM at the noise floor.
## Pattern: `@remotion/google-fonts/<Family>`
```tsx
import { loadFont } from "@remotion/google-fonts/Inter";
loadFont("normal", { weights: ["400", "800"] });
```
Translate to a `<link>` tag in `<head>`:
```html
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: Inter, sans-serif;
}
</style>
</head>
```
Pull the family name and weights from the import path and `loadFont`
arguments. HF's compiler inlines the Google Fonts CSS at render time, so
you don't pay a network round-trip per render.
## Pattern: local fonts via `@font-face`
```tsx
import { Font } from "remotion";
Font.loadFont("/MyFont.woff2", "MyFont");
```
Translate to a `@font-face` rule:
```html
<style>
@font-face {
font-family: "MyFont";
src: url("assets/MyFont.woff2") format("woff2");
font-weight: 400;
font-style: normal;
}
</style>
```
Copy the font file into `hf-src/assets/` next to the HTML.
## Pattern: system font fallback (no font load)
```tsx
<div style={{ fontFamily: "Helvetica, Arial, sans-serif" }}>...</div>
```
Same string in HF — but be aware: on Linux without a real Helvetica
installed (typical CI environment), Remotion and HF fall back to
_different_ sans-serif system fonts because they bundle different
Chromium versions. This is the noise floor: ~0.025 mean SSIM cost,
visible as different stroke widths at large font weights (800+).
If matching the Remotion render exactly matters for a specific
fixture, load the same font explicitly — don't rely on system
fallback.
## When in doubt: use Inter
Inter renders identically across Chromium versions and is free.
Translate any "system sans-serif" Remotion comp to Inter when you
need to minimize font drift in the validation harness.
## Font loading and `delayRender`
Remotion uses `delayRender()` to defer the first frame until fonts
load. HF's compiler inlines Google Fonts at compile time and waits
on `@font-face` readiness via the Frame Adapter pattern — the
`delayRender` call drops in translation. See [media.md](media.md).
## Multi-weight loading
When Remotion loads multiple weights:
```tsx
loadFont("normal", { weights: ["400", "500", "700", "800"] });
```
Inline all weights in the Google Fonts URL:
```
?family=Inter:wght@400;500;700;800&display=swap
```
Translation rule: enumerate every distinct `font-weight` value
that appears in the composition's CSS (`font-weight: 800`
weight 800 must be loaded). If the Remotion source loads weights
that aren't actually used, drop them.
## Font subsetting
Remotion's `loadFont` doesn't subset; HF's compiler doesn't either
(yet). Don't try to optimize this in translation — it's lossless to
keep the same weight set as the Remotion source.