Communitygithub.com

brewed-ops/talking-explainer

Talking Explainer - 将任意主题转化为配有卡通解说员的 16:9 (1920x1080, 60fps) 动态设计解说视频。解说员实时口型同步、手势配合关键词,以用户自己的声音和品牌风格进行讲解。

talking-explainer 是什么?

这是一个高级 AI Agent 技能,用于生成高质量的动态设计解说视频。其核心特色是包含一个卡通解说员角色,该角色能够实现近乎真实的唇形同步(6 种嘴型由语音驱动)、在关键词处做出手势,并伴有眨眼等细节。该技能能基于用户的声音克隆或麦克风录音,结合用户提供的主题,自动生成从钩子式开场到品牌结尾卡的完整视频。它适用于“说话解说员”、“说话吉祥物”、“让吉祥物说话”、“唇形同步解说”或任何需要发言人出镜的解说场景。技能支持的平台包括 Cursor 等支持 Agent 的 IDE,工作流由多个阶段(脚本、故事板、多工人并行渲染、最终合成)组成,并遵循严格的苹果风格视觉规范(白背景、特定字体、Solar 图标等)。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/brewed-ops/talking-explainer/tree/main/skills/talking-explainer

在你喜欢的 AI 中提问

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

文档

Talking Explainer

声音是时钟,解说员开口说话(唇形同步),每个想法首先是一张日常图片,每个场景都有一个推近镜头和一个强调时刻,外观是苹果风格,影片承载用户的品牌。工作示例:"REA - Reverse Engineer Anything"(129.0 秒,12 个场景) - references/example/(SCRIPT, STORYBOARD, RETIME)。

下面使用的路径:

  • <skill> = 此技能的文件夹。 <kit> = <skill>/../explainer-kit。 <engine> = <skill>/../spatial-film。
  • <home> = TALKING_EXPLAINER_HOME 或 ~/.talking-explainer;profile = <home>/profile/(与 explainer-kit 共享)。
  • <py> = 存储在 <home>/config.json 中的 python 命令,由 setup-check 设置(Windows 上为 py -3.12,macOS 上为 python3)。

从影片项目根目录运行每个影片脚本。脚本是经过验证的代码——运行它们,永远不要重新生成。通过联系表判断场景,切勿在主会话中读取场景 HTML。Worker 接收文件路径。

安装(仅首次运行)

如果还没有 <home>/profile/brand.json,则运行 explainer-kit 的 Phase S(setup-check,品牌访谈 + profile.mjs init、voice.md、音乐)。品牌访谈会设置解说员的名称(--presenter)。此技能额外需要两项内容,在同一个访谈中询问:

  • 开头和结尾词 在 voice.md 中,逐字写入,包含用户的名字(钩子开场是 "? 是真的吗? 在此,来自 ... 让我们来分析一下。")。
  • 解说员: 捆绑的演示解说员(一个面无表情的卡通眼镜男),或用户自己的角色——请参见下面的 "您自己的说话角色"。

