Communitygithub.com

michaelburshtein/thought-to-motion

将说话人视频片段、语音录音或纯文本转换为竖屏(9:16)或横屏(16:9)视频,并带有与说话内容同步的动态设计——词语同步字幕(希伯来语/英语)、关键词卡片、A/B面揭示、图标、片尾卡、品牌主题以及可选的无版权音乐。完全本地运行(Whisper/ivrit.ai + Remotion + ffmpeg),包含两道人工审批关卡。

thought-to-motion 是什么?

该技能是一个功能强大的AI Agent工具,能够将说话人视频、音频或纯文本自动转化为具有专业动态设计的短视频。它支持三种输入模式:说话人视频(保留原画面,叠加字幕和卡片)、纯语音(无需画面,生成全屏品牌画布、动态字幕和实时波形)以及纯文本(直接生成带计时字幕和场景的视频)。输出格式包括竖屏(9:16,适配Reels/TikTok/Shorts)和横屏(16:9,适配YouTube/LinkedIn)。 该技能完全在本地运行,无需上传任何数据,使用Whisper(或希伯来语版ivrit.ai模型)进行转录,Remotion进行渲染,ffmpeg处理媒体。它包含两道人工审批关卡:第一关审核运动设计计划(包括元素表格、字幕修正和视频标语),第二关审核关键帧截图以确保布局和视觉效果无误。技能还支持高级功能,如背景替换(需静态摄像机清洁画面)、虚拟摄像机(模拟多机位编辑)以及自动字幕语言(双语字幕或独立渲染)。 内置品牌配置文件(brand.json)可自定义文字标识、系列标签、主题(温暖/电影/科技)等。运动设计遵循一套完善的规则,包括安全区域(避开应用UI覆盖区域)、面部保护(卡片和面板不遮挡说话人面部)、字幕速度限制(≤20字符/秒)以及视觉效果间隔(每6秒内至少有一个视觉事件)。技能还集成了自动音频处理(噪声消除、均衡、压缩、标准化至-14 LUFS)以及可选的无版权背景音乐。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/michaelburshtein/thought-to-motion-skill/tree/main/skills/thought-to-motion

在你喜欢的 AI 中提问

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

文档

thought-to-motion 是做什么的?

创意即产品,其余皆为图层。此技能接收一段录音(说话人视频或纯语音笔记),提取其中的要点,并围绕它们设计动态效果:以说话语言显示字幕、关键词卡片、转折点揭示以及结尾提问。

三种模式:

  • 说话人视频(talking-head):保留原始画面,卡片、字幕和缩放效果叠加在画面上。
  • 纯语音(voice):无需画面(仅音频文件或从视频中提取的音频);生成全屏品牌画布,包含场景、动态字幕和实时波形。
  • 纯文本(text):无需录音;直接将纯文本转换为带计时动态字幕和场景的品牌画布,通常配以背景音乐。

两种格式:9:16(默认;适配Reels、TikTok、Shorts)和16:9("aspect": "16:9";适配YouTube、LinkedIn、网页)。同一计划可渲染为两种格式:16:9格式下,9:16布局被放置于宽幅舞台上(说话人视频模式:说话人框在右侧,动态设计在左侧)。

所有操作均在本机运行。画面、音频或文本不会被上传至任何地方。

0. 环境搭建(每台机器只需一次)

在技能文件夹中运行:

bash scripts/setup.sh          # 创建虚拟环境 + 固定版本包 + 引擎/node_modules(基于锁文件)+ 本地声音工具包

需要安装 ffmpeg、Node 18+、Python 3.10+。首次转录时会从 huggingface.co(及其文件CDN *.hf.co)下载模型至 .cache/hf。若网络访问受限制,需允许这些主机。如果已存在 Chrome/Chromium 无头 Shell,请设置 BROWSER_EXECUTABLE=/path/to/headless_shell;否则 Remotion 会在首次渲染时自行下载至 engine/node_modules。使用 .venv/bin/python 运行 Python 脚本。

您的品牌设置(仅一次)

