mcpField
S
short-form-video

short-form-video

github.com/nateherkai创意与媒体2.4k66 次安装2 周前更新
代码仓库

关于 short-form-video

这项技能用于维护旧版 10–30 秒竖屏 HyperFrames 视频,涵盖音频同步、场景构建、字幕和验证。适用于维护文档中的 May Shorts 示例,而非制作新录音。

主要功能

  1. 01按剪辑后时间同步音频
  2. 02四层合成结构
  3. 03场景与人物画面模式编排
  4. 04逐词同步卡拉 OK 字幕
  5. 05渲染与逐帧验证

适用场景

  1. 01维护 May Shorts 示例
  2. 02音频剪辑后调整场景时间
  3. 03核对字幕与画面时序

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nateherkai/hyperframes-student-kit --skill short-form-video

安装后在 Claude Code 中输入/short-form-video确认已加载。

详细介绍

短视频竖屏(Hyperframes)

短视频竖屏的规格为 1080x1920、时长 10–30s,包含真人讲述、动态视觉场景叠层和卡拉 OK 字幕。本技能的所有内容均提炼自 May Shorts 的第 19 次迭代复盘(v1 → v4),用于维护这些示例。新录制内容请使用 short-form-edit。

始终先调用 /hyperframes。 本技能建立在其基础之上,并不取代框架规则(data-* 属性、window.__timelines、合成结构)。无论格式如何,这些规则都不可更改。

适用场景

  • 维护现有的 May Shorts 示例。
  • 明确要求使用其旧版四层框架。

操作手册(概览)

  1. 音频是事实依据。 先编辑音频(剪掉重录片段和停顿)。保存为 <name>-edit.mp4。使用 ffprobe 测量精确时长,即合成的 data-duration。
  2. 使用根目录中的 scripts/transcribe-elevenlabs.mjs 辅助脚本(ElevenLabs Scribe)转录编辑后的音频;也可使用学生选定且根据 docs/TOOLS-AND-API-KEYS.md 进行标准化的替代方案;或者,在通过字幕中的 shift() 函数调整现有构建的时间时,保留现有字幕,只移动场景的起始时间。
  3. 根据编辑后的时间确定场景边界——绝不要在同一文件中混用原始时间和编辑后时间锚点。请参阅下文的“音频同步流程”。
  4. 构建合成框架(4 层:ambient-bg、seam-treatment、captions、face)——请参阅下文的“合成框架”。
  5. 使用相对于各场景 data-start 的局部偏移量编写场景。 每个场景都是一个独立的子合成,位于 compositions/scene<N>-<label>.html。
  6. Lint → 草稿渲染 → 逐字帧验证 → 最终渲染。 这是验证关卡。绝不要跳过第 3 步(帧验证)。

合成框架(始终启用的 4 层)

每个短视频竖屏都包含以下 4 个位于 compositions/ 下的子合成,并加载到共享轨道:

index.html (root, 1080x1920, data-composition-id="main")
├── ambient-bg.html        track-index="3" — radial gradient + drift grid + particles + vignette
├── face-wrapper + <video> track-index="0" — talking head (see face-mode choreography)
├── seam-treatment.html    track-index="5" — feathers y=960 edge (bottom-half scenes only)
├── scene1-<label>.html    track-index="1" — scene overlays (back-to-back, no gaps)
├── scene2-<label>.html    track-index="1"
├── …
└── captions.html          track-index="2" — karaoke captions, word-synced
  • data-duration 在 root、ambient-bg、seam-treatment、face-video、face-audio 和 captions 中完全相同。只有场景叠层会随时间变化。
  • 真人视频的 <audio> 必须是独立元素(混音器需要),绝不要使用视频自身的音轨。
  • class="clip" 应添加到带定时的 div 上——绝不要添加到 <video> 或 <audio> 上。

人脸模式编排(短视频竖屏的标志性手法)

人脸位于一个尺寸与源视频原生横屏尺寸相同(1920x1080)的包装 div 中。GSAP 对包装元素进行动画处理(绝不要对视频元素进行动画处理——改变 <video> 尺寸会导致画面冻结)。

两种模式:

const BOTTOM     = { x: 0,       y: 1136, scale: 0.5625 }; // bottom-half, full landscape visible
const FULLSCREEN = { x: -1166.5, y: 0,    scale: 1.7778 }; // cropped-cover, fills 1080x1920
const MODE_DUR = 0.32;

BOTTOM 会将 1920x1080 的源视频以 1080x607.5 的尺寸渲染,并居中放在底部 960px 区域内。FULLSCREEN 会水平裁切以填满竖屏画面。

