Cut Monthly Video Costs From $86 to $16 With Code-Based Stickman Animation

    This article compares generative video models with pure code-driven programmatic animation for producing explainer short videos, using stickman animation as a test case. Working with an AI coding assistant, the author builds a 15-second, three-shot explainer in the browser with HTML, CSS, and JavaScript, captures the frames one by one, and composes them into a 60fps clip. The measured inference cost for the sample was about $0.54, and monthly spending dropped from $86 to $16. Readers will find why code animation fits structured explainer content, how to distill reusable "skill" assets such as skeleton baselines, motion and shot rules, and export pipelines, a four-step workflow from specification to finished video, plus cost analysis and best practices.

    Introduction: Drawing Video With Code Instead of Models

    When producing short videos for overseas markets, the stage most likely to blow the budget or drain your motivation is generating the visuals. Generative video models tend to have three problems:

    • High cost: They bill by credits or duration, and a few dozen dollars a month doesn’t last long.
    • Poor consistency: The same character easily breaks across shots—faces warp, identities drift, and expressions don’t match from one shot to the next.
    • Costly iteration: Change one line of dialogue and the whole shot usually has to be regenerated, like pulling from a gacha machine over and over.

    This problem isn’t entirely the model’s fault. Generative models are good at learning complex distributions from massive visual samples, but they don’t guarantee output that strictly follows a specific rule. Explainer short videos, however, are highly structured: character appearance is fixed, shots switch according to a script, and motion serves information delivery. For this kind of “clear rules, simplified style” content, programmatic animation is a lower-cost, more controllable alternative. The approach tested in this article: using an AI coding assistant, build the character and storyboard in the browser with HTML, CSS, and JavaScript, capture the frames one by one, then compose them into a 60fps clip with a command-line video processing tool.

    The test covered three rounds: generate a version directly with no specification at all; then distill a reusable animation “skill” asset and regenerate; finally export and compose the video. The test sample was a 15-second, three-shot stickman explainer on the theme “the pain points of a one-person company doing overseas short videos.” The measured inference cost for the sample was about $0.54, and monthly spending dropped from $86 to $16. The numbers below come from the author’s single-machine test and are not any platform’s standard billing; treat them only as an order-of-magnitude reference.

    1. Why Code Animation Fits Explainer Content

    Dimension Generative video model Pure code programmatic animation
    Cost structure Billed by generation duration or credits; a redo means paying again One-time upfront inference, then unlimited re-rendering
    Character consistency Easily drifts or breaks across shots Driven by a single skeleton definition, consistent throughout
    Changing copy Related shots often need regeneration Only change data or constants; animation keeps running
    Resolution and frame rate Limited by the model’s output specs Freely controlled by export parameters
    Output controllability Black-box generation; only repeated filtering Every element’s position and timing is traceable
    Visual ceiling High, close to real footage quality Limited; suited to stick figures and diagrammatic expression

    Note that code animation is not a replacement for generative video but a complementary approach. Realistic characters, complex lighting, and true physical effects should still be handled by generative models; stickman figures, flowchart animations, and data visualizations are better produced with code.

    2. Counter-Example: Writing With No Specification at All

    To make the comparison convincing, first simulate the “no rules” state and let the AI coding assistant generate the page directly. The prompt needs to do three things: limit the working directory, declare that no existing specification will be used, and specify the output format. A reference version:

    1. First check whether the skill specification folder in the current directory (e.g., .claude/skills)
    2. contains any stickman animation specifications. Look only at this directory; don't scan other
    3. locations on the computer.
    4. If no existing specification is used, generate a single-page 15-second stickman explainer
    5. animation in ./stickman-demo/v1-no-skill.html, explaining "the pain points of a one-person
    6. company doing overseas short videos":
    7. - 3 shots total, adapted to a 16:9 widescreen computer display;
    8. - no irrelevant decorative elements.
    9. When done, describe the result and the time taken.

    In the author’s environment, the tool confirmed that there was no stickman specification in the current directory and generated a single-file page, v1-no-skill.html, of about 11.6 KB in roughly 64 seconds. Opening it directly in a browser, the page did show content cards for “topic selection,” “filming,” “editing,” and so on, but there were three obvious problems:

    1. Disproportion: The head-to-body ratio was stiff—heads too large, torsos too short—and the same character’s proportions weren’t consistent across the three shots.
    2. Distorted lines: Arm and leg lines were crooked, and some segments were clearly detached from the torso.
    3. Mixed structure: Animation logic, styling, and page content were all written in the same file, making them hard to locate and reuse.

    The root cause isn’t that the tool “can’t write code.” HTML and CSS alone are enough to make smooth animation; the problem is a lack of constraints. Without a unified skeleton definition, every generation is a fresh guess at character proportions, and the model has no “memory” to keep things consistent from front to back. So a viable path is to first write the character and motion rules as a clear specification, then have the tool generate and correct according to that specification.

    3. Consolidating the Specification Into “Skill” Assets

    In an environment that supports a Skill mechanism, a skill is a directory containing an instruction file and optional scripts and resource files. It can be reused across projects and read on demand by the AI coding assistant. For animation, a skill asset should lock down at least five categories of knowledge:

    • Skeleton baseline: size proportions and joint definitions for the head, neck, torso, and upper/lower limbs;
    • Motion rules: joint-angle ranges for common actions, keyframes, and easing methods;
    • Shot rules: storyboard layout, safe margins, and 16:9 canvas dimensions;
    • Copy rules: text length per shot, subtitle line count, and dwell time;
    • Export pipeline: screenshot parameters, frame rate, composition commands, and audio concatenation order.

    Write these once, and every future creation calls on them directly—effectively giving the AI coding assistant an “animation production manual.”

    3.1 Skeleton Baseline: Give the Character a Mathematical Identity

    A stickman looks simple, but it’s actually a small skeleton system. A common approach introduces a normalized coordinate system: the ground center is the origin, the unit is 1, and the character’s total height is about 10 units. Here is a set of example parameters:

    1. // skeleton.js: the character's "mathematical definition," shared by all shots
    2. const SKELETON = {
    3. totalHeight: 10, // total character height (normalized units)
    4. headRadius: 0.9, // head radius
    5. neckLength: 0.3, // neck length
    6. torsoLength: 3.2, // torso length (shoulder to hip)
    7. upperArm: 1.8, // upper arm length
    8. forearm: 1.6, // forearm length
    9. thigh: 2.0, // thigh length
    10. shin: 1.9, // shin length
    11. shoulderWidth: 0.35, // half-width of shoulders/hips (offset of left/right joints from the center axis)
    12. lineWidth: 6, // line width (px, 16:9 widescreen 1920x1080 canvas)
    13. };
    14. // Compute each joint's position in the character's local coordinate system from the skeleton
    15. // parameters (character facing front, arms hanging naturally)
    16. function buildRestPose(s = SKELETON) {
    17. const { totalHeight, headRadius, neckLength, torsoLength,
    18. upperArm, forearm, thigh, shin, shoulderWidth } = s;
    19. const neckY = totalHeight - headRadius * 2 - neckLength; // neck-base height
    20. const shoulderY = neckY - 0.2; // shoulders slightly below the neck base
    21. const hipY = neckY - torsoLength; // hip height
    22. return {
    23. head: { x: 0, y: totalHeight - headRadius, r: headRadius },
    24. neck: { x: 0, y: neckY },
    25. shoulderL:{ x: -shoulderWidth, y: shoulderY },
    26. shoulderR:{ x: shoulderWidth, y: shoulderY },
    27. elbowL: { x: -shoulderWidth, y: shoulderY - upperArm }, // upper arm hanging vertically
    28. elbowR: { x: shoulderWidth, y: shoulderY - upperArm },
    29. handL: { x: -shoulderWidth, y: shoulderY - upperArm - forearm },
    30. handR: { x: shoulderWidth, y: shoulderY - upperArm - forearm },
    31. hipL: { x: -shoulderWidth, y: hipY },
    32. hipR: { x: shoulderWidth, y: hipY },
    33. kneeL: { x: -shoulderWidth, y: hipY - thigh },
    34. kneeR: { x: shoulderWidth, y: hipY - thigh },
    35. footL: { x: -shoulderWidth, y: 0 }, // both feet on the ground
    36. footR: { x: shoulderWidth, y: 0 },
    37. };
    38. }

    The leg lengths should sum to exactly the hip height, so that when the character stands naturally, both feet land exactly on the ground. This “self-consistent constraint” is the fundamental reason code characters don’t distort easily. As for appearance features like black-framed glasses or hairstyles, they can be split into a separate decoration layer that overlays on top, so changing the look doesn’t affect the skeleton. The overall approach follows the layered idea of “data defines the character, the view handles drawing,” just with joints and limbs replacing components.

    3.2 Motion and Shot Rules

    With a skeleton, you still need motion and shot rules. Motion can be expressed as “keyframes plus eased interpolation”: each keyframe gives the angle or endpoint position of each joint, and intermediate frames are computed by an easing function—there’s no need to hand-draw frame by frame. Joint-angle ranges for common actions should be written into the spec—for example, when raising a hand to wave, the shoulder joint swings between about 90° and 150°. This keeps motion natural and avoids the model freelancing into joints bending backward.

    Shot rules also need to be quantified. A storyboard can be described with a structure like this:

    1. {
    2. "fps": 60,
    3. "scenes": [
    4. { "id": "pain-point-1", "duration": 5, "caption": "One-person company: topic, filming, editing all on you",
    5. "layout": "character-left", "action": "type-on-laptop" },
    6. { "id": "pain-point-2", "duration": 5, "caption": "Generative video: gacha rerolls, credits skyrocket",
    7. "layout": "character-right", "action": "shrug" },
    8. { "id": "pain-point-3", "duration": 5, "caption": "The way out: lock the animation pipeline with code",
    9. "layout": "character-center", "action": "point-at-diagram" }
    10. ]
    11. }

    3.3 The Skill-Creation Prompt

    Here is a ready-to-use skill-creation prompt:

    1. Create a stickman animation skill under <working directory>/.claude/skills/stickman-animator. The
    2. target output is a 60fps explainer short adapted to a 16:9 widescreen computer display, including:
    3. 1. SKILL.md: the applicable scenarios, skeleton proportion conventions (total character height
    4. normalized to 10 units, head radius about 9% of total height, with lengths given for neck,
    5. torso, upper arm, forearm, thigh, and shin), allowed and prohibited joint ranges of motion,
    6. common action and shot layout rules, and general coding conventions for code animation
    7. (separate data from rendering, centralize constants).
    8. 2. skeleton.js: export the skeleton constants and the default-pose computation function.
    9. 3. render.js: draw the character and shots from pose data, and support jumping to a specified frame.
    10. 4. export.mjs: use browser automation to capture frames one by one, then call a command-line video
    11. processing tool to compose the video and concatenate the narration.
    12. 5. storyboard.example.json: an example storyboard configuration.
    13. Finally, list the directory structure and describe each file's responsibility.
    1. Use this Skill to implement the storyboard described in <target page path>: shot by shot, check
    2. whether the head-to-body ratio, joint connections, and lines are consistent. Fix anything that
    3. doesn't comply with SKILL.md, and list the changes when done.

    3.4 Reuse Value

    Once a skill is distilled, it can be used across projects, and its changes can be tracked with version-control tools; teams can also share the same set of specifications when collaborating. For an independent creator or a one-person company, this turns “re-describing the requirements every time” into “calling on a validated production manual.”

    4. From Specification to Finished Video: A Four-Step Workflow

    Environment self-check: Install the Node.js runtime, a command-line video processing tool (this article uses a common open-source option as an example), and Chrome or Edge. The export script calls on these. It’s recommended to keep the skill directory inside the working directory rather than a global one, to avoid cross-project contamination. You can also put it under version control to ensure script changes are traceable.

    1. node --version
    2. npx --yes playwright@latest install chromium

    Step 1 | Generate the page: Generate the animation again with the skill available. Write according to the skill’s specifications and explicitly specify the output path, such as ./stickman-demo/v2-with-skill.html. In the test, the new version had consistent skeleton proportions, correct joint connections, and the character with black-framed glasses throughout all three shots.

    Step 2 | Inspect and fine-tune: Open the page in a browser and check it shot by shot. Every constant in the script corresponds to a specific dimension, so adjusting proportions only requires changing numbers—no need for the model to guess again. Also check for anomalies such as content going off-canvas or clipping through. If necessary, have the tool self-check against the skill spec and list the changes.

    Step 3 | Deterministic rendering and export: The animation’s keyframe computation must be uniquely determined by time. When exporting frame by frame, jump to the corresponding time point by frame number, then capture the frame. The export script’s approach:

    1. // export.mjs (illustrative code): capture frames one by one and compose the video
    2. import { chromium } from 'playwright';
    3. import { execFileSync } from 'node:child_process';
    4. import { mkdirSync, rmSync } from 'node:fs';
    5. import path from 'node:path';
    6. const FPS = 60;
    7. const DURATION = 15; // seconds
    8. const framesDir = 'frames';
    9. const outVideo = 'stickman-15s.mp4';
    10. rmSync(framesDir, { recursive: true, force: true }); // clear old frames to avoid mixing in the previous run
    11. mkdirSync(framesDir);
    12. const browser = await chromium.launch();
    13. const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } });
    14. await page.goto('file://' + path.resolve('stickman-demo/v2-with-skill.html'));
    15. await page.waitForFunction(() => window.__animationReady === true); // wait for the animation to finish initializing
    16. for (let i = 0; i < FPS * DURATION; i++) {
    17. // the frame number directly determines the visual state, so every export is identical
    18. await page.evaluate((time) => window.__renderAt(time), i / FPS);
    19. // wait for requestAnimationFrame to actually finish drawing before capturing
    20. await page.evaluate(() => new Promise((r) => requestAnimationFrame(() => r())));
    21. await page.screenshot({ path: `${framesDir}/f${String(i).padStart(5, '0')}.png` });
    22. }
    23. await browser.close();
    24. execFileSync('ffmpeg', [
    25. '-y',
    26. '-framerate', String(FPS),
    27. '-i', `${framesDir}/f%05d.png`,
    28. '-c:v', 'libx264',
    29. '-pix_fmt', 'yuv420p', // compatible with mainstream players
    30. '-crf', '18', // visually near-lossless
    31. '-r', String(FPS),
    32. outVideo,
    33. ], { stdio: 'inherit' });

    The page side needs to provide two interfaces: __renderAt(time) computes the character pose and shot state for a given time, and __animationReady is set to true after the animation initializes, so the script doesn’t start capturing before the page is ready.

    1. // In-page illustrative code: time uniquely determines the frame
    2. window.__renderAt = (time) => {
    3. const scene = pickScene(time); // find the current shot from the storyboard config
    4. const localTime = time - scene.start; // time within the shot
    5. const pose = samplePose(scene.action, localTime); // keyframes + easing
    6. drawFrame(scene, pose); // draw according to the skeleton baseline
    7. };

    There are two key points here. First, __renderAt(time) must be a pure function: the same instant produces the same result no matter how many times it’s rendered. This avoids rendering differences across environments causing frame jitter. Second, wait for one frame to finish drawing before capturing, otherwise you may capture the previous frame’s image.

    Step 4 | Compose the audio: Generate or record narration with the same shot durations, concatenate it in order with an audio processing tool, and finally align and combine it with the video by time point. Since the storyboard data is maintained centrally, audio duration and visual rhythm can be adjusted together.

    5. Cost and Quality: Let the Data Speak

    Cost magnitude: The approach’s inference overhead comes only from generating and modifying code, independent of the final render length. The sample version of 15 seconds and three shots measured about $0.54 in inference cost, and the monthly bill dropped from $86 to $16. Actual usage will vary with version iteration and platform billing rules; readers should rely on the statistics in their own environment. With an AI coding assistant, you can use “status check” or “usage statistics” commands to view consumption at any time, rather than discovering anomalies only when the bill arrives.

    Modification cost: When changing copy, the visuals often don’t need to change—just hand the new lines to the tool. In the test, revising a version of the copy took under a minute and generated almost no new inference overhead. If the narration needs re-recording, first estimate each audio segment’s duration, then adjust the shot dwell times accordingly to keep visuals and audio in sync.

    Output specs: The export script writes resolution, frame rate, and encoding quality as parameters, adjustable on demand.

    6. Pitfalls and Best Practices

    • Avoid pointless repeats: Re-running with no change in requirements just charges again. Think through what to change before acting.
    • Make scripts repeatable: Clear the frame directory before exporting and use distinct output filenames to prevent old files from mixing in.
    • Validate layout with real data: Test text layout with longer, real copy to avoid subtitle overflow or obscuring the character.
    • Version-control the specification: The constants and rules in the skill are the character’s “design settings”; changes should be tracked and revertible.
    • Know the boundaries: For realistic characters or complex effects, still use a generative video model; this approach only handles the parts with high controllability requirements.

    7. Conclusion

    The core takeaway from this test is a single point: replacing “uncertain generation” with “deterministic rendering” is the key to driving down short-video content production costs. With the help of an AI coding assistant, developers or creators should first distill the skeleton specification and export pipeline, then have the tool generate the page according to the spec, and finally produce the finished video with deterministic rendering. The value of this workflow isn’t limited to stickman animation—any structured, iteration-heavy visualization with clear rules, such as flow diagrams, dashboard demos, or product feature explainers, can reuse the same idea.

    From $86 to $16, what’s saved isn’t just money, but the time and patience of “re-pulling the gacha” every time you change a line of copy. For independent creators and small teams, turning reusable specifications into assets and having tools execute to a standard is the way content production should work in the AI era.