Communitygithub.com

thativanng/reels-maker

构建和渲染电影、视频或动画,一切由代码驱动。创建一个HTML文件,通过`window.seek(t)`按需绘制任意帧,再通过无头浏览器以2倍分辨率逐帧渲染,并合成带音频的MP4文件。

reels-maker 是什么?

`reels-maker` 是一种独特的 AI 代理技能,专门用于通过纯代码创建电影、视频或动画。其核心理念是将整个视频定义为一个确定性的HTML页面:页面必须提供一个 `window.seek(t)` 函数,该函数能根据时间参数 `t` 精确绘制出对应的视频帧,且完全不依赖实时时钟。这使得渲染过程可重复、可校验,并且可以在不播放视频的情况下检查任何时间点的画面。 该技能主要面向 AI 编程助手(如 Claude Code)以及希望用编程方式而非传统视频编辑器创作内容的开发者。它支持构建多种格式的视频(如 9:16、4:5、1:1、16:9),并特别适用于需要生成解说视频、个人展示视频、广告短片等场景。典型工作流包括:先通过 `reel-intake` 确定需求和风格,然后基于 `window.seek(t)` 编写页面,最后使用内置工具链(`render.mjs`、`audio.py`、`mux.sh`)完成高保真的MP4渲染,并自动处理音频响度、色彩空间和文件打包。 该技能通过 `SKILL.md` 文档提供了详尽的步骤指引,包括故事板、测试片段、完整构建、审核(`film-audit`)、渲染、音频合成、最终封装和封面生成。它强调确定性渲染,能避免因GPU噪声带来的细微差异,确保重渲染结果高度一致。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/thativanng/reels-maker/tree/HEAD/skills/film-engine

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

film-engine:从代码逐帧生成的电影

工具包位置: 本技能中的所有命令均在 reels-maker 文件夹(即 github.com/thativanng/reels-maker 的克隆仓库,包含 template/ 和 tools/ 目录)下运行。若项目尚未创建,请先按该仓库的 SETUP.md 进行设置。

核心理念概述

在这里,一部电影就是一个 HTML 页面,遵循唯一规则:window.seek(t) 必须仅根据时间 t,每次都精确绘制出对应的帧。画面中的任何内容都不能读取真实时钟。然后,渲染器会以 30 fps 的速度逐步推进 t,以 2 倍分辨率截取每一帧的截图,并将其传递给 ffmpeg。由于页面是确定性的,因此重渲染的结果是一致的(平均误差在单个像素级别内;GPU 噪声可能导致个别像素多达约 60 级的色差)、17.3 秒处的静止帧就是视频将显示的画面,并且所有检查(film-audit)都可以在不播放电影的情况下查看任意时刻。

