Communitygithub.com

igm61799-cloud/voiceover-to-animation

将旁白或解说音频文件转换为完全由代码绘制的 2D 动画视频(MP4),无需视频生成模型或素材库——每一帧都由 Canvas 2D 绘制,精确匹配旁白的单词时间,并使用无头 Chromium + ffmpeg 渲染。

voiceover-to-animation 是什么?

此技能将用户的旁白音频文件转化为一部完整的、由代码驱动的 2D 动画短片。整个流程完全依赖编程确定性:每段场景都是时间的纯函数,因此任何一帧都可以独立渲染,从而实现即时预览、并行渲染和完美音画同步。它支持在安装了 faster-whisper、Playwright、Pillow 和 ffmpeg 的本地环境中运行。系统会先转录音频获取单词级时间戳,然后引导用户建立项目、设计艺术风格、编写故事板,再逐场景用 Canvas 2D 代码绘制动画,最后通过无头 Chromium 和 ffmpeg 合成为 H.264 + AAC 编码的 1920×1080 MP4 文件。其核心优势在于:不依赖任何视频生成模型或素材库,所有帧都是代码原创,因此风格统一、可控性强,且能通过即时静帧复核确保视觉质量。整个工作流程包括:转录→建项目→定风格→编写故事板→逐场景编码→静帧复核→最终渲染→交付,并附有详细的参考文档辅助故事板设计、引擎 API 使用和常见陷阱规避。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/igm61799-cloud/voiceover-to-animation/tree/HEAD

在你喜欢的 AI 中提问

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

文档

旁白 → 代码驱动的 2D 动画短片

你正在制作一部短片,而不是幻灯片。旁白是固定的;你的工作是构思观众在每一刻看到的内容,用代码绘制出来,并交付一个 MP4 文件,使其剪辑和视觉节拍精准落在对应的单词上。

整个流程是确定性的:每个场景都是时间的纯函数,因此任何一帧都可以独立渲染。这一特性赋予了其他所有能力——即时静帧用于审查、并行渲染、完美的音频同步。

机器上所需的内容

在开始前检查这些;它们是唯一的依赖项。

python -c "import faster_whisper, playwright, PIL; print('ok')"
ffmpeg -version

缺失的组件:pip install faster-whisper playwright pillow,然后 python -m playwright install chromium。ffmpeg 必须在 PATH 中。如果某些内容无法安装,请告知用户缺少什么,而不是切换到更弱的方法。

工作流程

保持用户视角的简单:他们给了你音频,并想要一部影片。按顺序执行以下步骤,并保持一个可见的任务列表。

1. 先听:单词时间戳

python <skill>/scripts/transcribe.py voiceover.mp3 work

它会打印带有开始/结束时间的句子以及每个单词的 word@start 格式,并保存 work/words.json。下游的一切都根据这些数字规划。注意总时长。

2. 在音频旁边设置项目

将 <skill>/assets/template/ 复制到工作文件夹,使其看起来像这样:

voiceover.mp3
render.py
src/index.html  src/engine.js  src/scenes.js  src/main.js

阅读 src/engine.js 一次(它很短),并浏览 references/engine-api.md,以便了解你已有的工具:缓动、种子随机数、摄像机、部分路径绘制以及印刷风格的元素(云、雨、闪电、烟雾、天际线)。

3. 确定艺术方向,然后根据单词进行故事板

选择一种视觉语言,并贯穿整部影片:一个小调色板(五到六种颜色),一种边缘和纹理处理方式,一种绘制人物的方式。模板附带了一种凸版印刷/版画风格(骨色纸张、海军蓝墨水、朱红、金色、摇摆的手切边缘)。使用它,或者通过更改 scenes.js 中的调色板和 POST 开关来重新设计样式——但不要在场景之间混合风格。多样性来自于每个场景中哪种颜色占主导(夜景、纸色场景、红色场景),而不是改变规则。

然后在编写代码之前编写故事板:一个包含镜头绝对开始/结束时间、每个镜头覆盖的单词、屏幕上显示的内容以及每个节拍对应的确切单词的表格。阅读 references/storyboarding.md 了解如何将旁白转化为图像——这是决定影片质量的部分。

简而言之:

  • 每个短语一个想法。包含三个从句的句子通常是三个镜头或一个镜头内的三个节拍。
  • 展示事物,而不是添加说明。重复旁白的屏幕文字会让观众阅读而不是观看。默认没有文字;名称、真实数据以及图表上的简短中性标签是例外。如果用户有文字偏好,则以他们的要求为准。
  • 给影片一个主线:一个反复出现的角色或主题,以及在结尾处对开头某些内容的呼应。
  • 有目的地改变尺度和摄像机:广角、特写、图表、地图、剖面图。连续两个镜头不应具有相同的构图。
  • 如果旁白以妙语结尾,则在最后一个单词后添加 1-2 秒的静音尾巴,以便最终图像能够落下。render.py 会填充音频。

