PTENES
MODULE 2.2

πŸ› οΈ Setup & prerequisites

Install Node.js 22+, headless Chrome, FFmpeg, 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 accessible in 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 approach
  • βœ“ 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 the 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 most subtle 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 it 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 processes nothing. 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 includes its own headless Chrome β€” 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 pins to a specific version of Chromium 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

Read the pinned version in HyperFrames’ package.json

The field puppeteer.chromiumRevision specifies exactly which Chromium build to use β€” no "latest".

2

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

If the build already exists, skip the download. The second project you create waits for nothing β€” 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, no API key required. 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 a ~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 Brazilian Portuguese
Install and generate your 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 1st run β€” expected output:
⬇ Downloading kokoro model (~340MB)...
βœ“ Model cached at ~/.cache/kokoro/
βœ“ Generated: assets/audio/s1.wav (3.2s)
πŸ’‘
Why without 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 segment takes less than 2 seconds.

Key concepts
πŸ”Š
kokoro-onnx
TTS engine
πŸ—£οΈ
pf_dora
PT-BR 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 issues (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+

Read 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 β€” checks Puppeteer cache

Checks whether the stuck build is in ~/.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. This is the recommended entry point for learning the pipeline, since every file that appears was created intentionally.

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

# 2. Enter the directory
cd meu-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 the init blank
meu-video/
β”œβ”€β”€ scenes/ # HTML scenes + GSAP
β”‚ └── s01.html
β”œβ”€β”€ assets/
β”‚ β”œβ”€β”€ txt/ # narration per 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 a scriptwriting foundation
  • βœ“ 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 durations with ffprobe to sync with the scenes.
Go to module 2.3 β†’