工作流程(请勿跳过任何步骤)

  1. 先确定需求和视觉风格。 reel-intake 的产出是已签署的简报和故事板(格式、时长、声音、禁止出现的内容);reel-style 的产出是选定的视觉风格。在获得这两项之前,不要开始本技能的构建步骤。
  2. 故事板。 reel-intake 负责编写故事板(时间·屏幕文字·声音和字幕·原因;位于 references/brief.md),并且在开始构建前,相关人员需签署确认。如果所选风格包含横幅,则故事板需增加一列横幅内容。
  3. 测试片段。 使用选定的风格构建大约前 10 秒的内容(步行风格电影可能需要 15-30 秒来展示一个章节),生成静止帧并获得肯定答复。在视觉风格未经签字确认的情况下进行完整构建是徒劳的。
  4. 构建 整部电影(风格包中说明了如何构建各个场景)。
  5. 关卡检查(film-audit):以 40 fps 进行碰撞检查、像素探针检查,然后由独立的审核人员进行审核。在此步骤完成前,不得将任何内容展示给相关人员。
  6. 渲染: node tools/render.mjs --page reels/<name>/page.html --out reels/<name>/out/film-silent.mp4(2x 帧,使用 lanczos 算法缩放,无颜色标签)。
  7. 音频: python3 template/audio.py out/film.wav(生成一个与电影时钟同步的提示列表)。
  8. 最终封装: zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4。该命令输出响度为 −14 LUFS、带限制器、无颜色标签的 H.264 文件,以及一个与电影比例相同(短边为 720px)的手机预览版。
  9. 封面: node tools/cover.mjs --page reels/<name>/page.html --out reels/<name>/out/cover.jpg。如果页面有封面模式(starter 中的 ?cover,或来自 config 的 cover),则绘制设计好的静止帧;否则将输出 T= 时刻的帧。封面保存为电影自身的比例,大小控制在 2MB 以下,对于 9:16 的电影,还会输出一个中心 3:4 的裁剪图(用于 Instagram 网格,已记录)。LinkedIn 仅在发布时接受封面:发布后只能编辑帖子的文本(LinkedIn 帮助中心,“编辑已发布的帖子”,https://www.linkedin.com/help/linkedin/answer/a522811)。其缩略图规格(JPG 或 PNG,宽高比与视频一致,最大 2MB)来自搜索摘要中引用的 LinkedIn 帮助信息;该页面本身无法加载,因此应视为未经核实的信息。
  10. 发送 优先发送手机预览版,然后发送完整文件和封面。

页面合约

  • window.seek(T):绘制第 T 帧。它是唯一驱动动画的地方。
  • window.ready:一个 promise,在字体、纹理和第一帧加载完成后 resolve。
  • window.DUR:电影的总时长(秒)。
  • window.FILM = { w, h, format, safe }:帧尺寸和像素单位的安全区域(keep-clear zone)。所有工具都根据此信息调整窗口大小,因此页面拥有其格式的控制权。
  • 可选:window.cover() 用于绘制封面而非视频帧,FILM.coverAt 指定封面所在的时间点(tools/cover.mjs 会使用这两个设置;如果没有,则取 T= 时刻的帧)。
  • window.collide(T) 和 window._dbg:供 film-audit 使用的钩子(参见该技能)。
  • 工具通过 HTTP 提供 kit 文件夹的服务(ES 模块无法从 file:// 加载)。要在浏览器中实时查看页面,可运行 npm run serve 并打开 http://127.0.0.1:8765/template/starter.html。

格式、starter 模板和其他语言

  • template/formats.json 包含四种尺寸(9:16 1080×1920 · 4:5 1080×1350 · 1:1 1080×1080 · 16:9 1920×1080)、平台到格式的映射,以及每个平台的安全区域及其来源。简报中的格式行从中选择。
  • 每个 reels 项目都位于自己的文件夹 reels/<name>/ 中(已被 .gitignore 忽略):包含其简报、故事板、page.html(从 starter 或 film.html 复制而来)、reel.json 或 career.json,以及 out/ 文件夹。页面从工具包的根目录加载字体和 formats.json,因此副本可以在此工作。将工具指向它:PAGE=reels/<name>/page.html。
  • template/starter.html + template/reel.json 是除体素步行风格外所有视觉风格的基础骨架。其文字和时间信息位于配置文件中,它根据 ?fmt= 或配置文件调整尺寸,并将所有文字保持在平台的安全核心区域内。?guides 会以红色显示覆盖区域,仅用于检查;渲染时切勿启用此参数。它只是一个骨架,而非视觉风格:reel-style 会重写其 tokens 和布局。
  • template/film.html(体素模板)仅为 4:5 比例, 并且选择不适用安全区域(safe 为 0):其横幅和字幕被设计为靠近边缘,因此安全区域探针检查总是通过,最终由审核人员目视确认。其摄像机关键帧是为 4:5 比例配置的;其他比例意味着需要重新配置关键帧并重新运行所有关卡检查。
  • 中文、日文、韩文: starter 模板在渲染时会从 Google Fonts 加载 Noto Sans TC(仅加载配置文件使用的字符),并以约 0.72 倍于拉丁文字号的大小显示 CJK 字符(因为它们的字符是全角宽度)。使用 表示需要换行的位置:中文可以在任意两个字符之间换行,因此长行需要手动指定换行位置。template/reel.zh.json 是一个工作示例。其他语言脚本需要在字体栈中包含自己的字体。

时钟与时间

  • 整个电影使用同一个时钟 来驱动场景、摄像机、横幅、字幕和声音。当需要在后期插入一个节拍而不重新调整所有时间时,使用时间重映射:场景时钟在插入点暂停,而叠加层(如横幅、字幕)继续使用真实时钟:
    const INS = [[24.0, 5.0, 'detail']];   // 在场景时间 24.0 处,播放一个 5 秒的插入节拍
    function remap(T) { let sh = 0; for (const [a, len, id] of INS) { if (T < a + sh) return { t: T - sh, ins: null }; if (T < a + sh + len) return { t: a, ins: id, u: T - sh - a, len }; sh += len; } return { t: T - sh, ins: null }; }
    
    音频脚本需要相同的映射表:编写一个 RT(t) 函数,将插入的时长累加到场景时间上,并将每个提示点放置于 RT(t) 处,否则插入点之后的所有提示都会偏移。(模板中没有插入内容,因此其 audio.py 不需要此函数。)
  • 缓动: 摄像机的移动使用 eio,物体出现使用 eo,行走和驾驶使用 trap(梯形速度),这样移动物体不会在端点处“卡顿”。
  • 摄像机关键帧 是绝对的 A(pos, target),或者是跟随主角地面点的 F(offset, targetOffset)。使用 eio 在关键帧之间进行混合。在重要的节拍上保持镜头稳定;持续运动的镜头会显得紧张。

覆盖层(在 DOM 中,位于 Canvas 之上)

  • 横幅: 年份、公司、角色标识,以及一个时间线,其圆点会随着当前年份变化。横幅的变更应在新场景已完全显示时进行(其布景已升起、服装已更换、主角已到达),而非在代码开始构建场景时就改变。请通过查看变更前后 ±1 秒的帧序列来确认这一点。
  • 字幕: 每个节拍一行故事文字,关键词以粗体强调色显示。使用 text-wrap: balance。为读者提供大约每秒 3 个词的速度,并在快速摄像机移动暴露其后的主体之前淡出字幕。
  • 对话气泡: 跟随角色移动:映射头部点,并将气泡固定在距离画面边缘 ≥24px 的位置。
  • 结束卡片: 姓名、一句标语、擅长领域、一句引语。场景在卡片后模糊。

音频

  • 提示点写在电影时钟上,紧邻其所属的时刻(如走路时每一步、物体出现时的提示音、物体落地时的撞击声)。
  • 不要为转场添加“嗖”声效果,这会显得廉价。使用提示音、滴答声和轻柔的撞击声。
  • 默认背景音轨由 template/audio.py 生成(基于正弦波),因此可免费在任何地方使用。如果有人使用 AI 生成的音轨,请检查其许可证:某些模型的权重可能只允许非商业用途。
  • 响度:使用两遍 loudnorm 标准化到 −14 LUFS(先测量,再线性应用),然后加限制器。一遍处理会导致过冲。

渲染中的关键教训(更多内容请参阅 references/gotchas.md)

  • 以 2 倍分辨率渲染,然后缩放。 EffectComposer 会去除 Canvas 的抗锯齿效果,因此 1 倍渲染会导致边缘出现大量锯齿。
  • 不要在 MP4 中添加颜色标签。 JPEG 管道会将其标记为完整范围,导致某些播放器会错误地移动颜色。在滤镜中使用 setparams=...=unknown。
  • 同一平面上的两个面会闪烁(z-fighting)。为前面的面设置深度偏移。
  • 必须加载字体(使用 document.fonts.load),然后再在 Canvas 上绘制文字,否则会静默地使用后备字体。
  • 在无头 Chromium 中启用 GPU(macOS 上使用 --use-angle=metal)。如果不启用,渲染速度大约会慢 10 倍。

无需每个步骤都手动提示

相关人员已一次性同意了工具包的允许规则(SETUP.md 第 4 步);请在其范围内进行操作,否则他们会被反复询问以批准每个操作:

  • 使用 Write 和 Edit 工具来写入和修改文件:页面、reel.json、简报、故事板、AUDIT.md。不要使用 Python 或 Shell 脚本、heredoc 或 sed -i 生成它们;这些操作都会触发批准提示。
  • 使用工具包的测量工具(stills、probe、sheet、collide、render、cover),而不是用一次性 python3 -c 代码片段。
  • 无需使用 mkdir、循环或链条: 每个工具都会自动创建自己的输出文件夹,并允许在一次调用中接受多个时间点(例如 stills.mjs … 1.5,6,12)。
  • reel 项目自身的脚本(如声音脚本、辅助工具)位于 reels/<name>/ 目录下,并作为 python3 reels/<name>/audio.py 或 node reels/<name>/x.mjs 运行,这些操作已包含在允许规则中。

命令

每个工具都以 一条简单命令 的形式运行(使用标志、不加前导 VAR=…、不使用循环、不使用 && 链)。这样,使用者的允许规则(node tools/*)就能覆盖这些命令,他们无需批准每个步骤。环境变量仍然对脚本生效。

npm run doctor                                  # 首先检查本机环境
npm run demo                                    # 12 秒的验证演示:输出至 out/demo/
node tools/stills.mjs "2,8.5,15"                # 生成 2x 分辨率的静止帧 → out/stills(用于体素模板)
node tools/stills.mjs --page template/starter.html --format 16:9 1.6        # 使用另一种比例测试 starter
node tools/stills.mjs --page template/starter.html --cfg reel.zh.json 1.6   # 使用另一个配置文件(这里是中文)
node tools/stills.mjs --dsf 1 --out out/chk 2,8.5                           # 快速生成 1x 帧用于拼接
python3 tools/sheet.py out/chk/sheet.jpg 6 300 out/chk/t*.jpg
node tools/render.mjs --page reels/<name>/page.html --out reels/<name>/out/film-silent.mp4
python3 template/audio.py out/film.wav
zsh tools/mux.sh out/film-silent.mp4 out/film.wav out/film.mp4

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

thativanng/reels-maker

The gates every code-rendered film passes before anyone sees it. A 40 fps collision pass (no mover touches a solid or another mover), pixel probes (nothing sits over or behind a face, a head, a subtitle or the frame edge), then an independent auditor (a fresh agent) who reads frame sheets at ≥2 fps and signs off. The builder never signs off their own film. Use it before sending ANY render, after every fix round, and whenever someone says "check the film", "audit this", "is it ready", or "why does this frame look wrong".

thativanng/reels-maker

The interview before any video is built. It reads what the person already gave (source text, CV, links, brand files), then asks the rest in a few short rounds of numbered questions with a recommended answer marked, always including the format (platform, reel or video, ratio, layout, length, sound). It ends in a one-screen brief that splits "you said" from "I assumed", plus a storyboard, and builds nothing until the person says yes. Use it whenever someone asks for a reel, a video, an explainer, a career film, an animation or a "make a video about X", before film-engine or any style pack, and again when a request changes its purpose, platform or audience mid-way.

thativanng/reels-maker

Picks the look of a reel or film before it is built. It shows three genuinely different looks as stills of the same opening frame with the same words, so the person judges the look and not the content. It keeps a log of every look ever shown, so no look comes back unless asked for, and it locks one look on purpose for a series. Use it after reel-intake's brief is signed and before any test strip, whenever someone says "what should it look like", "give me options", "make it look different from last time", "it looks cheap", or starts a new reel or a new series.

thativanng/reels-maker

The voxel career-film style. A blocky 3D version of the person walks, without ever vanishing, through one scene per role. Their outfit changes as they walk, each scene rises out of the floor ahead of them, and a dark banner tracks year, company and role. Use it when someone wants their career, a journey or a "how I got here" told as a short 3D film for LinkedIn or a portfolio, says "make my career film", "turn my CV into a video", "voxel film", or wants a new chapter added to an existing one. It runs on film-engine (render, audio, finish) and must pass film-audit before anything is sent.

相关技能