默认值(请勿再次询问)

  • 旁白 使用 profile 中的语言,风格来自 voice.md 中的用户风格。屏幕上 = 简短的基础英文(每个标题行约 6 个单词)。长度不限,只要信息传达清楚即可(自然叙述时约 150-160 wpm)。
  • 用户自己录制旁白 从脚本中(他们的 ElevenLabs 声音克隆或自己的麦克风)。阶段 1 会将脚本作为可粘贴的段落提供,并等待一个 MP3 文件。仅当用户要求时,才通过 API 生成(<engine>/scripts/el-tts.py,密钥在环境变量 EL 中,从不存储在磁盘上)。
  • 开场 = 先钩子: 以关于主题最令人惊讶的主张作为问题开场,然后是 voice.md 中的开场词。主题的名称在第 2 段出现。结尾 = voice.md 中的结尾词 + profile 中的 cta。
  • 概念类主题 获得一个字面意义上的日常类比(REA:一家咖啡店的秘密拿铁配方)。关于用户自己工具或系统的“工作原理”主题 则改为对真实事物进行演练 - 请参阅 references/real-apps.md。第三方工具和平台同理:说出真实产品名称,演练真实的请求流程,并使用平台自身的文案、设置和从其实时页面读取的数字。对于任何技术主题,默认使用演练方式。
  • 短片(<= 30 秒): 大约 2.6 词/秒,4 个段落 = 4 个帧(钩子 + 身份 / 名称 / 单一画面 / 结尾),一行结尾词,2 个 worker x 2 个场景。
  • 议题/新闻主题: 首先研究实时报道(本地媒体 + 一篇深度文章),然后平衡地撰写:每个主张都附带其来源("根据该机构...","批评者说..."),恐惧感配上其真实规模,然后是一个编号的灰色地带部分,其中官方声明相互矛盾或关键细节未公开,一个公平的利好段落,以及一个需要提问的总结——永远不要给出结论。任何仅通过搜索摘要得知的内容(页面本身未能加载)将保留在 SCRIPT.md 的事实块中,标记为 "未验证,不朗读"。对于此类主题,16 帧 / 约 700 词是可以接受的。
  • 脚本来自粘贴的转录稿: 保留来源的事实和观点顺序,用叙述者的声音重写每一行(切勿逐字逐句翻译),并删除来源主持人自己的部分("我构建了..."、代码演示、他们的名字)。长篇幅粘贴内容会在大约 50k 字符处截断:在 SCRIPT.md 中注明截断位置,然后使用标准机制填充缺失部分,并像其他主张一样进行验证。第一天将粘贴内容保存到 references/source-transcript.txt,并保留来源中提到的人物和里程碑。
  • 真实人物 = 人物卡片,而不是姓名标签: 肖像(双色调照片或插画像)+ 姓名 + 一行角色 + 年份。在 SCRIPT.md 中列出每个提及的人物及其场景,位于 "People on screen" 下。
  • 外观 = 苹果风格: 白色背景(#F5F5F7 地面),Geist 字体配合特定大小的字距,模拟玻璃(.ap-glass——在 3D 引擎内永远不要使用 backdrop-filter),.ap-window / .ap-dark 面板,临界阻尼的 sp() 弹簧(禁止使用 back.*),克制(一个想法一帧,脉冲 <= 1.1),一个蓝色的 LENS 脊柱。颜色 = 含义,为每个影片重新定义。脚手架会设置所有这些。
  • 图标 = Solar(480 Design, https://solar-icons.vercel.app)—— 粗体双色调用于主要图标,线性用于 UI 镀铬,来自 references/icons-solar.html。永远不要使用 Lucide 或 Phosphor。艺术作品采用 CC BY 4.0 许可:每次交付时,向用户提供 "Icons: Solar by 480 Design (CC BY 4.0)" 这一行,用于视频描述。
  • 运动: 标题文字以逐个词的方式出现(升起 + 模糊 -> 0,弹簧),任何工具都有 UI 动画,解说图,再加上每个场景都有一次摄像机推近(ZOOM)和一个强调节拍(EMPH:脉冲、标记扫过、下划线绘制、焦点拉动、数字弹出)。遵守 60fps 流畅法则。
  • 1920x1080,60fps。品牌 Logo 在钩子中,角落 Logo 贯穿中间,结尾卡片 = Logo + cta。

阶段

#阶段操作关卡
1脚本 + 录音研究主题(真实事实,带有来源)。加载 <kit>/references/voice-script.md + <home>/profile/voice.md。钩子优先的开场 + 如上所述结尾,不要使用 "!",一个类比(或演练),12 个段落 = 12 个帧(形状:references/example/SCRIPT.md)。拼出以字母形式读出的名称("R-E-A")。关于 AI "不能做" 的说法必须对现今的模型成立。不要使用行话数字(页面,而不是 tokens;四舍五入的计数)。编写 <film>/SCRIPT.md,将段落作为纯文本交给用户(没有代码块,最后一个段落之后没有任何内容——他们将整条消息粘贴到 ElevenLabs 中;录制提示放在之前的消息中),等待 MP3;ffprobe 其长度录音在手,长度已记录
2脚手架 + 时间node <skill>/scripts/new-talking-explainer.mjs <film> --name <slug> --mp3 <take.mp3>; <py> <kit>/scripts/transcribe.py assets/audio/vo.mp3 src/timing --lang <code> --prompt "<names, jargon>"; <py> <kit>/scripts/words.py src/timing/vo-words.json(提示表)转录与脚本匹配
3故事板以 GLOBAL 时间(如下)按照 references/example/STORYBOARD.md 的形状编写 STORYBOARD.src.md:一个段落一帧,在句子停顿处剪切(总和 = 语音结束 + 2.8s),标题每行一个字段(- start: / - duration: / - src:),每个块标记其ZOOM和EMPH节拍在提示词上,颜色 = 含义,真实事实 + 虚构额外内容,两个场景共享一个主要对象时有一个 STAGE POSE 接缝。<py> src/storyboard-local.py -> STORYBOARD.md。向用户显示帧列表(每行一个)他们的 "继续"
4契约 + 解说员 + 音频编辑并运行 src/set-film.py(场景 + 语音长度)。编辑并运行 src/set-presenter.py(姿态大约在提示词前 0.1 秒;思考/行走没有嘴部——切勿在说话时进行)。背景音乐:<py> <engine>/scripts/bgm-cut.py assets/audio/bed.mp3 assets/audio/bgm-edit.wav --len <total> --a 0 <total+3> --fade-out 2.6(比背景音乐长的影片会重复主体部分:--a 0 <len> --b <bar> <len> --b ... --xfade 0.3) -> <py> <kit>/scripts/master-audio.py --len <total> -> <py> <engine>/scripts/build-presenter.py(打印 "lip sync: N poses") -> <py> <kit>/scripts/build-brand.py(打印角落 Logo 窗口)。用一个 <engine>/scripts/patch_exact.py 脚本重写每个 [FILM] 部分的 frame.md。编辑并运行 src/set-cues.py。<py> <engine>/scripts/make-harness.py; <py> <skill>/scripts/make-packets.py; node <engine>/scripts/test-scene.mjs m-presenter "<5 times>"解说员表单:嘴巴在说话时张开,姿态在提示词上
5场景references/workers.md:6 个 Sonnet worker x 2 个场景,最多同时运行 4 个(一轮修复计入次数),其提示模板(区域法则包括推送峰值、0.12 限制、仅限 Solar、苹果风格条状、永远不要虚构数字)。自行审阅中间件;对同一 worker 进行修复每个表单匹配其块,在表单大小上可读
6发布<py> <engine>/scripts/fromto-scan.py compositions/s*.html (0) -> <py> <engine>/scripts/assemble.py -> npx hyperframes@<film.json hyperframes> lint . + check . -> <py> <engine>/scripts/seam-check.py + node <kit>/scripts/seam-diff-all.mjs -> node <engine>/scripts/render-final.mjs <slug>-1080p60(后台运行;以闪光扫描结束) -> 将渲染结果转录到 .hyperframes/work/sync + <py> <kit>/scripts/sync-check.py src/timing/vo-words.json .hyperframes/work/sync/vo-words.json -> <py> <skill>/scripts/frames.py renders/<slug>-1080p60.mp4 frames.jpg --at <one per scene> 和 --zone --at <every ZOOM peak> -> node <engine>/scripts/encode-web.mjs renders/<slug>-1080p60.mp4 renders/web --name <slug> --poster <t> -> 交出路径和 Solar 信用行lint/check 0 错误,接缝在解说员框外为 0.00%,0 次闪光,同步中位数约为 0.000 秒,任何峰值处红线左侧都没有内容

时间只写一次,采用全局秒数

手动将 20 个场景的词时间转换为场景本地时间是错误滋生的地方。在 STORYBOARD.src.md 中,为每个帧指定 - start: <global>,并将提示词标记为 "word"@g<global>;ZOOM 范围和 "退出于" 时间可以是纯全局数字。<py> src/storyboard-local.py 会写出 STORYBOARD.md,其中每个时间都是本地的,检查开始链以及每个提示词是否适合其场景,并打印用于 set-film.py 的场景列表。SFX(src/set-cues.py)和解说员(src/set-presenter.py)也以全局秒数编写。

构建后的录音/语言/开场词替换(重新计时,绝不重建)

新的录音 -> 备份 compositions/、film.json、STORYBOARD.md、src/ 到 .hyperframes/work/<old>/,将旧渲染移动到 renders/<old>/ -> 将录音复制到 assets/audio/vo.mp3 -> 转录 -> 在 set-film.py 中修改剪辑 -> 解说员姿态、背景音乐、主音频、build-presenter、build-brand、set-cues、make-harness -> 编写 RETIME.md(每个场景:每个节拍 -> 其在本地时间的新提示词;包含新内容的场景获得完整块;形状 references/example/RETIME.md;"此文件优先级高于 STORYBOARD.md 时间") -> 修补 frame.md 持续时间 / Logo 窗口 / 接缝 -> 向每个相同的 worker 发送其 RETIME 部分(每次 4 个)。对于更快的录音,场景会变短:告诉 worker 在放弃一个节拍之前先缩短弹簧。

竖屏 / TikTok / Reels / Shorts 剪辑(移植,绝不重建)

  1. <py> <skill>/scripts/port-portrait.py <film> <film>-9x16 - 一个新文件夹(16:9 影片保持不变):复制源和音频,将发布的场景移动到 references/src-16x9/(worker 的规格),编写竖屏契约(针对 TikTok UI 的 frame.md 区域、worker 简介、1080x1920 起始帧、set-film 大小),将解说员移动到左下角(缩放 x0.9,脚部 y 1640)。
  2. 从新根目录:<py> src/set-film.py -> build-presenter.py -> build-brand.py(垂直 Logo = 顶部居中,y 150,在平台标签下方) -> make-harness.py -> test-scene.mjs m-presenter(解说员 x 约 26-556,y 约 1074-1640)。
  3. Workers:相同的配对,提示词 = "PORT"(从 16:9 源开始,保留复制/节拍/提示词/颜色/图标/接缝姿态,仅重新处理布局和相机)+ 竖屏区域法则:标题 y 260-500,舞台 x 60-1020 / y 520-1060(文本 x <= 920 且 y >= 680),右下角 x 580-920 / y 1080-1520,解说员 x 20-560 / y 1060-1660,y 250 之上或 y 1540 之下没有任何内容。复制另一配对对象的配对最后执行。
  4. 像阶段 6 一样发布,使用 render-final.mjs <slug>-1080x1920p60;frames.py --zone 检测竖屏并绘制解说员框和平台 UI 线。1080p60 主版本按原样上传到 TikTok。 首次通过时的问题:主要对象被压缩到右下角(改为在舞台中使节拍成为主要对象,缩小显示字体代替);在推送过程中,一个两行标题与升起的堆栈发生碰撞(在峰值处留出 >= 40px 间隙);一个次要卡片被推送拖过 y 1540(在该推送期间使其后退/变暗)。

真实应用 + 真实 logo

关于用户自己设置的影片会显示真实的应用:来自源的 logo、来自应用自身 CSS 的应用颜色(scripts/app-tokens.py)、用户的真实文件夹名称和数字、在任何 worker 开始前的隐私列表。配方:references/real-apps.md。对于该影片,frame.md 解除 "禁止第三方 logo" 的限制并列出文件。真实的网站:在第一阶段,当用户录音时,启动一个后台捕获代理(无头 Playwright,仅限公开页面):2x 视口 + 每个网站关键页面的全页 PNG、标头本身提供的 logo(保存到 assets/logos/<brand>-logo.svg)、计算出的 tokens(bg/text/accent/fonts/radius)以及真实可见的文案和统计数据 -> references/apps/README.md。脚本中的数字来自实时页面,绝不来自第三方博客。

您自己的说话角色

在一个聊天中使用参考图像生成三个图像提示(<kit>/references/mascot-sheet-prompt.md - 将 KEEP 段落替换为他们的角色),然后: <py> <kit>/scripts/cut-sheet.py --poses p.png --faces f.png --fx x.png <home>/profile/mascot-talking -> <py> <engine>/scripts/blink-fit.py <home>/profile/mascot-talking --band 0.36,0.57 -> <py> <kit>/scripts/mouth-fit.py <home>/profile/mascot-talking --band 0.36,0.57。与用户一起阅读 _review.png、_blink-review.png、_mouth-review.png。脚手架在拥有 mouth-fit.json 后自动拾取 mascot-talking/。Torch 是可选的(更锐利的放大 + 眨眼);没有它将使用 Lanczos 进行放大,并跳过眨眼。

文件

路径用途
scripts/new-talking-explainer.mjs脚手架:explainer-kit 脚手架...

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能