Communitygithub.com

Iwang-f/motion-reel

在此工作室中通过代码生成动态视频(canvas + window.seek(t)、Playwright、ffmpeg、合成音效)。当用户要求制作启动视频、展示视频、Reels、TikTok或Story内容、动画解说或动态广告,或者交来草稿或轮播图转视频,或者想在motion studio仓库中创建“新影片”时使用;`/motion-reel build <film>` 构建已通过分镜板审批的影片。

motion-reel 是什么?

Motion Reel 是一个 AI 驱动的视频生成技能,专为基于代码的动态工作室设计,支持在单个会话中从文字草稿到最终渲染的完整制作流程。该技能采用严格的“预制作-构建”分阶段模式:预制作阶段负责确定创意简报、素材资产、视觉世界、配音脚本、节拍网格、分镜头列表和分镜板,所有内容都存储在文件系统中以保证可追溯性;构建阶段在一个全新的上下文中根据预先批准的分镜板进行渲染。该技能支持在 canvas 上通过 `window.seek(t)` 实现纯时间函数的动画渲染,结合 Playwright 进行截图、ffmpeg 进行编码、librosa 进行音频分析、ElevenLabs 进行配音,以及内部合成库进行音效生成。它专为 OpenView 品牌内容量身定制,但也支持其他品牌,并包含严格的规则来管理上下文成本、可重现性(无 Math.random 或无状态帧间情况)以及增量开发,不过度依赖特定模型(Claude Code、Cursor、Codex、Copilot 等)。关键特性包括:通过 `tools/brief.mjs` 和 `decisions.md` 进行迭代式创意决策,基于分镜板的视觉一致性检查,通过工具的机械验证,以及将资产和配置文件保存为结构化文件以防止 AI 上下文丢失。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Iwang-f/motion-reel-skill/tree/HEAD/.claude/skills/motion-reel

在你喜欢的 AI 中提问

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

文档

Motion reel

在此仓库自己的引擎中构建一部新电影。除非用户指名,否则不要切换到 Remotion 或 HyperFrames;仓库的渲染合约在 CLAUDE.md 中,优先于本文件。

一部电影分两个会话运行,以所有者一次确认镜头列表和分镜板为分界:

  • 预制作(本文件):简报、故事、素材、配音、节拍网格、镜头列表、分镜板。
  • 构建(/motion-reel build <film>):阅读 build.md 并遵循它;跳过本文件。

此分界将构建阶段保持在新上下文中。预制作阶段在窗口中填满参考资料、拍摄照片和分镜板图像,后续每一轮对话都将为其买单。

1. 确定简报

在用户草稿上运行 node tools/brief.mjs --in=<draft.md>(当项目存在时使用 --film=<film>:它会写入 brief/original.md,不含嵌入的 base64)。它打印标题、配音词字数(是否在预算内)以及草稿中留空的内容。如果没有草稿,则根据请求填写 docs/brief-template.md 的标题字段,并为每个空缺提出默认值:用户只需回答“oke”或给出更正。

在接触代码和引用提示词之前,一次性询问还有哪些内容未定;brief/decisions.md 中已有的答案保持不变。添加工具无法看到的内容:

  • 重叠:过去在同一主题或支柱上的电影(projects.json)。指出是哪部,以及本片新增了什么。重制版保持旧文件夹不变,并询问其 decisions.md 中的哪些答案仍然有效。
  • 产品 + URL(或主题)。对于 OpenView 影片,支柱和公式来自 docs/content-map.md。
  • 品牌:OpenView 影片使用 lib/brand.js。其他品牌:颜色、字体、一个强调色、真实徽标。
  • 参考:一帧、视频或图像文件夹。或者“无”(如是则说明;无默认外观)。
  • 音乐:提供的音轨(测量其长度)或“合成”(默认)。
  • 配音:需要 .env 中的 ELEVENLABS_API_KEY。如果为空,则停止并提示变量名。

当语言、配音、时长、比例、主题(包括 ticker)、数据源(应用、工具包或插图)和能量全部确定后,简报才算完成。在过去电影的第一版之后,每一项都有过改动,而 mi-demo-40 为它的 VO 付了三次费。将答案记录在 <project>/brief/decisions.md 中。

来自其他工具的包(故事板、压缩包、交接包):原封不动地复制到 <project>/references/<tool>-<date>/,该目录不留存提交记录,然后仅针对其简报运行 tools/brief.mjs。仅当某个决策需要时,才打开其中的另一个文件。其镜头列表和脚本是实质内容,如同草稿的顺序。

