Twelve videos in four days. Nobody picked up a camera.
Prajjwal Pathak35 min
- date
- words
- 6 889
- read
- 35 min
- sources
- 10 sources
- finished videos
- 12 finished videos
- HeyGen spend
- $8.20 HeyGen spend
- per voice minute
- ~$0.14 per voice minute
- quality gates
- 37 quality gates
- longest render
- 19.5 min
- views
- 8 views
Updated on 12 October 2026. The studio is now open source: cybiqon-ai/faceless-video-studio (MIT), with a step-by-step setup guide. It has moved on since this post was written: 38 gates (a new one, B18, fails a Short whose bottom 40% is empty), 22 look families instead of 15, and two more render engines alongside HyperFrames — the vendored animate styles and Manim. The figures below are as of 11 October.
On 8 October our company changed what it does with its evenings. The products were built and almost nobody knew they existed, so from that day the focus became content: a video every day for YouTube and Instagram. There was one condition. I would not film anything. No camera, no microphone session, no editing timeline.
Four days later there are twelve finished videos. Eight came out of the daily studio: teaching Shorts, two seven-minute long-forms, product promos. Four are explainers of our own blog posts, now on YouTube. All twelve are narrated in my voice, which I recorded once. Every frame is HTML and GSAP animation rendered to MP4 by HyperFrames. The narration is a HeyGen clone. A Claude Code agent does the rest — it picks the topic, researches it, writes and lints the script, voices it, builds the frames with parallel sub-agents, checks its own work, renders, and sends the MP4 and a post kit to my Telegram before I wake up.
That is the flattering version. The honest one is that my first review said “too fast, too much content”, the fourth said the script “considers the viewer as an expert, which is wrong”, and in between I told the agent its videos looked so alike that “it will soon be noticed as AI generated”. This post is the whole machine: what it is made of, every complaint and the gate it turned into, the voice clone, what it actually costs to the cent, and how to set it up on your own computer.
TL;DR
- 12 finished videos in 4 days, with no filming. 8 from the daily studio and 4 blog explainers on YouTube, between 8 and 11 October 2026, across 34 commits. HyperFrames renders the frames locally; HeyGen supplies the voice clone and music. No avatars and no cloud rendering.
- The voice cost $8.20 in total. We loaded $15 into HeyGen’s pay-as-you-go API wallet; on 11 October the API reported $6.80 left. Measured on the clone, a minute of narration costs about $0.14. The agent’s own runs cost far more: about $18.35 for one 85-second Short and about $26 for a seven-minute long-form plus its companion Short.
- 37 pass/fail gates, and most of them exist because something went wrong. The pace gate came from “too fast”, the 12-year-old gates from “too expert”, the variety gate from “looked alike”, the hook gate from “the hook doesn’t make sense”, and the newest gate from words that were being cut in half.
- The voice was the hardest part. At HeyGen speed 0.9 the clone spoke about 3 words a second against our 2.0 target, and its timestamps run about 0.2 s late, which clipped the start off a third of all sentences. The fix is one take per sentence at 0.75, trimmed on the actual sound.
- A render takes 2.5 to 19.5 minutes on a 4-CPU machine. The longest, 12,722 frames for a 7-minute video, took 1,168 seconds. Every fix after rendering costs a full render again.
- We did not track cost per video. Every ledger entry has
cost_usd: null. That is the first thing we would do differently.
What HyperFrames and HeyGen each do
These two tools get confused, partly because HyperFrames is published by HeyGen. They do completely different jobs here.
HyperFrames is the renderer. Its own description is “an open-source framework for turning HTML, CSS, media, and seekable animations into deterministic MP4 videos”, under the Apache 2.0 licence. A video is an HTML file. Each element declares when it appears with data-* attributes, animation runs on a GSAP timeline that the renderer can seek to any frame, and a headless Chrome captures every frame before FFmpeg encodes them. Because the page is plain HTML, an agent that can write a web page can write a video, and because rendering is deterministic, the same file gives the same MP4 every time. We pinned versions 0.8.141 to 0.8.145 over the four days, one per project, and render everything on our own machine.
HyperFrames also ships agent skills — the README counts 21 — that teach a coding agent how to build compositions: a router skill, the composition contract, animation rules, a CLI skill and workflow skills such as faceless-explainer and product-launch-video. We installed them on 20 September and use them under our own skill, described below.
HeyGen is the voice. HeyGen is best known for AI avatars, and we use none of that. We use three things, all through its API:
- An instant voice clone of me, made once and verified on 8 October with word timings. Every video uses the same voice; that is part of the brand.
- Text-to-speech with that clone, which returns a WAV file and per-word timestamps.
- Background music retrieval, which costs nothing per call in our tests, and once returned nothing at all.
Everything else is ours: the research, the script, the design system, the frames, the checks and the delivery.
The pipeline: from a topic to an MP4 without a camera
The studio is a Claude Code skill called video-studio, run from cron with claude -p "/video-studio daily". Every stage writes its output to disk inside the video’s folder, so a run that dies at 3 a.m. is resumed by the next night’s run instead of being thrown away.
- Pick.
ledger.py todayreturns the delivery date, the day’s pillar, the format and what was made recently. A topic I have scheduled on our content planner takes priority. Otherwise the agent searches the web for what is trending or confusing that week.ledger.py checkrefuses a reused slug, or any topic whose words overlap 50% or more with anything from the last 30 days. - Research dossier. Every fact gets a numbered source URL in
research/sources.md. For a teaching video the solution is written and run first, and the output shown on screen is pasted from the real run. The skill’s rule: “Nothing goes on screen that is not in this folder.” - Plan.
PLAN.mdholds three hooks of different types, each scored out of 12; the story; a beat-by-beat storyboard; a script with a word budget; and a look. The agent picks the look after researching two or three reference creators, and the ledger refuses one used in any of the last three videos. - Gate A. The script must pass a linter and three separate reviewer agents (described below) before a single second of audio is generated. Voice is the only step that costs money per attempt, so it waits.
- Voice.
voice_build.pyvoices the script one sentence at a time with my clone, trims each take on its real sound, and writes a manifest of every file’s hash. - Frames. One general-purpose sub-agent per beat builds that beat’s HTML in parallel; a long-form goes in waves of eight. A HyperFrames helper assembles them into one
index.html. - Gate B.
npx hyperframes check --strict, then snapshots at the middle of every beat. The agent opens the snapshots as images and checks them against the rubric. After the render, a separate judge agent looks at frames decoded from the final MP4. At most two fix loops. - Render and deliver.
npx hyperframes render --quality high, then FFmpeg’sloudnormbrings the audio to −14 LUFS.deliver.pychecks the post kit and sends the video to Telegram with three titles, a YouTube description, an Instagram caption, hashtags, a pinned comment and the sources. It prints one line —Rendered: <slug> <seconds> <MB> msg <id>— and that line is the only proof of success the cron trusts.
The studio never posts. YouTube’s API keeps uploads private until an app passes Google’s audit, and Meta offers us no posting route, so I publish by hand from the Telegram message. That is why the most honest measure of the studio is posted divided by made, not made.
Three tracks a day
| Cron (IST) | Track | Ceiling |
|---|---|---|
| 23:00 daily | itspyguru: teaching Short, or a 16:9 long-form on Wednesday and Sunday | 3 h / $25; long-form nights 7 h / $60 |
| 14:00 daily | blog: an explainer of that day’s post on our AI blog | 2 h / $20 |
| 16:30 Mon, Thu, Sat | promo: a Cybiqon product or service | 2.5 h / $25 |
Download CSVall tables as JSONCC BY 4.0
The weekly rotation is fixed in code: an AI term on Monday, Python on Tuesday, a long-form on a trending AI tool on Wednesday, a small build on Thursday, the week’s tech story on Friday, an AI term or Python on Saturday, and a system-design long-form on Sunday. Both long-form days also get a vertical companion Short cut from the same research.
The Claude Code skill behind it
The skill is open source at cybiqon-ai/faceless-video-studio; when this post was written it lived only in our company repository. Its SKILL.md was 404 lines and has seven modes: daily, promo, blog, plan <topic>, build <slug>, revise <slug> "<feedback>" and setup. revise takes one sentence of my feedback and rebuilds only what that sentence touches.
| Part | What is in it |
|---|---|
references/ |
The quality rubric; 15 look families; the pillars; a prompt library; jargon.txt (the terms a beginner wouldn’t know) |
references/craft/ |
Nine researched craft notes: hooks, retention and story, script voice, teaching formats, visual design, product promos, platform specs, recording and lighting |
templates/ |
PLAN.md and the BRIEF.md handed to the HyperFrames workflow |
assets/ |
The brand core, the logo, vendored fonts (Plus Jakarta Sans, JetBrains Mono) and four caption skins |
scripts/ |
Six Python tools and their unit tests |
Download CSVall tables as JSONCC BY 4.0
The six scripts are the deterministic half of the system: the parts where we did not want a model’s judgement.
| Script | Job |
|---|---|
ledger.py |
Today’s pillar and format, the no-repeat check, the look-variety check, marking a video posted |
planner.py |
Reads the topic I scheduled; “never raises: a planner outage must not stop a video” |
script_lint.py |
Gate A18: sentence length, reading grade, number density, jargon, idioms |
voice_build.py |
One HeyGen take per sentence, trimmed on sound, with a hash manifest; --check is gate B17 |
gap_check.py |
Gate B16: no silence over 0.7 s between lines |
deliver.py |
Refuses delivery without the four PASS lines, the voice check and a look block, then sends to Telegram and writes the ledger |
Download CSVall tables as JSONCC BY 4.0
The craft notes are where the research went. They cite YouTube’s own help pages on Shorts, Nielsen Norman Group on dark mode, a large study of edX lecture videos on how long people keep watching, 3Blue1Brown’s FAQ, HeyGen’s and ElevenLabs’ voice-cloning guides, and awesome-opus5-5-videos, an MIT-licensed list of videos made with Claude together with the prompts their creators shared. We read that list on 10 October, and it gave us the prompt library, three new looks, two gates and the most useful single rule in the visual notes: simulate the thing, don’t depict it.
Running an agent unattended, safely enough
The cron calls a wrapper, studio/run.sh, which comes down to this:
flock -n /tmp/cybiqon-video-studio.lock timeout "$LIMIT" claude -p "/video-studio $ARGS" \
--permission-mode acceptEdits \
--allowedTools "Read,Write,Edit,Glob,Grep,WebSearch,WebFetch,Skill,Task,TodoWrite,Bash" \
--disallowedTools "Bash(git push:*),Bash(rm -rf:*),Bash(curl:*),Bash(wget:*),Bash(sudo:*),Bash(crontab:*),Bash(ssh:*),Bash(scp:*)" \
--strict-mcp-config --mcp-config '{"mcpServers":{}}' \
--max-budget-usd "$BUDGET"
Four decisions are packed into that command.
flockandtimeout. Two agent sessions never overlap, and every run has a wall-clock ceiling. The long-form ceiling of seven hours still ends before the next scheduled job.--max-budget-usd. Claude Code stops the run once its own estimate of API spend reaches the cap. The documentation is careful to say the estimate “can differ from your bill”, and that spend can pass the cap, so leave headroom.- Bash allowed whole, with explicit denies. Our first unattended run used a per-command allowlist and stalled at
cd hf && node …: a headless run cannot answer a permission prompt. Sincepython3was already allowed, listing commands bought no safety, only fragility. So the shell is open, and pushing, downloading,sudo,sshandrm -rfare refused. There is still no--dangerously-skip-permissions. - No MCP servers. The run reads the web and then runs code it wrote, because “code on screen is code that ran”. The tool scope is the limit on what a poisoned web page could make it do.
Then the check. A cron that exits 0 tells you nothing — our company’s rules say that exit code 0 “has already meant ‘did nothing’ for 33 consecutive nights” on another job. So run.sh counts: if this run’s slice of the log has no Rendered: line, I get a Telegram alert with the reason, whatever the exit code says. It also spots a logged-out CLI and says so.
37 quality gates, and the failure behind each one
The rubric has 20 plan checks (A1–A20) and 17 build checks (B1–B17). “Each line is pass or fail; there is no partial credit.” Thirty-two are hard, meaning a failure blocks the video (two of those apply only to teaching or long-form videos). Few of them were in the first version. Most were added on the day a video failed in that exact way.
| Gate | Rule | Why it exists |
|---|---|---|
| A8 | Narration at most 2.0 words a second, with a 0.4–0.8 s hold after a key reveal | The first Short, Two Sum: 97 words in 44 s. My verdict: “too fast, too much content” |
| A14 | The viewer is fixed: “a smart 12-year-old who has used ChatGPT and never coded” | The temperature Short’s script “considers the viewer as an expert” |
| A15 | Every term defined in the same breath | That script had idioms and maths words, and 17 spoken numbers in 72 s |
| A16 | Teach-back review: a fresh agent hears only the narration, a separate judge grades it | The first reviewer was told to play “a developer”, and the planner graded its own pass |
| A18 | script_lint.py passes: no sentence over 18 words, reading grade ≤ 7, ≤ 1 number per 10 s |
The mechanical half of A14 |
| A19 | Expert accuracy review: simplified is fine, false is not | An outside review caught three simplifications in the temperature Short that had become untrue |
| A2, A20 | The hook is the viewer’s own question, proven on screen by 3 s; a cold-viewer agent must get it | “The hook doesn’t make sense… I am noticing this in all videos” |
| B11 | Real footage fills ≥ 80% of the frame for ≥ 50% of the runtime | “The actual visuals were limited to very small space on screen” |
| B13 | A fresh agent must not call this video and the last three the same template | “The last two videos were quite similar” |
| B14 | A judge reviews ≥ 6 frames decoded from the final MP4, not just browser snapshots | Snapshots are not the file: our rendered frame 0 once differed from every snapshot |
| B16 | No silence over 0.7 s between voice lines | Padded frames left 3–5 s gaps in the first long-form |
| B17 | Every word is heard: each voice line was made by voice_build.py and starts and ends on silence |
A third of all sentences were losing their first ~0.2 s |
Download CSVall tables as JSONCC BY 4.0
The three reviewer gates are worth a closer look, because they are where we learned the most about using agents to check agents.
A16, the teach-back. A fresh sub-agent that has never seen the research, the plan or the storyboard gets only the narration and three “why” questions the planner wrote in advance. Its persona: “You are 12, smart and curious. You’ve used ChatGPT but never written code, and English is your second language.” It explains back what it learned, answers the questions and lists every point where it would have asked “what’s that?”. A second, separate judge then sees the narration as well, so it can tell a real gap from a point the script already explains. The first version of this judge saw only the reviewer’s notes. It kept failing points the script covered, every round of fixes added words, and a 355-word script grew to 482 without ever passing, although every teach-back had been correct. Now fixes may not grow a script past its length budget, and the planner may never overrule the judge.
A19, the expert. A beginner can understand something false. So a second fresh agent, playing “a senior ML engineer / Python core developer / systems engineer”, flags only what is false, what plants a misconception, and causal claims that are wrong. Each flag comes with a replacement that is “just as simple and true”.
A20, the cold viewer. A third agent gets only the first three seconds: the first two narration lines, the on-screen text and a description of what is visible. “You are scrolling Instagram Reels. You know nothing about this video.” If it can’t say who the video is for and what problem it is about, the hook is rewritten.
Then there is deliver.py, which refuses to send a video unless PLAN.md contains the literal lines A16: PASS (judge), A18: PASS, A19: PASS (expert) and A20: PASS (cold viewer). That is the difference between a rule and a gate. Gate A is text the agent reads; deliver.py is code that refuses.
Two things the logs show plainly. On the first long-form, the 12-year-old review “passed only on the third judge round”; the rubric says a second failure means splitting the topic, and the agent treated it as a wording fault instead. It wrote that down in the report: “That’s a deviation.” And on one Snackly revision, “the final-file review never formally passed”: two judge rounds failed, the agent fixed every major point and checked the render frame by frame itself, but no third judge ran. Both were disclosed in the delivery, which is the rubric’s rule — “Never deliver silently” — and both are why the gates keep tightening.
Cloning a voice with HeyGen: what it took
The voice is the part a viewer notices first and the part that went wrong most often.
The sample. HeyGen’s own guide asks for “30–60 seconds of expressive speech with your phone close to your mouth”; its developer docs for instant clones say only the first three minutes of a recording are used, in MP3 or WAV, up to 100 MiB. ElevenLabs notes that more than two or three minutes gives little extra for an instant clone. Our skill’s guidance splits the difference: record one continuous take of 90 to 120 seconds, then submit the best 60 to 90. The other rules come from the same guides. Use a quiet room, because the clone copies the room. Read more expressively than feels natural, because cloning flattens tone. Read the kind of script the clone will speak, in your natural accent, including the words where the accent shows. Our practice script, about 230 words, has a Two Sum walkthrough, an embeddings explanation, a line in Hinglish (“price kya hai?”) and a run of numbers. The skill’s setup mode can create the clone through the API with a helper from the HyperFrames media skills (heygen-voice.mjs clone <file> --name "Prajjwal"); ours is called “pj voice”.
The speed problem. The first fix, on 9 October, was to slow the clone to HeyGen speed 0.9. It was not enough: measured on later scripts, whole lines at 0.9 came out at 2.8 to 3.0 words a second, and the first take of the rate-limiting long-form ran 318 seconds at 3.02 words a second. Our target is 2.0, and I cap revisions at 2.2. Slowing the whole line further made it drawl.
The fix was to stop voicing lines and start voicing sentences. voice_build.py sends each sentence on its own at speed 0.75, then joins a line’s sentences with a 0.35-second breath. That lands under 2.2 words a second while keeping the gap between lines under 0.7 seconds. It has a second benefit: a fix to one sentence re-voices only that sentence, and takes are cached, so a rerun costs nothing.
The clipped-words problem. On 11 October I reported that “few words are getting cut… proper words are not hearable”. The cause was ours. The earlier script trimmed each take at HeyGen’s first-word timestamp, minus 80 milliseconds. Those timestamps run about 0.2 seconds late, so the trim sliced the start off a third of all sentences — “The” became “e”, “Step” became “tep”. On the Snackly promo, 12 of 44 sentences were clipped. Now each take is cut at its first and last audible 10-millisecond window (anything above 3% of the take’s peak), with padding and 8 ms fades, and the build fails if a trimmed take still starts or ends on speech. Gate B17 makes deliver.py refuse any video whose voice files were not made by this script or were changed after it.
The rate limit. HeyGen’s documentation lists 30 requests a minute for POST /v3/voices/speech on pay-as-you-go accounts, and a 429 Too Many Requests beyond that. We found it the hard way: on the rate-limiting long-form night it “refused 23 lines on the first try”, and because the voicing ran as parallel batches, the refusals failed silently into a log. Now voice_build.py retries with backoff and jitter, up to six times, and never runs more than about four requests in parallel. (Yes, a video about rate limiting hit a rate limit.)
What it costs to make an AI video with HeyGen and HyperFrames
Every figure in this section is first-party unless it is marked as a list price.
| Item | Figure | Source |
|---|---|---|
| HeyGen wallet loaded | $15 | Our top-up |
| Wallet on 10 Oct, 13:08 UTC | $10.52 | GET /v3/users/me |
| Wallet on 11 Oct | $6.80 | GET /v3/users/me |
| HeyGen spent, all video work to date | $8.20 | $15 − $6.80 |
| Clone TTS, test 1 | 346 characters → 22.8 s of audio → $0.05 | Balance before and after |
| Clone TTS, test 2 | 967 characters → 58.9 s of audio → $0.14 | Balance before and after |
| Music retrieval | $0.00 | Balance did not move |
| Agent run, temperature Short (85 s) | about $18.35 of a $25 cap; about $10 of it the 11 parallel frame workers | Run log, 9 Oct |
| Agent run, rate-limiting long-form + companion Short | about $26 of a $60 cap | Run log, 10 Oct |
| Daily video-idea job | about $0.25 | Cron docs |
| Rendering | no per-render charge; our own 4-CPU machine | — |
Download CSVall tables as JSONCC BY 4.0
Three things follow from the table.
The voice is cheap, and nearly all the cost is the agent. The two tests put the clone at about $0.14 per minute of finished narration. Arithmetic, not a measurement: a clean single pass of the 415-second long-form is about 6.9 minutes of audio, roughly $0.97 of voice. The agent that wrote, reviewed and built that video ran for hours. The agent figures are Claude Code’s own estimate of API spend, the same number --max-budget-usd checks; the documentation says it can differ from a bill.
Parallelism is the expensive part. On the temperature Short, the 11 frame sub-agents took about $10 of $18.35. Parallel workers are what make an 85-second Short with 11 distinct scenes possible overnight, but each one starts by loading the same skills and brief.
We cannot tell you what one video cost. The ledger has a cost_usd field, and it is null on all eight entries. The wallet total covers every voice take for twelve videos, the revisions, the abandoned takes and two pricing tests. If you build something like this, write the cost of each run into its ledger entry from day one.
Wallet or subscription? On 10 October, with about $10 left, we asked whether to keep topping up the wallet or take HeyGen’s Creator plan. HeyGen’s pricing page lists Creator at $29 a month, or $24 a month paid annually. Third-party write-ups say web-plan credits do not pay for API calls, which are billed separately; HeyGen’s pricing page links to API pricing but does not spell that out, so treat it as unconfirmed. We are staying on the wallet. Our three tracks need on the order of 175 minutes of narration a month on clean first passes. That is our own estimate, and at $0.14 a minute it comes to about $25 before revisions.
What didn’t work
Listed roughly in the order we found them. The visual ones cost render loops, and a loop on the Snackly revision took about 35 minutes.
- Too fast. Two Sum, the first Short: 44 seconds, 97 words, nine beats. I liked the animation (“hats off to the animation”) and said it was “too fast, too much content in just 44 seconds, we could have gone beyond a minute”. The agent had optimised for research on short attention spans; the audience is people learning Python. Fix: teaching runs 60–90 seconds at no more than 2.0 words a second, with a hold after every reveal (A8). “Cut beats, never pauses.”
- The first unattended run stalled. On 9 October the run got as far as building frames and then could not run
nodeornpxwithout a permission prompt nobody was awake to answer. Fix: allow Bash whole and deny the dangerous commands by name. - A HyperFrames helper deleted footage. The assembler moves each frame’s video clip out of the frame file before checking the other frames; when a check fails it stops, and the clips are gone. Two clips vanished on the Page Arcade Short; the agent restored them and flagged it as a bug in the installed workflow, not in our code.
- The videos looked alike. After the Page Arcade and ChitraYatra Shorts I wrote: “the last two videos were quite similar; this way it will soon be noticed as AI generated”, and the real footage “was limited to very small space on screen”. Fix: only the brand core stays fixed — the voice, one green accent (
#00D890), a two-second end mark. The look changes every video, from a list of families that has grown to 15: blueprint, whiteboard, isometric 3D, documentary, split-screen, editorial paper and others.ledger.py look-checkrefuses a family used in the last three videos, or a hook type or caption style repeated from the previous one. Footage goes full screen (B11). - The script assumed an expert. The LLM-temperature Short was the first video where I said “the visuals & frames of this video was very good, I am impressed. But what’s bad was the script itself.” It skipped the foundation, explained the mechanism with maths, used idioms (“long shots”) and spoke 17 numbers in 72 seconds. The review gate had flagged it twice and been overruled by the agent that wrote it. Fix: the fixed 12-year-old viewer, the linter, the teach-back with a separate judge, the expert review.
- Hooks that meant nothing to a stranger. On the Snackly promo: “the whole video is good except the beginning… the hook doesnt make sense”. Clever lines like “Ten comparisons, or five lookups” scored well on craft with a planner who already knew the topic. Fix: line one is the viewer’s own question in their words (“Why does your shop’s website load so slowly?”), and a before-and-after proves it by three seconds (A2, A20).
- Soft footage we didn’t notice. Chrome’s screencast on our machine delivers 360×640 frames whatever size you ask for, so every screen recording before 10 October was a 3× upscale. Fix: capture with
page.screenshotat device pixel ratio 3 instead, which gives true 1080-pixel frames at about 7.5 frames a second. - Frame 0 ignored the trim. The rendered MP4’s first frame showed the clip’s own first frame — prices and an “Add to cart” button — although every browser snapshot looked right. Fix: pre-trim clips with FFmpeg, and always decode frame 0 of the final file (B14 now does).
- Silence between sentences. The first long-form had 3–5 second gaps from padded frames. Even a 2-second gap felt one second too long. Fix: B16 and
gap_check.py, at most 0.7 seconds. - Clipped words, voice speed and the rate limit. All described above. The speed and the rate limit each cost 20 to 40 minutes on the night they were found.
- Smaller traps. The machine cannot fetch Google Fonts, so the first-choice look for one video was abandoned; looks now use fonts already on disk. Background jobs die after ten minutes unless given a longer timeout. An earlier voice script reused stale audio. And when the server’s timezone was switched from UTC to IST on 8 October, cron fired every job 5.5 hours early, the studio’s slot had already passed, and no video was made that night; all 14 crontab entries were converted the next day. The HeyGen music search sometimes returns nothing, and two videos reused an earlier track.
What worked
Real footage beat everything we drew. The video I liked most was a blog explainer about Google’s Gemini model taking on real jobs — “this is amazing. i loved this one.” Its footage is the real source page: Google’s announcement, captured with Puppeteer at 2×, with a green highlighter drawn on the exact sentences being discussed. The highlight coordinates were read from the page’s DOM, not guessed. The claims in it follow Google’s page rather than our own blog post. Where our post said a saving had “already” happened, Google’s page said “once rolled out”, and the video went with Google. That method is now the template for every blog video.
The simple style held up. Flat navy, one green accent and motion that shows a state changing — a pointer moving, a cell filling — got praise on the first day and still works. The isometric look on the temperature Short got the “very good, I am impressed”.
Putting gates in code, not in prose. The rules that lived only in the skill’s instructions were the ones bent under pressure: the third judge round and the final-file review above. No video has gone out without the lines and checks deliver.py enforces. The PASS lines, the voice manifest and the look-check are three short pieces of code that changed the output more than any amount of prompt wording.
Per-sentence voicing. It fixed the pace, made revisions cheap and, with the trim on real sound, fixed the clipped words. It is the single biggest improvement in how the videos sound.
You can watch what the method produces: Google gave its newest AI real jobs, the Jev explainer and how OpenAI trained agents to run enterprise software, all on our @cybiqonai channel. The audience for these is our LLMBytes daily AI blog.
How long a HyperFrames render takes
All renders ran locally on one machine: Ubuntu 24.04, 4 CPUs and 30 GiB of RAM, with HyperFrames using one worker. These are the timings from the render logs.
| Video | Frames | Render time |
|---|---|---|
| AI agents long-form (7:04) | 12,722 | 1,168 s (19.5 min) |
| Rate-limiting long-form | 12,957 | 791 s |
| LLM temperature Short | 3,600 | 526 s |
| Gemini blog explainer | 3,518 | 427 s |
| Jev blog explainer | 3,547 | 307 s |
| Snackly promo | 2,224 | 188 s |
| Rate-limiting companion Short | 2,669 | 144–185 s across four renders |
Download CSVall tables as JSONCC BY 4.0
Frame count is not the whole story: the rate-limiting long-form has more frames than the agents one and rendered in two-thirds of the time, because its scenes are simpler. The practical lesson is the one in the failure list. A render is cheap in money and expensive in time, so everything that can be checked before rendering — snapshots, the linter, the reviewers, the voice manifest — is checked before rendering.
How to set up HyperFrames and HeyGen on your own machine
The whole skill is now open source at cybiqon-ai/faceless-video-studio: clone it, run ./install.sh ~/my-studio, and follow its setup guide. The steps below are what that guide automates, if you would rather build your own.
1. Install the basics. HyperFrames needs Node.js 22 or newer and FFmpeg. We use Node 22 through nvm, Python 3.12 for the helper scripts, and FFmpeg 6.1 from apt.
sudo apt-get install -y ffmpeg
node --version # 22 or newer
2. Install HyperFrames and its agent skills. In Claude Code, add the plugin; for other agents, install the skills directly:
claude plugin marketplace add heygen-com/hyperframes
claude plugin install hyperframes@hyperframes
# or, for any agent that reads skills:
npx skills add heygen-com/hyperframes
3. Make one video by hand first. Before automating anything, render one composition yourself, so you know what a good one looks like and how long your machine takes.
npx hyperframes init my-video
cd my-video
npx hyperframes preview
npx hyperframes check --strict
npx hyperframes render --quality high --output renders/video.mp4
4. Get a HeyGen API key and fund the wallet. API usage is billed per operation from a wallet. Keep the key out of your code:
echo 'HEYGEN_API_KEY=...' >> .env && chmod 600 .env
# check the key and your balance
curl -s -H "X-Api-Key: $HEYGEN_API_KEY" https://api.heygen.com/v3/users/me
The response includes wallet.remaining_balance. The older v2/user/remaining_quota endpoint still answers, but HeyGen marks it legacy and says it will be removed on 31 October 2026.
5. Clone your voice once. Record one expressive take of 90–120 seconds in a quiet room, as WAV, and submit the best 60–90 seconds. HeyGen’s current instant-clone flow uploads the recording as an asset, creates the voice and polls it until it is active. Then voice a test paragraph and time it. If it is faster than about two words a second, don’t just lower the speed — voice one sentence at a time.
6. Trim on sound, not on timestamps. Whatever TTS you use, find each take’s first and last audible sound yourself and cut there, with a few milliseconds of padding and a short fade. Then listen to the first word of every sentence once.
7. Normalise loudness for social platforms. We use the same pass on every video:
ffmpeg -i renders/video.mp4 -c:v copy \
-af loudnorm=I=-14:TP=-1.5:LRA=11 -ar 48000 -c:a aac -b:a 192k \
-movflags +faststart video.mp4
8. Write your gates as code. Start with three: a script linter that fails long sentences and undefined terms, a delivery script that refuses a video without the review lines you require, and a voice check that refuses audio it didn’t build. Add one every time you catch a failure by eye.
9. Only then, schedule it. Run your agent headless from cron with a lock, a timeout, a budget cap, a scoped tool list and no MCP servers, and judge success by counting a line your delivery script prints, never by the exit code. Expect the first unattended run to fail on something you never saw in an interactive session.
If you would rather have this built for your business than build it, that is the kind of AI agent and automation work we do.
Verdict
The studio works. Twelve finished videos in four days, narrated in my voice, with the research, the script, the design and the delivery done by an agent while I slept, for $8.20 of voice. I would not have believed that number on 7 October.
Three things I would carry to anyone building the same thing.
Your gates will come from your failures, not your foresight. Almost every one of the 37 checks was written the day a video failed that way. Plan for it. Make the first week about reviewing every video yourself and turning each complaint into a line of code that refuses the next bad video, rather than into another paragraph of instructions an agent can talk itself past.
Measure cost per video from the first run. The wallet tells us what all the voicing cost; the run logs tell us what two runs cost. Nothing tells us what a Short costs, which is the one number a business deciding whether to do this would ask for first.
The voice is the product. Animation is where the agent impressed us fastest, and the voice is where viewers will decide whether to stay. Pace, clipped words and silence between sentences took more fixes than every visual problem combined, and they were all invisible in a snapshot.
All figures are first-party unless marked. Video counts come from the studio ledger and the YouTube upload ledger; run costs from the agent’s own reports in the run logs, which are Claude Code’s estimates rather than a bill; the HeyGen wallet from its API on 10 and 11 October 2026; the TTS cost per minute from two before-and-after balance checks on 10 October; render times from HyperFrames’ render logs; quality gates from the skill’s rubric. Owner feedback is quoted from the notes made the day it was given. HeyGen’s plan prices, rate limits and clone requirements were read from heygen.com and developers.heygen.com on 11 October 2026; the claim that plan credits don’t cover the API is from third-party write-ups and is marked as unconfirmed.
FAQ
What is HyperFrames?
HyperFrames is an open-source framework from HeyGen, under the Apache 2.0 licence, that turns HTML, CSS, media and seekable animations into deterministic MP4 videos. A video is a web page whose elements declare their timing with data attributes. It renders locally with headless Chrome and FFmpeg, and needs Node.js 22 or newer. It ships agent skills so that coding agents such as Claude Code can write compositions.
Is HyperFrames free?
Yes. The framework and its CLI are open source under Apache 2.0, and rendering on your own machine has no per-render charge; you pay only in machine time. Our renders on a 4-CPU machine took between about 2.5 and 19.5 minutes per video. HeyGen also offers hosted rendering, which we have not used. HeyGen’s voice, avatar and music APIs are paid separately.
How much does a HeyGen voice clone cost per minute of audio?
In our measurements on 10 October 2026, text-to-speech with an instant clone of our founder’s voice cost about $0.14 per minute of finished audio, through HeyGen’s pay-as-you-go API wallet: $0.05 for 22.8 seconds and $0.14 for 58.9 seconds. HeyGen’s developer documentation lists professional-voice speech at 0.6 API credits per generated minute and does not publish a per-minute price for instant clones. HeyGen’s documentation says creating an instant clone is free during its preview.
Can Claude Code make videos on its own?
Yes, with a renderer and a voice. Our setup runs Claude Code headless from cron with a custom skill that researches a topic, writes and lints a script, voices it with a HeyGen clone, builds frames with parallel sub-agents, renders with HyperFrames and sends the MP4 to Telegram. It made twelve finished videos in four days. It still needed a human to review every video and to post them.
Is the video studio open source?
Yes. The video-studio Claude Code skill is published at github.com/cybiqon-ai/faceless-video-studio under the MIT licence, with an installer, a starter studio, a filled-in example brand, and docs for setup, voice cloning, scheduling and every quality gate. You bring a HeyGen API key and your own voice; the agent runs in Claude Code and renders locally with HyperFrames. Our own studio runs the same public code, with only its config, brand and plugins kept private.
How long does a HyperFrames render take?
It depends on frame count and scene complexity. On a 4-CPU, 30 GiB Ubuntu machine with one render worker, a 74-second promo of 2,224 frames took 188 seconds and a 7-minute long-form of 12,722 frames took 1,168 seconds, about 19.5 minutes. Our other seven-minute video rendered in 791 seconds because its scenes were simpler.
What is the HeyGen API rate limit for text-to-speech?
HeyGen’s usage-limits documentation lists 30 requests per minute for POST /v3/voices/speech on pay-as-you-go and subscription accounts, and 120 on Enterprise; going over returns 429 Too Many Requests. Parallel voicing hits that limit quickly. One of our runs had 23 lines refused, so voice sentences sequentially or with a small pool, and retry with backoff and jitter.
Do you need a HeyGen avatar to make AI videos?
No. We use no avatars at all. HeyGen supplies only the cloned voice and background music; every visual is an animated HTML scene, a real web page captured in a browser or real product footage, rendered by HyperFrames. Faceless explainers like these suit teaching content, and avoid the cost of avatar video.
How long should a YouTube Short be?
YouTube allows Shorts up to three minutes long. Our own teaching Shorts run 60 to 90 seconds at no more than two words a second, after our first 44-second Short was judged too fast to follow. Long-form explainers run four to eight minutes.
Sources
- faceless-video-studio — the studio described here, open source (MIT), published 12 October 2026
- HyperFrames on GitHub — HeyGen, Apache 2.0; README read 11 October 2026
- HyperFrames quickstart — HyperFrames documentation
- HeyGen API: Usage limits — HeyGen developer documentation
- HeyGen API: Instant voice clone — HeyGen developer documentation
- HeyGen API: HeyGen Voice — HeyGen developer documentation
- HeyGen API: Get current user — HeyGen developer documentation
- HeyGen pricing — read 11 October 2026
- How to perfect your AI voice clone — HeyGen blog
- Claude Code CLI reference — Anthropic
- YouTube Shorts length — YouTube Help
- awesome-opus5-5-videos — videos made with Claude and their prompts, MIT
- FFmpeg loudnorm filter — FFmpeg documentation
- EBU R 128: Loudness normalisation — European Broadcasting Union
- We built our AI agents a wiki. They went straight to grep. — how the agents find their way around this codebase
- We built the game in six days. The store review took fifteen. — the game whose footage appears in the studio’s product Shorts
AI VideoHyperFramesHeyGenClaude CodeVoice CloningAutomation
Read next
- We deleted the voice bill. Now the studio posts its own videos.Our open-source Claude Code video studio now clones my voice offline in English and Hindi, renders on a CPU and posts to YouTube and X by itself: 40 videos in ten days, $0 for voice. Instagram is still by hand, and the post says why.
- We built the game in six days. The store review took fifteen.We built ChitraYatra in six days — 25 windows to 169, five ways to play, 72 AI-generated scenes and four generated scores — and then Google Play's review took 15 days and we missed RevenueCat Shipaton by three. This is how the whole game was made, including the rule we broke on day two.
- Our Chrome extension sat untouched for four months. Review took one day.MapWit is a free Chrome extension for Google Maps lead generation: it scores the local businesses in a search and exports them to Excel, with no server and no account. It sat untouched for four months, went from zero tests to 171 in one day, and passed Chrome Web Store review on the first round.