PTENES
MODULE 2.2

🛠️ Setup & prerequisites

Install Node.js 22+, FFmpeg, headless Chrome, and Kokoro TTS. Set everything up from scratch through execution npx hyperframes init successfully.

6
Topics
20
Minutes
Practical
Level
Setup
Type
HyperFrames CLI npx hyperframes Node.js v22+ runtime FFmpeg C:\ffmpeg\bin -nostdin Chrome headless browser ensure Kokoro PT-BR TTS pf_dora hyperframes doctor ✓ diagnosis SETUP ENVIRONMENT
1

⚙️ Node 22+ and FFmpeg

Two required binaries: Node.js version 22 or higher and FFmpeg available on the PATH. Without them, HyperFrames can't render a single frame.

Why Node 22+ specifically?

HyperFrames uses Native ESM and APIs for fs/promises available starting with Node 18, but version 22 brings the --experimental-strip-types and the updated V8 that speeds up composition parsing. Older versions (16, 18) may work partially but cause warnings and unexpected behavior in build-index.mjs.

Check the version and install via nvm (git-bash / WSL)
# Check the current version
node --version
# should return v22.x.x or higher
# If you need to install via nvm
nvm install 22
nvm use 22
nvm default alias 22
Install FFmpeg and add it to PATH (Windows)
# 1. Download the static release from ffmpeg.org/download.html
# 2. Extract to C:\ffmpeg (it should contain bin\ffmpeg.exe)
# 3. Add to PATH via PowerShell (Admin)
[Environment]::SetEnvironmentVariable("Path",
"$env:Path;C:\ffmpeg\bin",
"Machine")

# 4. Verify (new terminal)
ffmpeg -version
# should show ffmpeg version 6.x or 7.x
✓ Correct path
  • ✓ FFmpeg in C:\ffmpeg\bin\ffmpeg.exe
  • ✓ PATH configured in the system (non-user)
  • ✓ Node 22+ verified with node --version
  • ✓ Open a new terminal after changing PATH
✗ Common pitfalls
  • ✗ Use FFmpeg installed by choco without checking PATH
  • ✗ Node 16 or 18 — causes errors with native ESM
  • ✗ Test ffmpeg in the old terminal (PATH not updated)
  • ✗ ffmpeg.exe outside the subdirectory bin
Key concepts
⚙️
Node 22+
Native ESM
🎞️
FFmpeg
C:\ffmpeg\bin
🌿
nvm
Manage versions
🔗
PATH
System var.
2

⌨️ ffmpeg -nostdin in git-bash

The quietest setup gotcha: running FFmpeg inside git-bash without -nostdin causes exit 0 without generating any files. No visible error — nothing is simply created.

⚠️ Critical gotcha—exits with code 0 without a file

In git-bash (MinTTY), FFmpeg tries to read stdin and silently blocks. The process exits with code 0 (success), but no MP4 is generated. It's the hardest bug to diagnose because everything seems to have worked.

✗ Problem (git-bash)
# Exits with code 0, no file!
ffmpeg -i frames/%04d.png \
-c:v libx264 output.mp4
# No errors — and no MP4
✓ Solution (-nostdin)
# Correct in git-bash
ffmpeg -nostdin \
-i frames/%04d.png \
-c:v libx264 output.mp4
# Generates the MP4 correctly
💡
HyperFrames already includes -nostdin

The HyperFrames CLI (npx hyperframes render) passes -nostdin automatically in internal calls to FFmpeg. You only need to worry about this if you invoke FFmpeg directly in git-bash for manual post-processing, concatenation scripts, etc.

📊 Why does this happen?
MinTTY (git-bash)
Emulates a POSIX terminal. When FFmpeg detects that stdin is a TTY, it waits for user input—which never comes.
Exit code 0
FFmpeg closes stdin and exits normally, without an error—but without processing anything. Ambiguous behavior by design.
-nostdin
Completely disables reading from stdin. FFmpeg processes the input file without blocking on the TTY.
Key concepts
⚠️
MinTTY
TTY in git-bash
🔇
-nostdin
Required flag
0️⃣
Exit 0
Silent
🔄
Auto CLI
Already included
3