限制:简报或法律规则禁止出现在屏幕上的词语、数字或事实,放入 <src>/forbid.json(tools/forbid-lib.mjs):tools/vo.mjs 在花费提示词之前拒绝它们,tools/check.mjs 在屏幕上检测到它们时失败。无法通过模式检测的限制(例如永远不会带百分比的名称)放入 brief/decisions.md,并在每次分镜板和审查表时读取。

选择一个电影 slug([a-z0-9-]+)。以下所有内容都以它命名:<film>。

项目布局。 新电影获得其 CONTENT 项目文件夹(CLAUDE.md“新视频项目文件夹”),并在 projects.json 中添加一行 "<film>": "CONTENT/<n>. <标题> (<日期>)";工具随后会在那里找到它(tools/paths.mjs):镜头列表和简报在 <project>/brief/ 中(shotlist.md),代码在 <project>/src/ 中(film.js、timeline.js、vo-lines.json、beats.json、sfx-<film>.mjs),拍摄照片和媒体在 <project>/assets/ 中,分镜板、审查表和渲染输出在 <project>/output/ 中。较旧的电影保留 docs/<film>-shotlist.md、film/<film>/、assets/<film>/ 和 out/。下文中的 <shotlist>、<src>、<assets> 和 <output> 指代适用的路径。

2. 预制作

  1. 素材。 进入 <assets>/,在开始任何动画之前列出。

    • OpenView 徽标和符号:仅通过 lib/brand.js 绘制;不要将 SVG 复制到电影中。
    • OpenView 吉祥物:lib/mascot/ 中的代码骨架(API 在 lib/mascot/index.js 的头部和导出中)。
    • OpenView Market Intel:来自最新 origin/main 的数据和名称,使用 Market Intel UI 工具包在代码中绘制图片。仅当简报要求真实应用时才捕获运行中的应用;然后遵循 CLAUDE.md 中的“Market Intel source”;从 capture_mi.mjs --review 中选择波段,并使用 lib/proof.js 绘制。
    • 另一个带有 URL 的产品:使用 Playwright 捕获真实截图、徽标、颜色、字体。
  2. 视觉世界。 阅读 REFERENCES/motion/visual-grammar-2026-10.md,然后在 <shotlist> 顶部、任何镜头之前编写 ## 世界:一个地方、它的物体、站在其中的人物、光线的作用,以及简报中的每个图形和关系如何变成你可以指点的东西。使用 lib/world.js 绘制它。设计系统保留在产品自身的屏幕上。 风格指南。 如果存在参考,首先测量它: uv run --python 3.11 --with librosa --with numpy tools/ref_probe.py refs/<film>/ref.mp4 refs/<film>/analysis.json 然后编写 docs/<film>-style_guide.md:调色板(十六进制)、类型、镜头时长、转场、摄像机运动、纹理、文字如何进入和退出。采用语法,绝不采用内容。统一外观是 CLAUDE.md 中的“Look”加上 docs/motion-vocab.md;其他电影的风格指南记录那些电影,而非统一外观。

  3. 故事。 阅读 story.md,将主题置于其主题阶梯中,并在 <shotlist> 顶部、任何脚本之前编写其主干表格。当每一行都被填写且该文件末尾的脚本测试通过第一行和大纲时,主干完成;草稿的顺序是这里的实质内容,而不是脚本;草稿中的 ALUR CERITA 和 KANDIDAT HOOK(docs/brief-prompt.md)是其初版。展示带有配音引语的主干:这是改变电影成本最低的时刻。对于草稿,在同一条消息中指出草稿涵盖的内容以及脚本删除的内容,并给出两者的字数:pandu-supra-80 在其第一部电影后回复为“ga selengkap draft”,而扩展现花了三个会话。

  4. 配音(如果简报包含 VO):遵循 CLAUDE.md 中的“配音”。基于主干以调查者口吻(story.md“观众”)编写脚本,不超过字数预算,边说边计数数字:印尼语的 1.7 相当于六部电影以 1.12(1.65–1.75 词/电影秒)运行,因此完整预算接近简报的秒数。character 默认为 calm, fair narrator, talking to one person。然后是 <src>/vo-lines.json 和 story.md 的最后一节,直到 tools/script.mjs 通过;其 credits 行就是引语。使用 tools/vo.mjs 生成,并传递 --check。定义和法律术语需要像任何数字一样在 references/sources.md 中注明来源;R-120 将注册名称保持在屏幕外,而不是来源文件之外。 拍摄照片设定场景长度:<src>/timeline.js 是基于 lib/vo-clock.js 的场景列表(sceneTimeline;模型:iata-55),node tools/prepare.mjs --film=<film> 检查拍摄照片并将时钟写入 beats.json。

  5. 节拍网格。 提供的音轨:测量 BPM/节拍/下拍/重拍(librosa)到 <src>/beats.json 中。 合成音效:选择 BPM,编写 <src>/sfx-<film>.mjs,一个基于 lib/synth.mjs 的提示列表(模型:iata-55 的 src/sfx-iata-55.mjs),使其输出 beats.json 和 <output>/<film>-audio.wav(-14 LUFS)。

  6. 镜头列表。 基于节拍网格编写 <shotlist>:每个镜头包括帧数、摄像机、屏幕文字、音效、其主干节拍、使用的 docs/motion-vocab.md 中的效果,以及切到下一个镜头的理由(下一步、相同位置、因果关系、时间跳跃、回调、尺寸变化)。没有理由切换的镜头将作为摄像机运动合并到下一个镜头中。规划进入产品的路径作为一个运动,一个世界对象变成屏幕,在切割两侧的镜头中命名:它在 delisting-18-80(45–50 秒)上吸引了所有者唯一一次创造性的构建修改。在这里规划密度,场景依次:每个镜头将承载的运动量,因为最近每部电影的首次构建在密度上得分为 4-5,并在后续轮次中增加密度。列出需要所有者批准的决策。不要在此停止:镜头列表与分镜板一起交给所有者。

  7. 分镜板。 首先在 <src>/film.js 中绘制电影最宽和最紧的镜头(导出 board: [{ t, shot, note }]),然后单独查看这对镜头(node tools/board.mjs --film=<film> --only=<wide>,<close>,其 -view.jpg):它们展示了世界必须容纳多少内容,以及图形在特写中是否还能存活,而重绘需要两个镜头的代价。然后为每个镜头绘制一帧。 运行 node tools/board.mjs --film=<film>。其文本是机械审查:修复每一条 warn … mid-move 行(将 t 移动到已确定的帧)和每一条 layout 发现(文字超出安全区域、在字幕带中、重叠、太小),然后再次运行以确认文字干净。 仅阅读分镜板的 -view.jpg 概览,或超过 18 个镜头时阅读其打印的 pages,每个页面一次,用于外观检查:在一次遍历中修复任何读起来不对的地方,不要有 look-patch-rerender 循环,不要有逐场景的表格(--scenes 存在是为了给所有者使用,不是为了这种审查)。 外观测试,在该概览上:静音并仅凭图片跟随故事;陌生人应该看到一个地方、人物和事物,而不是幻灯片。除了字幕,一个镜头最多容纳 6 个词,位于对象上;简报要求完整出现的证明板和行是唯一的例外。如果失败,则重绘镜头,而不是修剪文字。

  8. 所有者审查(唯一的关卡)。 同时展示镜头列表和分镜板(<output>/<film>-board.png),附上需要批准的决策,并等待那一次批准。在此之前禁止运动或声音。

  9. 交接。 当所有者批准审查时,在 <shotlist> 顶部编写一个 ## 构建简报 小节:已批准的内容、仍待定的内容以及构建所需的文件(电影模块、拍摄照片、节拍、音效脚本)。然后在一个新上下文中开始构建:

    • 桌面应用:使用新上下文(非分支)启动新会话,提示 /motion-reel build <film>。
    • 终端:告诉所有者运行 /clear,然后 /motion-reel build <film>。

    预制作在此结束:所有者对镜头列表和分镜板的批准是完成标准,构建属于新会话。