复制 brand.example.json 为 brand.json 并填写:文字标识(您的姓名或品牌)、系列标签、用户名、品牌标语、主题(warm、cinematic 或 tech,参见 engine/src/lib/theme.js;您可在此添加自定义颜色和字体)。每个计划中的 brand、theme 和 bumpers 字段均来自此文件。若无 brand.json,则无片头、片头或片尾。

1. 素材录入(只询问无法推断的信息)

  • 源素材。含说话人的视频→说话人视频模式;仅音频或仅需语音的视频→纯语音模式(预处理将提取音频);纯文本→纯文本模式。
  • 格式:9:16、16:9,或两者(同一计划的不同 aspect 值渲染两次)。
  • 音乐:开或关。仅内置生成的背景音乐(静谧/温暖/脉冲,无版权,无需担心侵权)。若用户想要特定歌曲,请关闭音乐,由用户自行在应用中添加。
  • 字幕语言:默认为说话语言。如需第二语言,可选择 双语(同一视频中,顶部显示说话语言,下方附较小翻译:lang2 + text2)或单独渲染。
  • 主题(warm 温暖 / cinematic 电影 / tech 深蓝,参见 engine/src/lib/theme.js)、品牌文字标识 + 系列标签(或无)、结尾提问/行动号召(如有)。
  • 纯语音模式:可提供用户自己的照片(放入 <job>/public/)。

2. 预处理

纯文本模式(无录音):

.venv/bin/python scripts/prep_text.py <text.txt | "内嵌文本"> <job> [--lang he|en] [--wpm 150] [--aspect 9:16|16:9]

将文本按短语边界分割成适合字幕的行,以舒适的阅读速度标注时间,并写入 plan.draft.json(模式为"text",音乐为宁静,动效为平静)。不要改写用户的话语,仅进行分割和时间标注。然后像纯语音模式一样设计场景(第4节)。跳至第4节。

视频或音频:

.venv/bin/python scripts/prep.py <media> <job> [--mode voice] [--lang he|en|auto] [--no-cut]

标准化为 1080x1920 30fps(或音频),剪切停顿超过0.45秒的部分,清理语音(DeepFilterNet3 噪声消除 + 均衡、去咝声、压缩、-14 LUFS;默认 --clean gentle,户外嘈杂片段用 full,录音室录制用 off),复制声音工具包,并转录剪切后的时间线(包含单词时间戳)→ <job>/transcript.json。希伯来语会自动使用 ivrit.ai 模型。脚本会打印置信度低的单词,请优先检查。

可选:替换背景(说话人视频模式)

最佳效果——拍摄干净背景。 在您入座前,先拍摄3-5秒的空房间,然后走入并开始讲话。将手机固定在三脚架上,并锁定曝光和对焦(iPhone上:长按屏幕直到出现“AE/AF LOCK”),避免您进入时画面变亮或变暗。不要变焦或移动相机。prep.py 会自动检测空闲开场片段,将其保存为精确的背景参考(work/clean_plate.png),并将其(以及走入动作)从视频中剪除。若无干净背景,引擎需猜测头部和躯干后的房间。空房间也可以是一个独立的片段,从相同锁定的手机位置拍摄(可在讲话前后拍摄):

.venv/bin/python scripts/plate_from_clip.py <job> <empty_room_clip>

它仅使用该片段中静止且无人的开场部分(当有人走入时停止),通过 ECC 和仿射变换将其与讲话视频自身的背景对齐,并按通道匹配曝光和颜色。处理前请检查 work/plate_check.jpg(讲话背景 | 干净背景 | 差异图)以及打印的匹配数值。

.venv/bin/python scripts/background.py <job> <plate.jpg> --draft [--reveal SECONDS]   # 草稿:半分辨率,速度提升约4倍
.venv/bin/python scripts/background.py <job> <plate.jpg> [--reveal SECONDS]           # 最终:全分辨率
# 选项:[--match 0.65] [--wrap 0.35] [--preview SECONDS]