🌐 HyperFrames headless Chrome

HyperFrames comes with its own Chrome headless — it doesn’t depend on Chrome installed on the system. A single command downloads and links the exact version tested with the CLI.

Why a dedicated Chrome?

Different Chrome versions render CSS and GSAP animations with subtle pixel differences. To make the output deterministic (same HTML → same MP4), HyperFrames locks to a specific Chromium version via Puppeteer, downloaded and managed internally. You don’t need to touch the system Chrome.

Download headless Chrome (only once)
# Downloads and installs Chromium at the version pinned by HyperFrames
npx hyperframes browser ensure

# Expected output:
✓ Chromium 121.0.6167.85 already installed
# or
⬇ Downloading Chromium 121.0.6167.85 (~170MB)...
✓ Done
What the command does internally
1

Reads the pinned version in HyperFrames’ package.json

The field puppeteer.chromiumRevision specifies exactly which Chromium build to use — no "latest".

2

Checks the local cache (~/.cache/puppeteer/)

If the build already exists, skip the download. The second project you create doesn't wait for anything — instant.

3

Downloads ~170MB from the Chromium CDN if needed

Only the first time or when the HyperFrames version is updated. A stable connection is recommended.

💡
Check where Chrome was installed
npx hyperframes browser path
# shows the full path to the executable
Key concepts
🌐
Chromium
Locked version
🎭
Puppeteer
Manager
💾
Cache
~/.cache/puppeteer
🔒
Deterministic
Pixel-perfect
4

🔊 Kokoro TTS

100% local PT-BR narration, with no API key. Kokoro has its own Portuguese phonemizer, so espeak-ng isn't needed. On the first run, it downloads ~340MB of model files.

✓ Correct installation
  • ✓ pip install kokoro-onnx soundfile
  • ✓ Python 3.10+ on PATH
  • ✓ First run: wait for ~340MB download
  • ✓ Default voice: pf_dora with --speed 0.98
✗ Don't install
  • ✗ espeak-ng — Kokoro doesn't need it and it causes a conflict
  • ✗ Other TTS packages that depend on espeak
  • ✗ Interrupt the model's first download
  • ✗ Use speed 1.0+ — sounds mechanical in PT-BR
Install and generate the first audio
# Install (once)
pip install kokoro-onnx soundfile

# Generate narration via HyperFrames TTS
npx hyperframes tts "assets/txt/s1.txt" \
--voice pf_dora \
--speed 0.98 \
--output assets/audio/s1.wav

# On the first run — expected output:
⬇ Downloading kokoro model (~340MB)...
✓ Model cached at ~/.cache/kokoro/
✓ Generated: assets/audio/s1.wav (3.2s)
💡
Why not use espeak-ng?

espeak-ng phonemizes Portuguese poorly — technical words sound robotic. Kokoro has its own PT-BR phonemizer trained specifically for the language.

⚡
Second run: instant

The model (~340MB) is cached in ~/.cache/kokoro/. From the second invocation onward, generating a 10s clip takes less than 2 seconds.

Key concepts
🔊
kokoro-onnx
TTS engine
🗣️
pf_dora
Brazilian Portuguese voice
📦
340MB
First time only
🚫
without espeak
Don’t install
5

🩺 npx hyperframes doctor

The diagnostic command checks the entire stack at once: Node, FFmpeg, Chrome, and Kokoro. If something is wrong, it tells you exactly what’s missing.

Expected output (environment OK)
npx hyperframes doctor

# Expected output:
✓ Node.js v22.3.0 — OK
✓ FFmpeg 6.1.1 found at C:\ffmpeg\bin\ffmpeg.exe
✓ Chrome headless 121.0.6167.85 — cached
✓ kokoro-onnx 0.8.2 — installed
✓ soundfile 0.12.1 — installed

All systems go 🚀
Output with errors (FFmpeg not found)
npx hyperframes doctor

