Your AI writes HTML; Envie renders it to video on your machine, verifies it and shows it back.
AI video, verified.
Describe a video to your AI. Get a real file back.
Envie gives Claude Code and any MCP client a deterministic render engine: headless Chrome filmed frame by frame, six verification gates, and a full read-back layer. Free. No watermark. No account.
By GOL Productions.
AI can write code. AI can describe video. But AI can't see what it made—so it guesses, you render, it's wrong, you describe what's wrong, repeat.
You: "Make me a 15-second launch video for my app"
AI: [writes HTML composition]
AI: [calls envie_render]
AI: [calls envie_see to check frames]
AI: "Done. Video at output.mp4. All 6 gates passed."
Envie renders what your AI writes, verifies it machine-checks, and lets your AI see the result. No guessing.
npx @golproductions/envie@latest setup
Detects Claude Code, Cursor, Windsurf—registers with all of them. Then just ask:
"Make me a 15-second vertical launch video for my app"
{ "mcpServers": { "envie": { "command": "npx", "args": ["-y", "@golproductions/envie", "mcp"] } } }
Or for Claude Code:
claude mcp add --scope user envie -- npx -y @golproductions/envie mcp
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WRITE │ ──► │ RENDER │ ──► │ VERIFY │ ──► │ SEE │
│ │ │ │ │ │ │ │
│ AI writes │ │ Chrome films│ │ 6 gates │ │ AI checks │
│ HTML comp │ │ frame by │ │ machine- │ │ frames at │
│ │ │ frame │ │ check video │ │ timestamps │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Your AI reads envie_guide and writes a composition: one self-contained HTML file with CSS animations, WebGL, Canvas, GIFs—whatever the browser can render.
envie_render films it deterministically. Headless Chrome with a virtualized clock: performance.now(), Date.now(), requestAnimationFrame, setTimeout—all seeked frame by frame.
Same composition = same video. Every time.
Six gates machine-check the result before delivery:
| Gate | What it checks |
|---|---|
| G1 | File exists, valid container, ≥2.9s duration |
| G2 | Has both video and audio streams |
| G3 | Audio isn't silent (mean > -50dB) |
| G4 | No black segment > 2 seconds |
| G5 | No freeze > 8 seconds, < 60% total still time |
| G6 | Final 15% isn't dead (frozen or black) |
A failing video comes back marked FAILED, with the gate report and an instruction not to deliver it, so your AI fixes the composition and renders again.
envie_see returns frames at chosen timestamps so your AI can judge layout and pacing—not just whether the file exists.
envie_translate reads the finished file as data: per-frame motion, every cut and fade, still holds, LUFS, true peak, and how each audio hit sits against the nearest picture event.
| Requirement | Notes |
|---|---|
| Node 24+ | Or later |
| Chrome | Or set ENVIE_CHROME to your binary |
| ffmpeg + ffprobe | Must be on PATH |
| Audio | Required. Videos with no audio fail G2 and G3 |
| Option | Platform | Description |
|---|---|---|
--narration "text" | Windows only | Local TTS voiceover (SAPI) |
--audio file.wav | All platforms | Overlay any wav/mp3/m4a |
Runs entirely on your machine. Nothing reaches GOL servers.
| Flag | Container | Codec |
|---|---|---|
--format h264 | .mp4 | libx264 (default) |
--format h265 | .mp4 | libx265 10-bit |
--format prores | .mov | ProRes 422 HQ 10-bit |
--format prores4444 | .mov | ProRes 4444 10-bit |
--format dnxhr | .mov | DNxHR HQ |
npx @golproductions/envie@latest setup # register MCP server
npx @golproductions/envie@latest uninstall # remove everything Envie added
envie render <comp.html> -o out.mp4 [options] # render video
envie see <comp.html|video.mp4> [--at 1000,4000] # extract frames
envie verify <video.mp4> # run gates
envie translate <video.mp4> # analyze motion/audio
envie guide # print authoring guide
envie mcp # start MCP server
envie here means npx @golproductions/envie@latest. Use @latest: plain npx runs an older globally installed copy if one exists.
--narration "text" # TTS voiceover (Windows)
--audio file.wav # Overlay audio file
--fps 24 # Frame rate (default: 24)
--format h264 # Output codec
-o output.mp4 # Output path
One self-contained HTML file:
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; width: 1080px; height: 1920px; overflow: hidden; }
/* your animations */
</style>
</head>
<body data-duration-ms="15000" data-width="1080" data-height="1920">
</body>
</html>
| Attribute | Description |
|---|---|
data-duration-ms | Video length in milliseconds (3000–300000) |
data-width | Canvas width (default: 1920) |
data-height | Canvas height (default: 1080) |
Everything the browser can animate:
requestAnimationFramesetTimeout, setIntervalperformance.now(), Date.now(), new Date()Math.random(), crypto.getRandomValues (seeded)NOT virtualized (avoid):
Declare what the composition must achieve:
<body data-duration-ms="12000"
data-expect-sync-ms="120"
data-expect-no-holds-longer-than="3">
| Assertion | Meaning |
|---|---|
data-expect-sync-ms="120" | Audio hits must land within 120ms of a picture event |
data-expect-no-holds-longer-than="3" | No still hold may exceed 3 seconds |
Failures are reported test-style:
SYNC FAIL: mean audio-to-picture offset 380ms exceeds tolerance 120ms
HOLD FAIL: 2 hold(s) exceed 3s: 4.20s @0.40s, 3.10s @7.80s
The render engine virtualizes time itself:
// Inside the page during render:
performance.now() // → virtual clock
Date.now() // → virtual clock
new Date() // → virtual clock
Math.random() // → seeded PRNG
// Same seed, same composition = identical output
This is how the same HTML produces the same video, every render.
Same machine + same Chrome version + same composition = bit-identical output.
Cross-environment, you may see variation from:
The guarantee is reproducibility on your machine, not cross-platform bit-identity. That's the right scope: your AI iterates locally, re-renders, gets the same result.
GOL claims no ownership over your compositions or videos. Envie runs on your machine. Nothing you make reaches us.
Free, under the GOL Open License: use, modify and redistribute it, with attribution to GOL Productions kept in every copy and fork. See LICENSE.
"Envie" and "GOL Productions" are trademarks. Forks must use a different name and state that they are based on software by GOL Productions.
Envie is part of the GOL Productions toolchain.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @golproductions/envieMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"com-golproductions-envie": {
"command": "npx",
"args": [
"-y",
"@golproductions/envie"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup reference@golproductions/envienpmEnvie works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.