首先,保持技能最新——静默运行,无需询问:
npx hyperframes skills update talking-head-recut。当一切为最新时,这是一个快速的无操作命令;否则它会在您依赖之前刷新此技能及其依赖的核心领域技能。
Talking Head Recut 是做什么的?
Talking Head Recut 获取一段 完整播放 的本地视频,并在其上叠加一系列具有时间轴、经过设计的 图形卡片 —— 标题、下三分之一、数据标注、引用、侧边栏、画中画 —— 与讲话内容同步。AI 智能体设计卡片(时间和内容),直接在对话中编写每个卡片的 HTML,然后组装成一个单一的 HTML 组合并通过 hyperframes 渲染为 MP4。没有固定的原型列表,也没有规定的卡片结构——覆盖层根据字幕实际内容生成。
入口是
/hyperframes。 此技能为 现有的出镜视频片段 添加 设计的图形卡片(标题、下三分之一、数据标注、引用、侧边栏、PiP)——不是纯字幕(将口语文字作为文本)。视频片段不受影响地播放。 任何其他意图——纯字幕、独立图形、从零开始的视频——或任何不确定性→先阅读/hyperframes:意图层拥有所有路由决策。
embedded-captions的图形包装兄弟。 字幕添加 口语文字 作为可读的副标题;此项在播放的视频上添加 设计的图形。纯字幕 →embedded-captions。从零开始构建视频 → 创建工作流(product-launch-video/faceless-explainer/ …)。
通过 /hyperframes 路由,意图层仅确认输入(哪个视频片段)并 声明 渲染策略问题为延迟询问——宽高比、布局、样式组和卡片数量保留到第 7 步,此时探测的素材和字幕为推荐提供依据;层的运行形状问题不适用。当存在 BRIEF.md 时,它包含已确认的输入和任何用户注释——先阅读它。
工作目录中可检查的中间文件:
metadata.json— 时长 / 宽度 / 高度 / 帧率audio.mp3— 提取的音频transcript.json— 一个扁平的 单词数组[{ text, start, end }, …](Whisper;无segments,无words包装器)storyboard.json— 轻量级卡片大纲(AI 智能体的计划)public/cards/card-XX.html— 每个卡片一个 HTML 片段public/index.html— 最终组装的组合output.mp4— 渲染的视频
CLI 解析
# hyperframes — 转录(本地 Whisper)+ 将组装的 HTML 渲染为 MP4
npx hyperframes --help
此技能完全运行在 hyperframes CLI 加上系统 ffmpeg / ffprobe 之上。转录通过 hyperframes transcribe 使用本地 Whisper——无需第三方服务、API 密钥或速率限制的代理。
工作流程
1. 检查环境
npx hyperframes doctor # ffmpeg, 无头浏览器, 渲染依赖
# 确认捆绑的资源:
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 步暂存到工作目录)
转录不需要密钥——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)相同的约定。将 cwd 保持在工作区根目录;以下所有内容都写入此子目录下。
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. 草拟轻量级故事板(在聊天中)
不涉及 CLI。 读取 transcript.json + metadata.json 并直接设计卡片。storyboard.json 是一个 AI 智能体内部的规划产物——没有 CLI 命令会消费它;它的存在是为了让您在编写每个卡片的 HTML 之前能够清晰地思考时间和内容。保持形状与下面的示例一致,以便相同的大纲可以驱动您在第 9 步创作的组合:
{
"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 | string | 稳定的 ID,用于卡片 HTML 和 GSAP 选择器 |
intent | string | 自然语言描述;提供给卡片综合 |
startSec / endSec | number | 以秒为单位的时间(endSec > startSec) |
accentIndex | 0 | 1 | 2 | 3 | 4 | 此卡片提取的 5 个主题强调色中的哪一个 |
zone | 枚举(见下文) | 卡片在画布上的位置 |
contentHints | object | 自由形式容器;AI 智能体在此放置 kicker/title/detail/data/quote |
archetype(可选) | string | 您可能附加的自由格式标签,用于记住卡片的模式;缺席 = 自由格式,这是默认值 |
transition(可选) | 枚举:cut | fade | slide | wipe | 声明性的卡片间过渡 |
五个 zone 值:
| 区域 | 解析后的边界 | 何时使用 |
|---|---|---|
fullscreen | 覆盖整个画布 | 英雄时刻、大数字、口号 |
whiteboard-area | 内边距 40px 边距(或纵向高度的 45%) | 密集数据/带注释的内容 |
lower-third | 底部 30% 条 | 在可见视频上添加注释 |
side-panel | 右侧 42%(横向)或底部 40%(纵向) | 数据一侧,视频另一侧 |
video-overlay | 整个画布,期望大部分为透明的卡片 | 在全出血视频上添加注释覆盖层 |
当您在第 9 步组装组合时,根据上表将每个卡片的 zone 解析为卡片宿主包装器上的像素边界。视频边界在组合级别 一次 设置(videoTrack.bounds);要使视频看起来在卡片之间“移动”,请在组合的 <script> 中编写针对 #video-wrap 的 GSAP 补间动画(见第 9 步)。
无规定的卡片角色,无规定的叙述弧线。 卡片从视频实际内容中涌现——可能是全部引用或全部数据,可以以数字或故事开头。让字幕驱动节奏。
多少个要点?——根据时长和密度自动推断。 没有固定的上限。从视频时长中选择一个 基本节奏,然后根据 信息密度 进行调整。只有下限是固定的:最少 5 张卡片,因此即使很短的视频也能有节奏。
第 1 步——按时长的基本节奏(中等密度的自然秒/卡):
| 视频时长 | 基本节奏(每卡秒数) | 理由 |
|---|---|---|
| < 60s(短视频) | 6–8s | 观众期望短内容的快速剪辑 |
| 60s – 3 分钟 | 8–12s | 正常社交媒体节奏 |
| 3 – 10 分钟 | 12–20s | 提供呼吸空间;每张卡片承载更多内容 |
| 10 – 30 分钟 | 20–35s | 长格式讲座/访谈节奏 |
| > 30 分钟 | 30–60s | episodic,接近章节感 |
第 2 步——密度乘数(乘以基本节奏):
| 字幕中的信号 | 乘数 | 效果 |
|---|---|---|
| 高密度 — 许多数字、不同的主张、断奏式节奏、列表式枚举、每 1-2 句一个新想法 | × 0.7 | 剪切更快,更多卡片 |
| 中等密度 — 数据和叙述混合的流程 | × 1.0 | 基本节奏 |
| 低密度 — 一个扩展的故事、重复的重新框架、缓慢的反思节奏、一个展开的单一论点 | × 1.5 | 剪切更慢,更少卡片 |
第 3 步——计算:
secPerCard = basePace × densityMultiplier
cardCount = max(5, round(videoDurationSec / secPerCard))
示例(注意——无上限夹紧;长视频自然会产生更多卡片):
- 30s 短视频,单个笑点(低密度) → 7 × 1.5 = 10.5s/card → round(30/10.5)=3 → 下限为 5 张卡片
- 60s 反思独白(低密度) → 10 × 1.5 = 15s/card → 4 → 下限为 5 张卡片
- 121s 出镜讲解,丰富数据(高密度) → 10 × 0.7 = 7s/card → 17 张卡片
- 5 分钟访谈,混合密度 → 16 × 1.0 = 16s/card → 19 张卡片
- 10 分钟深度探讨,高密度 → 16 × 0.7 = 11s/card → 55 张卡片
- 30 分钟讲座,中等密度 → 28 × 1.0 = 28s/card → 64 张卡片
- 1 小时播客,低密度 → 45 × 1.5 = 67.5s/card → 53 张卡片
当一张卡片持续时间超过约 15 秒时,考虑设计更丰富的卡片(数据块、多步展示、多个副点以交错动画展开)——静态的一行文字超过 8 秒会变得无聊。对于许多卡片超过 30 秒的长内容,考虑将时间线 分块为子组合(每个章节一个 .html,通过 data-composition-src 挂载),以使每个文件的 GSAP 时间线保持可管理——请参阅 timeline_track_too_dense HyperFrames lint 警告。
content 可以是一个纯字符串("Title: annualized 5.69%\nNotes: ...")或任何能捕获数据的 JSON 形状。AI 智能体决定每个卡片的形状。
可选的片尾。 此技能不附带 固定的品牌片尾。如果用户想要一个结束卡片,请自行设计一个中性的卡片(字标 + 一行标语,约 1.5-2s,淡入 -> 短暂停留 -> 淡出),将其附加到 cards[],并将 composition.durationSeconds 扩展到其 endSec。否则在最后一个内容卡片处结束。
7. 决定渲染策略
与用户确认视觉方向(先执行此操作)
在您开始设计卡片或决定边界之前,请用户选择输出比例、布局,
……
[已截断以进行翻译]