✓ Node.js v22.3.0 — OK
✗ FFmpeg not found in PATH
→ Install FFmpeg and add C:\ffmpeg\bin to PATH
✓ Chrome headless 121.0.6167.85 — cached
⚠ kokoro-onnx not found
→ Run: pip install kokoro-onnx soundfile

2 issues found. Fix them before rendering.
💡
Run doctor before any render

Especially in a new environment or after updating HyperFrames. The npx hyperframes render fails midway through the process if a dependency is missing — the doctor detects it beforehand.

What the doctor checks
1

Node.js — minimum version 18, recommended 22+

Reads process.version and compares it with the field engines from package.json.

2

FFmpeg — runs ffmpeg -version and parses the output

Checks whether the binary is accessible via PATH and shows the full path found.

3

Chrome — check Puppeteer cache

Check if the stuck build is at ~/.cache/puppeteer/. If not, suggest running browser ensure.

4

Kokoro — import the Python module and check

Runs python -c "import kokoro_onnx" e import soundfile. Minimum versions checked.

Key concepts
🩺
doctor
Diagnostics
✓
All OK
4 checks
✗
Issues
With suggestion
🔁
Pre-render
Always run
6

📦 Start a project

With the environment ready, the next step is to create the project structure. The template blank + --non-interactive generates everything without questions — ideal for scripts and CI.

Blank template vs. others

O --example blank creates a minimal project with the correct folder structure but no prebuilt scenes — you start from scratch. It's the recommended entry point for learning the pipeline, since each file that appears was created intentionally.

Create and configure a new project
# 1. Create a project (no interaction)
npx hyperframes init my-video \
--example blank \
--non-interactive

# 2. Enter the directory
cd my-video

# 3. Install dependencies
npm install

# 4. Copy fonts (required before any render)
node scripts/fetch-fonts.mjs

# 5. Check the environment before rendering
npx hyperframes doctor
Structure generated by init blank
my-video/
├── scenes/ # HTML scenes + GSAP
│ └── s01.html
├── assets/
│ ├── txt/ # narration by scene
│ ├── audio/ # .wav generated by TTS
│ └── fonts/ # ← fetch-fonts.mjs
├── scripts/
│ ├── build-index.mjs
│ ├── fetch-fonts.mjs
│ └── narration-template.sh
├── design.md # palette, typography, style
└── package.json
✓ After init, always do this
  • ✓ Read the design.md to understand the palette
  • ✓ Run node scripts/fetch-fonts.mjs before the render
  • ✓ Use narration-template.sh as the script basis
  • ✓ Run doctor once in the new project
✗ Common beginner mistakes
  • ✗ Render without running fetch-fonts.mjs → font not found
  • ✗ Ignore the design.md and invent a color palette
  • ✗ Skip the npm install after init
  • ✗ Use spaces in the project name (e.g., meu video)
💡
The design.md defines the visual identity

Each project has a design.md with the main palette, typography, and visual style. For INEMA.CLUB videos, the default palette is: background #0D1321, amber accent #FACC15, white/gray text. Claude reads this file before writing any scene.

Key concepts
📦
hyperframes init
Scaffolding
📄
design.md
Palette + style
🔤
fetch-fonts
Required
📝
narration.sh
TTS template

📋 Module 2.2 summary

What you learned in this module

Complete setup checklist
  • ✓ Node.js 22+ installed and verified with node --version
  • ✓ FFmpeg in C:\ffmpeg\bin added to the system PATH
  • ✓ Headless Chrome installed via npx hyperframes browser ensure
  • ✓ Kokoro TTS installed (pip install kokoro-onnx soundfile), without espeak-ng
  • ✓ npx hyperframes doctor returning "All systems go"
  • ✓ First project created with npx hyperframes init <nome> --example blank --non-interactive
  • ✓ fetch-fonts.mjs executed, fonts downloaded
  • ✓ Understood why -nostdin is required in git-bash
Next module:
2.3
📝 Script & TTS narration
Structure the script using the narration-template.sh, generate the audio files with Kokoro (pf_dora --speed 0.98) and measure the durations with ffprobe to sync with the scenes.
Go to module 2.3 →