本地人像蒙版(MODNet)结合干净背景差异蒙版:在静态摄像机下,片段的中值画面即为空房间,任何与之不同的部分(快速移动的手、头发、手臂)保留为人物。空房间仅从每个像素点实际为空的帧中学习(先遮蔽人物),这样头部旁边的真实墙壁永远不会被误认为人物。半透明边缘(头发)会针对空房间进行去污染处理,因此不会显示旧墙壁的残留边缘。桌面线以下的所有内容(--desk auto:约下巴下方1.2个脸高;或分数如 0.9;站立拍摄时用 off)——桌面和搁置的前臂——位于人物前方,保持原样拍摄并重新打光以匹配。

使用 --moving-camera 处理手持拍摄(仅模型)。说话人背后为纯色或绿色墙壁效果最佳。然后,人物将根据干净背景的亮度和颜色重新打光,背景的光线会包裹其边缘,同时一个渐晕和颗粒效果叠加于两者之上,使它们共享同一台相机。--reveal 在指定时刻之前保留真实房间,然后过渡到新背景(当说话人在镜头前要求时效果很好)。

处理后,运行 scripts/bg_qa.py <job>:它每隔一帧比较原始和新的视频,并报告人物丢失(红色)或旧房间泄漏(黄色)的位置,按秒统计,并生成最差帧的汇总图(work/bg_qa_sheet.jpg)。在用户看到视频前,修复或标记每个失败的秒数。已知误报:在干净背景和正式录制之间移动的物体(椅子、门)会被计为“人物”;在针对这些秒数采取行动前请查看汇总图。

干净背景应与场景匹配:室内/室外、一天中的时间、暖/冷光、相机高度。输出 public/source_bg.mp4。

3. 阅读转录文本,修正错误,编写字幕

  • 修正明显的识别错误(人名、俚语、混合语言词汇)。列出每一项修正给用户查看;不得暗中改变原意。若不确定原文,请询问。
  • 删除填充词("um"、"אה")。字幕:每行一个想法,≤约42个字符,最多2行,阅读速度适中(≤约20字符/秒),提示时间来自单词时间戳。
  • 第二语言:自行翻译提示文本,保留说话人的语气和相同的时间(作为双语字幕的 text2;保持翻译简短,以便单行显示)。
  • 在从右到左字幕中,将引用的英文保持为一个连续序列(例如 "כי אני זוכר Is that cheese")——引擎会将其隔离。

4. 动态计划 → 关卡 1(审批)