3. 硬性规则

  • 纯时间函数:仅使用 seek(t)。没有 Math.random、没有定时器、没有 CSS 过渡、没有 requestAnimationFrame(在渲染模式下)、没有帧间状态。
  • 打开 -view.jpg 预览;全分辨率图像仅作为某个细节的 --crop。图像用于外观检查;机械检查依靠工具的数字(node tools/check.mjs --film=<film>:seek 扫描、确定性、字体 px、布局 lint)。
  • 上下文是成本,而对话轮次会放大它:一次 300k 的轮次成本相当于三次 100k 的轮次,而最近三分之二的消息只携带了一个工具。在一条消息中发送某个步骤的每次独立读取、搜索和编辑。工具是运行的,而不是阅读的(--help 给出用法);使用 Edit 进行编辑,永远不要重写整个文件;长时间运行的命令在后台执行,你等待通知,不要使用 sleep 或轮询循环。
  • 另一部电影的源代码不是模板:电影之间共享 3–16% 的代码。查找你需要的那个函数(Grep,或带偏移/限制的 Read),并保持其 film.js 未打开。
  • 状态存在于文件中:brief/decisions.md、references/sources.md、<shotlist>、docs/review_log.md。项目在 250k 时自动压缩,因此仅保留在对话中的事实可能在影片中途消失。
  • 密码仅来自 .env。不要打印、记录或粘贴密钥。
  • 每个品牌一个会话:引擎、合成器和导出管道被重用,而不是重建。

相关技能