在新场景内容出现前 0.15s 完成转场,使用 ease: "expo.inOut":

[
  { t: <scene-4-start>, mode: FULLSCREEN },
  { t: <scene-5-start>, mode: BOTTOM },
  …
].forEach(({ t, mode }) => {
  mainTl.to("#face-wrapper", { ...mode, duration: MODE_DUR, ease: "expo.inOut" }, t - 0.15);
});

人脸模式瞬间切换,是竖屏视频中最突兀的单帧效果。务必使用插值。

人脸调色(每条短视频都必须做,无一例外)
#face-video {
  filter: contrast(1.08) saturate(1.08) brightness(0.97);
}

此外,还要在完整时长内进行细微的 1.00 → 1.025 Ken Burns 缩放(ease: "none"),并添加侧边暗角 ::after 伪元素,让人脸自然融入周围的藏青色背景,而不是与锐利的边缘生硬相接。

接缝处理(底部半屏场景必需)

在 y=960 处添加一条从藏青色渐变至透明的渐变带(60–100px),以及一条带柔和辉光的 2px 强调色扫描线。应在人脸之后绘制,使其位于人脸上方;全屏场景接管画面时会遮住它。y=960 处锐利的切线是 AI 编辑内容最明显的特征之一(仅次于背景平坦)。

音频同步协议(请勿跳过)

**问题:**如果音频经过编辑(重录/删去停顿),源转录稿中的时间戳就会与编辑后的视频不匹配。按原始时间编写的场景起始时间会延迟触发。

**规则:**所有时间都必须使用编辑后时间。绝不可混用。

任何短视频重新定时的验证流程:

  1. 测量两个音频文件:
    ffprobe -v error -show_entries format=duration -of csv=p=0 assets/original.mp4
    ffprobe -v error -show_entries format=duration -of csv=p=0 assets/<name>-edit.mp4
    
    差值 = 剪掉的总时长。
  2. 如果使用 captions.html 中的 shift() 函数来映射转录稿中的词语,则以该函数为准。映射 shift(originalTime) = editedTime 也适用于每个场景的 data-start。
  3. 场景内部偏移(位于 compositions/sceneN.html 中)相对于场景的 data-start,属于本地时间。如果场景父级的 data-start 使用了正确的编辑后时间,内部偏移无需修改即可保持正确——除非场景跨越了剪辑点;这种情况下,父级时长和内部偏移都要调整。
  4. 人脸模式转换数组中的时间必须使用编辑后时间。它们不会自动调整。

重新定时的计划格式(每次都使用此表格结构):

场景当前起始时间当前时长新起始时间新时长原因
..................

然后列出人脸模式数组,再列出任何内部偏移更改,最后列出帧验证清单。

场景编写

一个场景对应一个子合成文件。场景在同一个 data-track-index 上首尾相接(无间隔)。每个场景内部:

  • data-duration 与父级的时间段完全一致
  • 所有 GSAP 锚点都是本地时间(从场景起始处的 0 开始)
  • 使用 tl.set({}, {}, <data-duration>) 补齐时间轴,使 GSAP 的 tl.duration() 与 data-duration 一致
场景节奏规则(基于 10 项原则)
  • 不能有静止帧。 每 100 ms 至少有 1 个元素在动。第一个元素的入场偏移 0.1–0.3 秒,不要从 t=0 开始。
  • 高潮效果至少停留 1 秒。 场景的「重大揭晓」(印章、数字锁定、笑点)必须在屏幕上至少停留 1 秒,理想情况下为 1.5 秒。应根据揭晓效果的停留时间规划场景,而不是根据总时长。
  • 整个场景时长内都要有动效。 如果入场动画在 4 秒场景的本地时间 2 秒前全部结束,就加入次要动效:下划线扫过、勾号弹出、卡片缓慢漂移、胶囊形元素上的微弱脉动光晕。节奏停滞会让观众划走。
  • 变换缓动方式。 每个场景的入场动画至少使用 3 种不同的缓动方式。
  • 每 5 秒播放时长至少有 1 个令人惊艳的效果。 字体猛击、故障/色差揭晓、快速摇摄、音频同步猛击。缺少这些效果时,视频看起来就像「带标签的对镜头讲话」——虽然正确,却令人难忘不了。

