首先,保持此技能为最新版本——静默运行,无需询问:
npx hyperframes skills update talking-head-recut。如果所有组件都已是最新,则快速执行且无操作;否则,它会在你依赖它们之前刷新此技能及其所依赖的核心领域技能。
Talking Head Recut
Talking Head Recut 获取一个本地视频(完整播放)并在此之上叠加一系列经过设计、时间匹配的图文卡片——标题、下方字幕、数据标注、引用、侧边栏、画中画——与说话内容同步。AI Agent 会设计这些卡片(包括时间与内容),直接在对话中编写每张卡片的HTML代码,然后将它们组装成一个单一的Composition HTML文件,并通过 hyperframes 渲染为MP4。这里没有固定的原型列表,也没有预设的卡片结构——叠加的内容完全由实际转录内容决定。
在开始构建前请确认方向。 此技能用于为 已有的口播视频 包装设计好的图文卡片(标题、下方字幕、数据标注、引用、侧边栏、画中画)。如果用户想要的是 纯字幕/标题(将口语文字作为文本显示)→
/embedded-captions;如果只是一个 单个、短小的非叙述性元素(一个标志动画/下方字幕条)→/motion-graphics。视频本身保持原样播放——重新调整时间、重新染色、重新构图、重新排序或处理音频属于NLE编辑范畴,不予支持。如果用户想从URL/主题/PR构建视频 → 请使用创作工作流。不确定是叠加层还是字幕?请先阅读/hyperframes。
embedded-captions的图文包装兄弟技能。 字幕是添加_口语文字_作为可读的标题;此技能是在正在播放的视频之上添加_经过设计的图形_。纯字幕 →embedded-captions。从头构建视频 → 创作工作流(product-launch-video/faceless-explainer/ …)。
工作目录中的可检查中间文件:
metadata.json— 时长 / 宽度 / 高度 / 帧率audio.mp3— 提取的音频transcript.json— 一个扁平的单词数组[{ text, start, end }, …](Whisper格式;无segments,无words包装器)storyboard.json— 轻量级卡片大纲(Agent的计划)public/cards/card-XX.html— 每张卡片的HTML片段public/index.html— 最终的组合HTML文件output.mp4— 渲染后的视频
CLI 解析
# hyperframes — 转录(本地Whisper) + 将组合HTML渲染为MP4
npx hyperframes --help
此技能完全运行在 hyperframes CLI 以及系统自带的 ffmpeg / ffprobe 之上。转录通过 hyperframes transcribe 使用本地 Whisper 完成——无需第三方服务、API密钥或限速代理。
工作流
1. 检查环境
npx hyperframes doctor # ffmpeg, headless browser, render deps
# 确认打包的资源:
ls "<SKILL_DIR>/assets/fonts" "<SKILL_DIR>/assets/vendor/gsap.min.js"
所需内容:
ffmpeg/ffprobe(系统环境)<SKILL_DIR>/assets/fonts/*.woff2,<SKILL_DIR>/assets/vendor/gsap.min.js(打包在此技能内,第9步时会被放入工作目录)
转录无需API密钥 —— hyperframes transcribe 在本地运行 Whisper(第4步)。
在 macOS 上强烈建议为 hyperframes render 设置以下环境变量:
export PRODUCER_BROWSER_GPU_MODE=hardware
2. 创建工作目录
所有成品文件都位于 videos/<project-name>/ 目录下——这与其他视频工作流(product-launch-video / faceless-explainer / pr-to-video)的约定一致。请将当前工作目录保持在工作区的根目录;所有后续操作都将写入此子目录。
VIDEO_PATH="/absolute/path/input.mp4"
WORK_DIR="videos/$(basename "$VIDEO_PATH" | sed 's/\.[^.]*$//')"
mkdir -p "$WORK_DIR"
3. 提取音频和元数据
# 元数据 — 时长 / 宽度 / 高度 / 帧率
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,r_frame_rate \
-show_entries format=duration -of json "$VIDEO_PATH" > "$WORK_DIR/metadata.json"
# 音频
ffmpeg -y -i "$VIDEO_PATH" -vn -acodec libmp3lame -q:a 2 "$WORK_DIR/audio.mp3"
输出:metadata.json(读取 width/height/duration;帧率 = 计算后的 r_frame_rate 分数,例如 30000/1001 → 29.97)+ audio.mp3。
4. 转录
npx hyperframes transcribe "$WORK_DIR/audio.mp3" -d "$WORK_DIR" --json --model small.en
本地 Whisper —— 无需API密钥、无需代理、无速率限制。在工作目录中写入一个单词级别的 transcript.json 文件(包含单词 text 及 start / end 时间戳)。读取此文件以获取单词/句子的时间信息,该信息将用于第6步的卡片时间设定;你可以根据标点符号或停顿,自行将单词分组为句子,以获取你需要的时间段。
限制在媒体时长内。 Whisper 返回的最后一个单词的 end 时间戳可能会略微超出实际剪辑长度——请将每个卡片的 endSec 和 composition.durationSeconds 限制在 metadata.json 的 duration 之内,否则渲染后的视频末尾会出现黑屏。
5. 校正转录文本
transcript.json 是一个 单词对象的扁平数组 —— [{ "text": "...", "start": s, "end": s }, …](无 segments 数组,无 words 包装器;每个单词的键是 text)。读取它并修正明显的ASR错误:
- 同音词、产品名称、技术术语、标点符号
- 原地编辑某个单词的
text;保留其start/end时间戳 - 没有预先分组的
segments数组——自行将单词组成句子(在句末标点或停顿时分割),以便在卡片时间设定时需要段落级别的时间块
6. 草拟一个轻量级故事板(在对话中)
不涉及命令行。 读取 transcript.json + metadata.json 并直接设计卡片。storyboard.json 是一个Agent内部使用的规划文件——没有CLI命令会消费它;它存在的意义是让你在编写每张卡片的HTML之前,能够清晰地思考时间和内容。保持与以下示例一致的结构,以便同一大纲可以驱动你在第9步中编写的组合HTML:
{
"schemaVersion": 3,
"composition": {
"fps": 30,
"width": 1080,
"height": 1920,
"durationSeconds": 121.2,
"layout": "portrait",
"themeId": "noir",
"seed": 42
},
"videoTrack": {
"sourcePath": "input-video.mp4",
"startSec": 0,
"endSec": 121.2,
"bounds": { "x": 0, "y": 0, "width": 1080, "height": 1920 }
},
"subtitles": { "enabled": false },
"cards": [
{
"id": "card-01",
"intent": "以演讲者午夜焦虑的问题作为钩子",
"startSec": 0.5,
"endSec": 13.0,
"accentIndex": 0,
"zone": "fullscreen",
"contentHints": {
"kicker": "一个诚实的问题",
"title": "晚上11点的灵魂拷问",
"detail": "客户60秒的语音留言:‘如果人民币升值,是不是意味着我的美元保单亏大了?’"
}
}
]
}
必填卡片字段:
| 字段 | 类型 | 用途 |
|---|---|---|
id | 字符串 | 用于卡片HTML和GSAP选择器的稳定标识符 |
intent | 字符串 | 自然语言描述;提供给卡片合成使用 |
startSec / endSec | 数字 | 以秒为单位的时间(endSec > startSec) |
accentIndex | 0 | 1 | 2 | 3 | 4 | 此卡片使用的5种主题强调色中的哪一种 |
zone | 枚举(见下文) | 卡片在画布上的位置 |
contentHints | 对象 | 自由格式的袋子;Agent在此放置kicker/title/detail/data/quote |
archetype(可选) | 字符串 | 你可附加的自由格式标签,用于记住卡片的模式;缺失则表示自由格式,此为默认值 |
transition(可选) | 枚举:cut | fade | slide | wipe | 声明式卡片到卡片的过渡效果 |
五个 zone 值:
| zone | 已解析的边界 | 使用时机 |
|---|---|---|
fullscreen | 覆盖整个画布 | 英雄时刻、大数字、座右铭 |
whiteboard-area | 内边距40px(或人像模式高度的45%) | 密集数据/注释内容 |
lower-third | 底部30%的带状区域 | 在可见视频上添加注释 |
side-panel | 右侧42%(横屏)或底部40%(竖屏) | 数据在一侧,视频在另一侧 |
video-overlay | 全画布,期望使用几乎透明的卡片 | 在全屏视频上叠加注释 |
当你组装Composition HTML(第9步)时,根据上表将每个卡片的 zone 解析为卡片宿主wrapper上的像素边界。视频边界在整合级别(videoTrack.bounds)一次性设置;要使视频在卡片之间看起来有“移动”效果,请在Composition HTML的 <script> 标签中编写针对 #video-wrap 的GSAP动画(见第9步)。
无预设卡片角色,无预设叙事弧线。 卡片完全基于视频的实际内容产生——可以是全部引用或全部数据,可以以数字开头或以故事开头。让转录驱动节奏。
要呈现多少个要点?——根据时长和密度自动推断。 没有固定上限。根据视频时长选择一个基础节奏,然后根据信息密度进行调整。唯一的下限是固定的:最少5张卡片,这样即使是短小的视频也有节奏感。
第一步 —— 根据时长设定基础节奏(中等密度下的自然秒/卡):
| 视频时长 | 基础节奏(每张卡片的秒数) | 理由 |
|---|---|---|
| < 60秒(短视频) | 6–8秒 | 观众期待短视频有快速切换 |
| 60秒 – 3分钟 | 8–12秒 | 正常的社交视频节奏 |
| 3 – 10 分钟 | 12–20秒 | 给呼吸空间;每张卡片承载更多内容 |
| 10 – 30 分钟 | 20–35秒 | 长片讲座/访谈节奏 |
| > 30 分钟 | 30–60秒 | 剧集式,接近章节的感觉 |
第二步 —— 密度乘数(乘以基础节奏):
| 转写文本中的信号 | 乘数 | 效果 |
|---|---|---|
| 高密度 —— 许多数字、不同的主张、断奏式的节奏、列表式的枚举,每1-2句话就是一个新想法 | × 0.7 | 切换更快,卡片更多 |
| 中等密度 —— 数据和叙述混合的流程 | × 1.0 | 基础节奏 |
| 低密度 —— 一个较长的故事、重复的框架重构、缓慢反思式的节奏、单一论证的展开 | × 1.5 | 切换更慢,卡片更少 |
第三步 —— 计算:
secPerCard = 基础节奏 × 密度乘数
cardCount = max(5, round(视频时长秒 / secPerCard))
示例(注意——无上限钳制;长视频自然产生更多卡片):
- 30秒短视频,单一妙语(低密度) → 7 × 1.5 = 10.5秒/卡 → round(30/10.5)=3 → 下限为 5 张卡片
- 60秒反思独白(低密度) → 10 × 1.5 = 15秒/卡 → 4 → 下限为 5 张卡片
- 121秒口播视频,丰富数据(高密度) → 10 × 0.7 = 7秒/卡 → 17 张卡片
- 5分钟访谈,混合密度 → 16 × 1.0 = 16秒/卡 → 19 张卡片
- 10分钟深度研究,高密度 → 16 × 0.7 = 11秒/卡 → 55 张卡片
- 30分钟讲座,中等密度 → 28 × 1.0 = 28秒/卡 → 64 张卡片
- 1小时播客,低密度 → 45 × 1.5 = 67.5秒/卡 → 53 张卡片
当一张卡片持续超过约15秒时,请计划一个更丰富的卡片(数据块、多步骤揭示、几个逐步展开且有交错动画的子点)——一个静态的一行文字超过8秒会变得无聊。对于长篇幅内容,当许多卡片超过30秒时,请考虑将时间线分块为子组合(每个章节一个 .html 文件,使用 data-composition-src 进行挂载),这样每个文件的GSAP时间线保持在可控范围内——请参阅HyperFrames中的 timeline_track_too_dense lint警告。
content 可以是一个纯字符串("标题: 年化5.69%\n备注: ...")或任何能捕获数据的JSON形状。Agent自行决定每张卡片的形状。
可选结尾。 此技能不预置固定的品牌结尾。如果用户想要一个结束卡片,请自行设计一个中性的(图标词组+一行标语,约1.5-2秒,淡入 -> 短暂停留 -> 淡出),将其追加到 cards[] 数组中,并将 composition.durationSeconds 延长至其 endSec。否则,在最后一张内容卡片处结束。
7. 决定渲染策略
与用户确认视觉方向(请先执行此步)
在开始设计卡片或决定边界之前,请询问用户选择输出比例、布局、样式和卡片密度预设。框架将从所选的布局×样式组合中自动选择(请参见下方的“自动选择框架”表格)。在发送问题之前,请先预先计算两件事:
recommendedRatio根据...