JavaScript 动画(逐帧代码绘制) 是做什么的?
制作每个像素都由代码计算的短动画电影:无需图片、无需加载字体、无需库。一个 HTML 文件包含整部作品;无头浏览器逐帧将其渲染为 MP4。
模型
使用 Claude Opus 5.5 构建和测试;绘制质量高度依赖模型。下面的自我检查需要图像输入:如果当前模型无法查看图像,请告知用户并将视觉验证视为未完成。其他模型未经测试;如果结果看起来粗糙,说明更强的模型可能有所帮助,不要声称这是最佳结果。
默认流程:不停止询问
直接运行。选择合理的默认值,并在交付时提及其他选项。仅在完全没有主题(例如“制作一个动画”,没有其他内容)时,才在开始前询问。
- 阅读需求。 从用户所说内容推断形式(故事、解说、诗歌、循环、交互页面)、时长(默认 15-20 秒;仅当主题无法在该时间内讲述时才延长)和画面比例(默认 1920x1080)。屏幕文字使用用户书写需求的语言;仅在他们明确要求或受众明确为双语时才制作双语。
references/forms.md为每种形式提供了简短结构。 - 根据主题和受众规划外观和音效, 用自己的话描述:电影是什么、外观和音效如何、为何适合该主题和受众。无需填写列表;
references/techniques.md包含各种元素,起始值是占位符,并非固定风格。切勿默认重复之前作品的外观或音效:两个不同的主题不应看起来或听起来相似。如果用户引用他人的作品(“像那个爆款”),借鉴其技巧,绝不借用其角色、故事或构图。 - 节拍网格、分镜头和分镜布局(以数据形式)(
references/storyboard.md)。先确定节奏和段落;然后按适合形式的节奏生成镜头列表(节奏表见references/storyboard.md;每个镜头包含构图、摄影机运动、动作、落点节拍、音效、转场);然后进行分镜布局(对于故事或解说,连续世界的轨迹)。这些数据以BPM、SECTIONS、SHOTS、EVENTS形式放入页面:场景、摄影机和配乐都读取它们,因此画面和声音通过构造自动对齐。对于故事或解说,检查逻辑:每个节拍由前一个节拍引起,隐喻在画面中可见。 - 从
templates/starter.html构建。 它已经是分镜头驱动的:一个用世界坐标绘制的世界,每个镜头使用withCamera,每段文本和每个关键对象使用claim()。替换占位调色板和演示世界。保持约定:draw(frame)是帧编号的纯函数。使用rng(seed)/hash2(),绝不使用Math.random或Date。 - 自我检查,然后渲染(下一节)。修复并重新检查直至干净。
- 交付: MP4 和 HTML(它可在浏览器中实时播放;点击启动声音)。然后,用一两句话提供可更改的内容:另一种外观、AI 音乐替代合成音乐、不同时长。
对于音乐,使用配乐技能(默认:在页面中使用 Web Audio 合成,无需密钥)。
自我检查(代理执行;用户永远不会看到)
node scripts/render.mjs piece.html sheet.jpg --sheet 1 # 每秒一帧,避开剪辑点
node scripts/render.mjs piece.html shot --stills 90,300,610 # 特定时刻
node scripts/render.mjs piece.html piece.mp4 # 完整渲染(如果有配乐则包含)
node scripts/asset-audit.mjs piece.html # 证明零资源:如果加载或嵌入了任何内容则退出码为 1
node scripts/layout-check.mjs piece.html # 文本与文本碰撞,或跨越已声明的对象
node ../soundtrack/scripts/sync-check.mjs piece.mp4 --cues-file piece.cues.json # 剪辑点与节拍对齐,无突兀
然后人工检查两遍,均在 references/qc.md 中:
- 分镜头一致性检查:每个镜头动作节拍处的静帧,对照其行(角色是否在分镜布局指定的位置,是否执行行中指定的动作?)。
- 导演检查:以每秒 2 帧的速度生成联系表(
--sheet .5),根据形式对节奏、构图多样性、无效帧、每个动作是否有音效、外观是否适合受众进行评分。至少进行两轮。仅渲染你更改的静帧,而不是每次重新渲染整部影片。
仅在触发时执行
| 何时 | 执行内容 |
|---|---|
| 角色出现在多个场景中 | 场景之前,单独渲染角色(表情+姿势)并根据 references/character.md 自行检查。角色暴露锚点(嘴巴、手部)以便道具附着。 |
| 用户提供了真人、宠物或地点的照片 | 使用 references/character.md 中的提取方法从照片构建角色。照片保持本地:绝不上传或将它们放入任何发布的内容中。 |
| 是真人作品且用户在场 | 在交付时(而非之前),提供使用关键道具或人物照片使其更具个性化的选项。 |
| 文字或对话气泡跟随移动角色 | 使用 placeFree(w, h, [above, right, left, below]) 放置,使其避开已声明的对象。 |
| 屏幕文字非拉丁语系(中文、日文……) | 使用 CJK 字体栈;检查每个字形是否渲染正确(等宽字体静默替换缺失字形,例如 ≈ 变成了 =)。 |
| 该页面将作为网页发布 | 交付 HTML;保留实时预览循环和点击播放音频功能。 |
防止常见失败的规则
- 时间的纯函数。 没有
requestAnimationFrame状态,没有 CSS 动画,没有累积物理:仅从t计算每一帧,否则渲染和预览不一致。 - 手绘线条的“沸腾”而非抖动。 当影片设置
LOOK.wobble时,每 4 帧更改一次抖动种子(LOOK.boil: 4),而非每帧。逐帧看起来是噪声;每秒约 7.5 次变化看起来是手绘效果。 - 身体使用圆润形状。 用椭圆和圆角矩形构建人物。顶点少的多边形看起来像标志(五边形的手,方形的躯干)。
- 选择能清晰表达姿势的角度。 从侧面看细长身体加短肢看起来像毛毛虫;同一姿势从正面(透视缩短)看起来像趴着的婴儿。
- 从后向前明确绘制。 后侧头发,再身体,再脖子,再脸,再前侧头发。大多数“某物遮住了脸”的错误都是绘制顺序问题。
- 剪辑点和动作节拍要准确。 每个剪辑点和可见动作都在
EVENTS/CUES中;配乐落点在这些节拍上(见配乐技能)。 - 文本绝不碰撞。 声明每个文本框和关键对象;
layout-check必须打印 CLEAN。覆盖显示器边缘或脸的标题看起来粗心,联系表上的眼睛会忽略它们。
文件
templates/starter.html:绘图库(墨水、插图、平面/蓝图图元、标签、纸张、滤镜层)、withCamera、claim/placeFree,以及分镜头驱动的双镜头骨架。scripts/render.mjs:MP4 / 静帧 / 联系表。window.CUES和window.SCORE可选:完整渲染时写入<out>.cues.json并混入 SCORE 配乐(无 SCORE 则为静音 MP4)。需要偶数画布尺寸。scripts/asset-audit.mjs:静态扫描 + 实时网络检查,检测任何加载或嵌入的内容。scripts/layout-check.mjs:读取整部影片的window.LAYOUT并列出文本碰撞及其时间。references/storyboard.md:节拍网格、镜头列表、分镜布局、连续性和故事逻辑。references/techniques.md:经过测试的绘制技巧(墨水、专色印刷、单线雕刻、文字形状、马克笔填充、插图形状)。references/forms.md:每种形式的结构说明。references/character.md:仅当有角色时。references/qc.md:自我检查清单。
要求:Node 18+、ffmpeg、Chrome(或运行 npx playwright install chromium),以及运行脚本的文件夹中的 npm i playwright-core(你的项目文件夹,非技能文件夹)。