首先阅读 references/motion-rules.md。然后按顺序运行 references/prompts/ 中的阶段提示,作为您自己的工作步骤(它们为审批关卡生成素材,但不能替代它们):

  1. 故事与钩子编辑器(1-story-hook-editor.md):钩子候选、开场问题及其解决、故事弧、剪辑列表。仅逐字引用。纯文本模式:改为使用 6-text-to-video-writer.md。
  2. 字幕设计师(3-caption-designer.md):分块、阅读速度、强调词、RTL。
  3. 动态导演(2-motion-director.md):每个节拍一个元素,落在对应单词上,每次一个焦点,进行变换而非替换。
  4. 声音设计师(4-sound-designer.md:在落点上稀疏的声音、音乐风格、一个静音节拍。

找出节拍(参见 references/design-rules.md):钩子、提到的名称(节目、人物、地点、产品)、关键概念、对比或选择、列表、说话人实际说的数字、转折/揭示、问题/行动号召。将每个节拍映射到一个元素(references/plan-schema.md)。向用户展示一张表格:

#时间说话内容元素原因教学点检查

还要提出视频标语(视频的主要思想,说话人实际说的一句话,约2-3秒),用于开场。同时列出:字幕修正、您添加的屏幕上事实(例如节目的年份)及其来源、主题、音效。停下来等待审批。 在此之前不进行任何渲染。

5. 编写并验证计划

编写 <job>/plan.json(结构见 references/plan-schema.md,示例见 examples/)。然后运行:

.venv/bin/python scripts/validate_plan.py <job>/plan.json

修复所有 ERROR。阅读 WARN 并修复重要项。除结构验证外,它还验证运动规则:每0.5秒有内容出现、无视觉事件间隔不超过6秒、最多同时显示2个图形、阅读速度(最大20字符/秒)、字幕时长、缩放限制、光线泄漏安全性、音效间距、静音节拍。仅在有意为之且需在关卡2说明原因的情况下违反规则。

验证器还强制执行安全区域(x: 60-900, y: 220-1420:不被应用UI覆盖的画面部分),并保持每张卡片和面板远离说话人面部(通过 faces.json 追踪)。添加 --fix 可自动移动卡片。参见 references/safe-zones.md。

虚拟摄像机(说话人视频模式,自动)

.venv/bin/python scripts/shots.py <job> [--plan plan.json]

将单个固定镜头呈现为多机位剪辑:摄像机A(广角,原始构图)、B(中景,约1.2x)和C(近景,约1.4x;16:9格式下可达1.7x),从同一帧裁剪并锚定在追踪的面部上。摄像机切换落在预处理生成的停顿剪切上(隐藏跳动),否则落在句子结尾;镜头持续3-8秒;避免连续使用同一摄像机;当卡片需要空间时使用广角,缩放和揭示时使用近景;每个变焦镜头向内推进约1.5%(平静效果)。每台摄像机都会根据卡片和字幕进行测试,确保面部保持清晰。自拍特写(面部高度超过画面三分之一)在9:16格式下不启用虚拟摄像机——没有空间进一步拉近。无AI生成的角度:所有画面保持真实且本地化。在关卡1表格中添加 "camera" 列(A/B/C)。

6. 关键帧截图 → 关卡 2(审批)

.venv/bin/python scripts/render.py stills <job>        # 关键时刻 → <job>/stills/sheet.jpg

截图表格显示辅助线:非安全区域用红色标出,追踪的面部用绿色标出。先自行查看:所有内容均位于安全区域内,无内容遮挡面部/嘴巴,希伯来语/英语顺序正确,字体已加载(无Times字体回退),无重叠。然后运行独立审查员(references/prompts/5-reviewer.md)作为另一个未看过您推理的智能体:仅向其提供截图、plan.json和转录文本。修复其列出的阻碍项,并将审查结论连同截图一起展示给用户。停下来等待审批。 审查员不得代替用户进行审批。

7. 渲染、检查、交付

.venv/bin/python scripts/render.py video <job> --name <名称>            # 540x960 草稿(默认,快速)用于审查
.venv/bin/python scripts/render.py video <job> --name <名称> --final    # 全分辨率 1080x1920,最高质量

每个审查渲染都是半分辨率草稿(540x960)。仅对已批准的最终版本运行 --final。每个字幕语言进行一次渲染(在计划中更改 lang + captions)。渲染后检查:时长是否匹配、音频是否存在、部分帧是否正常。交付MP4文件(1080x1920或1920x1080 H.264 High Profile,faststart;适用于Reels、TikTok、Shorts、YouTube、LinkedIn)以及同期生成的 .srt 字幕文件(每种字幕语言一个)。若计划中包含 "music",背景音乐会随音频自动混合并自动闪避语音。在2核CPU上,渲染耗时约为每分钟视频需几分钟。

--final 还会生成 <名称>_social.mp4:画面相同,码率约10 Mbps(足够小以用于调度API,例如Instagram约300 MB的限制),音频在最终文件中重新测量并标准化至 -14 LUFS / -1 dBTP。交付该副本用于发布,保留高码率母版作为存档。测量交付文件(ffmpeg -i <文件> -af ebur128=peak=true -f null -)并报告其响度。

视频在最后一个单词结束约0.8秒后结束(预处理保留了该尾音),因此最后一个单词永远不会被切掉。若计划中包含 "bumpers",render.py 会拼接开场→片头→视频→片尾(scripts/bumpers.py),按开场+片头长度偏移.srt文件时间,并在音画不同步时停止(参见 开场、片头和片尾)。

规则(不可协商)

  • 绝不捏造事实、数字、引用或故事。转录文本之外的屏幕上事实(日期、标题)必须经过核实并在关卡1展示给用户。
  • 不要绘制可识别的角色、标志或受版权保护的艺术作品;可使用字体和内置通用图标。
  • logo 元素例外……(此处原文被截断)

(翻译内容根据原始截断内容处理,后续部分如需补充可继续提供原文。)

相关技能