字幕(卡拉 OK 风格)

  • Montserrat 900,46–58px(适用于 1080 宽度),底色为 100% 白色
  • 当前词语:放大至 1.08 倍并弹出 + 更改为强调色(AIS 使用 #37bdf8,也可根据品牌调整)
  • 通过多层 text-shadow 添加描边,绝不要使用 -webkit-text-stroke(在 Chromium 渲染中显示不一致)
  • 去掉 rgba 背景胶囊条——依靠描边保持可读性。字幕应像画面上的涂鸦,而不是字幕轨道。
  • 重新定时时,在 captions.html 中使用 shift() 函数,将转录稿词语时间戳映射到编辑后时间。这样无需改动转录稿 JSON,重新定时也能按机械流程完成。

完整的卡拉 OK 实现请参阅 /hyperframes 下的 references/captions.md。简而言之:每个词使用一个 <span> 元素,通过 data-word-start 指定时间戳,GSAP 补间动画作用域限定在各个 span 内,弹出动画时长控制在 0.08–0.12 秒。

环境背景(绝不交付纯色藏青背景)

最低可行的背景层:

  1. 径向渐变底色(中心比边缘亮 15–20%)
  2. 动画噪点/颗粒叠加层,不透明度为 8–12%
  3. 4–8 个漂移的粒子点或网格轨迹
  4. 微妙的暗角

background: #07121c 本身只是占位符,不是设计。若要营造科技感/控制室美学,请使用 feedback_techy_background_layers.md 中的 6 层结构(通过暗角遮罩的 HUD 网格 + 电路轨迹 + 脉冲节点 + 扫描光束 + 遥测滚动条 + 角落的等宽字体标签)。

音频响应

  • 标题随节拍脉动 3–6%。背景可随低音脉动 10–30%。
  • 文字响应幅度保持轻微(3–6%),以确保字幕清晰易读;背景可以更强烈。
  • 使用带种子的离线分析器(预先计算音频特征轨迹),确保渲染结果具有确定性。渲染流程中不要使用 AnalyserNode——Math.random() 和实时音频节点会破坏确定性。

转场

  • 轮换转场类型。 不要连续两次使用相同类型的转场。一连六次硬切是 AI 剪辑最明显的破绽。
  • 面部模式转场(BOTTOM ↔ FULLSCREEN)在场景间切换模式时,也可作为场景转场。
  • 对于纯叠加层的场景间转场,从注册表安装:push-up、flash-through-white、sdf-iris,或完整的 shader-transitions 包。运行 npx hyperframes catalog --type block 浏览。

验证关卡(强制要求——未通过前不得交付)

Lint 通过 ≠ 设计有效。只有在精确到词语时间戳提取帧并逐张读取所有 PNG 后,才能报告短视频渲染完成。

步骤 1——草稿渲染
cd video-projects/<slug>
npx hyperframes lint
npx hyperframes render --quality draft --output renders/<slug>-vN-draft.mp4
步骤 2——精确到词语的帧提取

选择 8–15 个时间戳,每个时间戳都对应一个口播词,且该时刻应显示特定视觉内容。不要选整数时间,也不要选场景中间的时间。要精确对应到词语。

mkdir -p renders/frames-vN
for pair in "<t>:<label>" "<t>:<label>" ...; do
  t="${pair%%:*}"; label="${pair##*:}"
  ffmpeg -y -ss "$t" -i renders/<slug>-vN-draft.mp4 \
    -frames:v 1 -q:v 2 "renders/frames-vN/t${t}-${label}.png"
done
步骤 3——读取每张 PNG

对每张 PNG 调用 Read,将图像加载到上下文中。不要只列出文件名。逐帧确认:

  • 预期视觉内容在预期时刻出现(不能晚 1 秒,也不能提前)
  • 所有下半屏场景中,发言者的脸都没有被裁切
  • 该场景的全屏或下半屏面部模式正确
  • 字幕符合品牌风格、清晰易读且没有溢出
  • 没有空白帧、意外重叠或画布外文字
步骤 4——若有任何问题,修复并重新验证。切勿交付有问题的成品。
步骤 5——最终渲染
npx hyperframes render --quality standard --output renders/<slug>-vN.mp4

从最终渲染中抽查 3–4 帧(使用相同时间戳,存放在不同的 frames-vN-final/ 文件夹中),确认标准质量编码没有改变任何内容。

10 条规则(质量检查清单——首次草稿前执行)

每个短视频项目都必须遵循。创作时就执行清单,不要等到完成后再检查。

  1. 不要出现静止帧。 每 100ms 都必须有元素在动。
  2. 场景重点内容至少停留 1 秒。 根据揭示时间安排时长,而不是根据总时长。
  3. 面部是角色的一部分。 调色 + Ken Burns 效果 + 侧边暗角。
  4. 不要出现明显接缝。 在 y=960 处使用渐变 + 扫描线进行羽化。
  5. 每 5 秒安排一个震撼瞬间。 字体重击、故障效果、快速摇镜、音频重击。
  6. 音频响应不可妥协。 文字响应 3–6%,背景响应 10–30%。
  7. 轮换转场类型。 不要连续两次使用相同类型。
  8. 字幕要醒目,不要只是礼貌地标注。 使用描边,不要使用药丸形底色。当前词要缩放并变色。
  9. 运动贯穿整个场景时长。 若入场动画结束得太早,就添加次级运动。
  10. 背景应该是一个图层,而不是一种颜色。 至少包含径向效果 + 噪点 + 粒子 + 暗角。
  11. 重击/印章叠加层应在目标文字完全显示后出现。 揭示逻辑优先于词语同步。印章的 t ≥ 目标内容完全显示的 t + 0.10–0.25s。否则笑点会在铺垫之前出现。

项目结构(每个短视频项目)

video-projects/<slug>/
├── hyperframes.json
├── meta.json                    (id, name, dimensions 1080x1920, fps 30)
├── index.html                   (root composition, the 4-layer scaffold)
├── compositions/
│   ├── ambient-bg.html
│   ├── seam-treatment.html
│   ├── captions.html            (with shift() function if retiming)
│   ├── scene1-<label>.html
│   ├── scene2-<label>.html
│   └── ...
├── assets/
│   ├── <name>.mp4               (original recording)
│   ├── <name>-edit.mp4          (edited — cuts removed — this is what the comp uses)
│   ├── transcript.json          (whisper output)
│   └── brand assets (logo, brand-tokens.css, background music)
└── renders/
    ├── <slug>-v1-draft.mp4
    ├── frames-v1/
    ├── <slug>-v1.mp4
    └── ...

重新定时流程(音频重新剪辑或时间戳发生偏移时)

  1. 使用 ffprobe 测量编辑前后音频的时长。差值 = 总剪切时长。
  2. 确定剪切区间:删除了哪些秒数,以及从哪里删除。
  3. 编写计划表:列出每个场景的 data-start、data-duration,每个面部模式转场的 t,以及内部偏移跨越剪切点的场景。
  4. 对于跨越剪切点的场景,其父级时长和内部偏移都要更改。完全位于剪切点某一侧的场景只需调整父级 data-start。
  5. 执行 Lint → 草稿渲染 → 精确到词语的帧验证 → 最终渲染。不得走捷径。

短视频中不该做的事

  • 不要对 <video> 元素的尺寸做动画——会导致画面冻结。应对包装 div 做动画。
  • 不要在任何时间轴上使用 repeat: -1——这会破坏捕获引擎。只能使用有限次数。
  • 不要使用 Math.random() 或 Date.now()——会破坏确定性。如果需要伪随机数,请使用带种子的 PRNG。
  • 不要在字幕中使用 <br>——自然换行再加上 <br> 会产生多余的换行。
  • 不要跳过帧验证关卡。Lint 的退出代码不能代表视觉效果是否正确。
  • 如果音频经过剪辑,就不要按原始时间编写。必须使用剪辑后的时间,否则就别做。
  • 不要让 background: #07121c 保持单调。要叠加图层。
  • 不要在场景之间硬切。轮换使用不同的转场风格。
  • 不要给字幕加得太客气。要让它们跳出来。
  • 不要让人脸画面静止不动。始终进行调色和 Ken Burns 效果。

从 may-shorts-18 中吸取的经验(v1 → v2)

这些经验总结自 v1 渲染中的 4 个具体问题,以及 v2 中的修复方法。每次制作新短视频时都要应用。

1. 重击/印章效果的时机——揭示顺序比逐词同步更重要

SLAM/STAMP 覆盖效果(KILLED、DEAD、STOP 等)应在目标文本完全可见后出现,而不是在口播对应词语时出现。在 may-shorts-18 v1 的场景 1 中,CLAUDE 和 CHATGPT 被设定为对手——KILLED 在本地时间 0.46s 时出现,而 CHATGPT 直到 0.66s 才出现,因此观众看到的是“Claude … KILLED”,目标却尚未显示出来。笑点就此垮掉。

规则: stamp_t ≥ target-text-visible_t + 0.10–0.25s。所谓“可见”的时间戳,是目标文本的入场动画结束时间,而不是开始时间。逐词同步只是参考;视觉揭示顺序才是约束。

2. BOTTOM 人脸模式的缩放——不要直接使用默认值

默认值 BOTTOM = { x: 0, y: 1136, scale: 0.5625 }(对 1920×1080 源视频来说恰好能水平铺满)会让讲者两侧露出空荡的演播室背景,前提是讲者在源视频画面中占比不到 70%。may-shorts-19 默认使用了这个值,may-shorts-18 v1 也照搬了它——两支视频的每个 BOTTOM 场景中,讲者左右两侧都有明显的空白区域。

规则: 优先使用 BOTTOM = { x: -180, y: 1110, scale: 0.75 }——左右各裁掉 180px,底部锚定到 y=1920。在确定这个常量之前,先针对实际源视频预览一帧 BOTTOM 模式。如果源视频中的讲者本来就被紧凑取景,缩放到 0.65 可能就够了;如果源视频是宽幅演播室取景,就将缩放提高到 0.80,并重新调整 x。

始终让 HIDDEN 的 x、y、scale 与 BOTTOM 完全相同——它们只应在 opacity 上有所不同,这样淡入淡出场景才不会在过程中发生几何偏移。

3. 人脸模式转场——同时做好三件事,而不是只做一件

相邻场景之间切换人脸模式时,如果只对人脸包装层进行默认的 0.15s 预滚动和 0.32s 时长的 expo.inOut 动画,效果会显得僵硬——变形的人脸后面,上一场景的面板仍完全不透明,因此观众会看到两个元素互相争抢,而不是交叉淡化。

规则: 对任何“主视觉”场景之间的人脸模式切换(尤其是 BOTTOM ↔ FULLSCREEN),都要同时做到以下三点:

  1. 将该转场的时长延长至 0.45–0.55s(而非默认的 0.32s)
  2. 在新场景的 data-start 前 0.25–0.30s 开始(而非默认的 0.15s)
  3. 在场景结束前 0.25s 开始,对上一场景的面板包装层进行淡出和模糊处理,在 0.20–0.25s 内过渡到 opacity: 0, filter: blur(6px)

在实现上,将人脸模式转场数组改为按条目设置 dur,这样其中一个转场就可以比其他转场更长:

[ { t: 2.06, mode: FULLSCREEN, dur: 0.50 }, { t: 3.71, mode: HIDDEN, dur: 0.32 }, ... ]
  .forEach(({ t, mode, dur }) => mainTl.to("#face-wrapper", { ...mode, duration: dur, ease: "expo.inOut" }, t));

三项同时调整 = “真正的剪辑师剪辑过”。单独调整任何一项 = 僵硬。

4. 视频中段的数据感场景胜过装饰性场景

对于 15–20 秒短视频的第 3–5 个场景(也就是观众注意力最容易流失的“中段苦熬期”),优先使用看起来像信息的视觉元素——条形图竞速、数字递增的统计网格、热力图、迷你趋势线、流程图、数据不断跳动的仪表盘界面,以及依次闪红的痛点网格。may-shorts-18 v1 的场景 4 将雷达环、终端芯片和火花组合在一起——功能齐全,却偏向装饰性,Nate 称它“乏味”。v2 将它替换为一个依次亮起红橙色的 3×3 痛点网格、一条逐步绘制的迷你趋势线(带有 YOU-ARE-HERE 标记),再加上有力的收尾——时长不变,参与度却高得多。

**规则:**纯文字加图标的场景看起来像幻灯片。数据感场景看起来像证据。当中段场景显得乏味时,就用看起来像信息的元素替换装饰:逐渐增大的小数字、逐渐填满的条形、逐步绘制的图表,或依次闪烁的网格。

参考构图

  • video-projects/may-shorts-19/ — 短视频的标准示例(18.84 秒,1080x1920,7 个场景、人脸模式调度、使用 shift() 的卡拉 OK 字幕、环境背景加接缝处理)。制作新短视频前,请阅读 index.html 和所有 compositions/scene*.html。
  • video-projects/may-shorts-18/ — 次要参考示例,融入了上述 4 条经验:BOTTOM scale=0.75、KILLED 印章在 CHATGPT 揭示后出现、场景 1→2 流畅淡入淡出、场景 4 数据仪表盘式的 “THE PATTERN” 网格。

相关技能(同时调用)

  • /hyperframes — 框架规则(始终最先调用)
  • /hyperframes-cli — CLI 命令(init、lint、preview、render)
  • /gsap — 动画库参考
  • /hyperframes-registry — 安装转场模块
  • /seedance-loop-prompt — 如果短视频需要 AI 生成的循环背景视频

记忆参考(相关反馈条目)

  • feedback_short_form_principles.md — 10 条规则及完整理由
  • feedback_contrast_technique.md — 光效局部化、text-shadow 光晕,以及提亮较暗文字
  • feedback_techy_background_layers.md — 6 层控制室背景堆叠
  • feedback_visual_verification.md — 验证关卡
  • project_ais_brand_specs.md — 如果短视频采用 AIS 品牌风格(十六进制色值、字体、Logo 光效)

评论

支持 Markdown