4. 先完整构建一个场景,再写其他场景

在 src/scenes.js 中编写第一个镜头,将其注册到 SHOTS 中,并查看它:

python render.py stills 0.3,1.5,2.9 first

然后用 Read 工具打开 work/first.png。在编写其他场景之前先执行此操作:它验证了流程,更重要的是,让你在更改风格的成本仍然很低时就能判断风格。

5. 一次编写几个剩余的场景

保持系统正常工作的规则(每条规则的存在是因为违反它会导致特定的失败):

  • 时间的纯函数。 一个镜头是 function name(g, t, u),其中 t 是绝对秒数,u 是自镜头开始的秒数。没有在帧之间累积的变量,没有 Math.random(),没有 Date。使用 hash(n)、noise1(x)、rng(seed)。帧是由多个浏览器同时无序渲染的;任何有状态的东西都会表现为闪烁或无法匹配的块。
  • 使用绝对时间进行动画。 编写 E.out(seg(t, 12.62, 13.1)),直接使用来自单词列表的数字。当剪辑发生变化时,节拍仍会落在对应的单词上。
  • 一切都要有点移动。 保持的帧会被视为错误。给每个镜头一个缓慢的摄像机漂移(1 + u * .01 缩放就足够了)和一些次级运动(雨、烟雾、摇摆的物体)。
  • 对所有内容使用缓动。 E.out 用于到达的物体,E.inOut 用于摄像机移动,E.back 用于弹出,E.bounce 用于着陆。线性运动看起来机械。
  • 每当摄像机拉远或抖动时,绘制的世界要比画框大。 背景和地面要远远超出 0..1920 的范围,这样任何边缘都不会暴露。
  • 冲击效果需要三件事:一个 2-3 帧的全屏 flash,一个衰减的 shake,以及一个反应(烟雾、后坐力、颜色翻转)。
  • 将场景代码拆分到多个文件中(s1.js、s2.js、...),一旦一个文件超过几百行,就将它们添加到 index.html 中,位于 scenes.js 之前。

编写两到三个镜头,渲染它们的联系表,查看,修复,继续。不要盲目地编写整部影片。

6. 使用静帧进行审查——这是你的眼睛

你无法观看视频,因此联系表就是审查手段。对于每个镜头,至少采样开始、主要动作的中间和结束,以及每个节拍的确切帧:

python render.py stills 12.2,13.3,14.3,15.4,16.5 act2     # 每个表最多约 16 个时间戳
python render.py sheet 4                                   # 整部影片,每 4 秒一帧

使用 Read 工具读取 PNG,并逐个镜头检查:主体是否大到一眼就能看清?是否有任何内容被裁剪、重叠或悬浮?重要事物与背景之间是否有对比?它看起来是经过设计的,还是画框的一半是空的?然后修复并重新渲染相同的时间戳。references/pitfalls.md 列出了那些容易犯却难以察觉的错误。

页面错误由 render.py 以 PAGE ERROR: 行的形式打印——黑色或半画的帧通常意味着该镜头中出现了异常。

7. 渲染并验证

python render.py full --workers 8

在后台运行它;一部 70 秒的影片大约有 2,100 帧,需要几分钟时间。它会写入 output.mp4(1920×1080,H.264 + AAC,音频填充至全长)。然后验证文件本身,而不仅仅是静帧:

ffprobe -v error -show_entries format=duration:stream=codec_name,width,height -of default=nw=1 output.mp4
python render.py sheet 6

确认时长、存在音频流,并且概览表中没有空帧。在你的报告中明确说明你检查过静帧和文件属性,但尚未观看其运动效果——用户应该观看一次。

8. 交付

向用户提供 output.mp4 的路径、概览表,以及一行关于编辑后如何重新渲染的提示。在浏览器中打开的 src/index.html 是一个包含音频的实时播放器,这是他们检查时间最快的途径。

声音

除非用户要求音乐或音效,否则只交付旁白。如果他们要求,则在最终混流中将其作为额外的 ffmpeg 输入添加,时间与用于视觉内容的相同节拍列表对齐。

参考文件

  • references/storyboarding.md - 将旁白转化为镜头;节拍定位;视觉隐喻;使场景看起来经过设计的元素。在第 3 步之前阅读。
  • references/engine-api.md - engine.js 中的每个辅助函数及其一行用法。在第 5 步之前阅读。
  • references/pitfalls.md - 通过艰难方式发现的失败模式及其修复方法。在第 6 步之前阅读。
  • references/example-bells/ - 一部完整的 71 秒影片(16 个镜头,约 900 行场景代码)及其故事板。阅读 storyboard.md 以了解预期的规划水平;当你想要了解某个特定效果(跟随攀爬角色的摄像机、爆炸、地图、画线的羽毛笔、眯起的眼睛)是如何构建时,打开 src/s*.js 文件。

相关技能