Communitygithub.com

动态排版

以正确方式让文字动起来——标题卡、动态字幕、下三分之一、标注和逐词揭示——通过阅读时间预算确保文字停留足够长的时间,并控制入场/出场时间、粗细和大小过渡,以及运动中字体层级。适用于用户提出相关需求时。

动态排版 是什么?

本技能专注于动态排版的制作核心:可读性。它提供了一个完整的工作流程,基于阅读时间预算(约3.5词/秒)、入场/出场帧数(入场8-15帧,出场≤入场)和单属性动画(如淡入、带位移的淡入、逐词揭示等)来精确控制每行文字的停留时长、入场和离场方式。指标如0.8秒的最短停留时间和0.3秒的术语税,确保了即使是单字或包含数字/专业名词的文本也能得到足够清晰的阅读时间。该技能设计用于与remotion-compose协作,通过type_budget.js脚本计算出精确的帧编号(enter@ / holdStart@ / holdEnd@ / exitOut@),直接转化为Remotion的<Sequence>边界,从而避免了猜测文字应停留多久的问题。支持平台包括基于React/TypeScript的Remotion环境。

兼容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SkillMedev/tutorial-video-studio/tree/main/skills/kinetic-typography

在你喜欢的 AI 中提问

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

文档

动态排版 是做什么的?

文字在运动中的首要任务只有一个:它必须可读。动画排版最常见的失败不是难看,而是文字在观众读完第一个词之前一闪而过,或是文字动得太多,让眼睛追着运动而非阅读内容。这是工艺层面。它决定了每行文字的停留时长、入场和离场方式,以及哪些属性可以动——并将具体的帧数预算交给 remotion-compose,后者编写实际渲染的 React/TypeScript。

核心规则:动画服务于阅读,而非装饰。 只有当运动能引导视线、建立层级或标记节拍时,它才有存在的意义。以下所有内容都遵循这一原则。

全程以一个运行的示例为例:一个16:9的产品标题卡,显示 "Ship video in one prompt"(5个词),30fps,以及一个动画化的下三分之一字幕轨道位于其下方。

工作流程

按顺序执行。在确定停留预算之前,不要选择入场动画——预算是决定你是否还有空间做动画的依据。

第1步 - 首先计算每词阅读时间预算

文字必须在屏幕上停留足够长的时间,以便以轻松的速度阅读,再加上其入场和出场所需的时间。在触碰任何动画之前,先预算停留时间。

  • 屏幕视频的基准阅读速度比印刷品慢:假设舒适阅读速度约为 ~3.5 词/秒(≈ 200 wpm)。字幕惯例类似——单次可读停留时间绝不低于 ~0.3s 每词。
  • 最小屏幕停留时间 = 词数 ÷ 3.5 秒,每行最低为 0.8s(即使是一个词也需要一个节拍来识别),并且对于眼睛无法预测的陌生术语、数字或名称,额外增加 +0.3s 术语税。
  • 入场和出场时间额外计算——不计入阅读时间,因为在过渡过程中文字并非完全可读。总时间 = 入场 + 停留 + 出场。

运行 type_budget.js(见下文),将一行文字转化为帧数预算。对于标题卡,它返回大约 43 帧的停留时间;这个数字就是你交给 remotion-compose 作为 Sequence 可读窗口的值,入场和出场时间在此基础上叠加。

第2步 - 选择与剪辑匹配的入场/出场时间,而非默认值

入场和出场是标点符号,而非句子。保持简短,让停留时间发挥作用。

  • 入场:8-15帧(0.25-0.5s)@ 30fps。 足够快,感觉干脆;足够慢,显得有意识。标题卡可以用较长的时长;快速字幕轨道则用较短的。
  • 出场:等于或短于入场。 出场不应拖沓——一旦读完,文字应立即清除。6-12帧。
  • 匹配出场与后续内容。 硬切到下一场景 → 在剪辑点同时退出文字(无淡出,让剪辑本身完成)。交叉溶解 → 在溶解过程中淡出文字。绝不要为硬切设计复杂的出场;这会与剪辑冲突。这是 motion-design-principles(剪辑和缓动)与本技能的交汇点——从那里获取缓动曲线,在此处应用于文字。
  • 交错多元素揭示,不要同时动画化。标题 + 副标题的最佳阅读效果是副标题在标题稳定后 4-8 帧再入场,从而使视线自上而下引导。

第3步 - 每行选择一种入场技术,并只动画化一个属性

同时动画化的属性越多,文字在过渡过程中就越难阅读。默认只动画化一个属性;只有在有明确意图时才组合两个属性(例如,透明度 + 一个小位移)。

  • 淡入(透明度 0→1) - 最安全,始终可读,是字幕轨道和主体文字的正确默认选择。
  • 升起/滑动(小位移,20-60px,与淡入配对) - 增加方向和活力;是标题卡的常用手法。保持距离小——大滑动会让眼睛追踪移动而非阅读。
  • 逐词揭示 - 每个词依次通过自己的短交错淡入/升起。用于强调行和歌词式片段,不用于密集字幕(阅读会变得断断续续)。整行揭示应在停留时间内完成。
  • 缩放/弹出(spring 从 0.85→1) - 有活力,适合单个主打词或数字标注。绝不要缩放整个句子;重排会难以阅读。
  • 遮罩/擦除揭示 - 高级、有方向性,适合单个标题。制作成本较高;保留给最重要的标题。

无论选择何种方式,动画化的是属性;文字本身在动画过程中不会重排。 动画化 opacity 和 transform(translate/scale/clip)——绝不使用 font-size、width 或会重新布局字形的方式修改 letter-spacing,因为布局驱动的动画会产生抖动且难以阅读。

第4步 - 将粗细和大小作为过渡来动画化,而非噪声

粗细和大小是文字在运动中表达强调的方式——但它们是停留状态之间的过渡,而非连续的抖动。

  • 粗细过渡: 一个词可以从较轻的粗细过渡到较重的粗细以体现强调(例如,在 8 帧内从 400→700 并稳定下来)。使用真正的可变字体粗细轴或字体的两个重量级别;绝不要通过缩放来伪造粗体。
  • 大小过渡: 数字或关键词可以一次放大以占据层级,然后保持。放大并保持,而非放大并脉冲。文字上的循环脉冲看起来像是渲染错误,而非强调。
  • 这些都是强调。每行最多一个粗细/大小强调,放在最重要的那个词上。如果所有内容都强调,那么就毫无强调。

第5步 - 设置运动中字体层级(顺序、大小、粗细、时间)

运动中的层级由四个信号组成;将它们一起使用,使眼睛知道看哪里以及按什么顺序看。

  1. 入场顺序 - 第一个动画化的内容最先被阅读。以标题开头,接着是副标题,最后是行动号召(CTA)。
  2. 大小对比 - 保持清晰的比例(标题 ≥ 1.6× 副标题)。运动无法挽救弱的静态层级。
  3. 粗细对比 - 越粗 = 越重要。屏幕上最多同时出现两个重量级别。
  4. 时间 - 最重要的行获得最长的停留时间,并且如果有的话,入场也最引人注目。最不重要的(如持续存在的 lower-third、水印)在单次入场后不再动画化。

将每行的预算、技术和层级角色填入 motion-type-spec 模板(见下文)。填写完成的规格就是交给 remotion-compose 的交接内容。

第6步 - 决定哪里不进行动画化

高级的做法是节制。在定稿前,从以下“不”列表中删除所有动画。一个具有良好预算的上升效果的标题卡,比每个词都做点什么的效果更好。

质量标准

完成的动态排版规格只有在满足以下所有条件时才达到 A+ 等级:

  • 每行都通过阅读时间预算 - 停留时间 ≥ max(0.8s, 词数 ÷ 3.5 + 术语税),由 type_budget.js 计算,入场/出场时间在此基础上叠加,绝不从中扣除。
  • 每行动画化一个属性(只有明确意图时可两个),并且没有行在动画过程中重排字形——只使用 opacity/transform。
  • 入场为 8-15 帧,出场 ≤ 入场,并且出场与后续编辑(硬切 vs. 溶解)匹配,而非默认。
  • 层级按顺序可读:入场顺序、大小比例(≥1.6×)和粗细都指向同一最重要的行。
  • 每行最多一个粗细/大小强调,且没有循环或脉冲。
  • 规格中命名了帧编号(入场开始、停留开始、停留结束、出场结束),以便 remotion-compose 无需猜测即可编写 Sequence。

禁忌

  • 不要交付停留时间短于阅读预算的文字——这是动态排版最常见的失败。如果没有足够空间停留,请删减词汇,而非缩短停留时间。
  • 不要动画化 font-size、width、letter-spacing 或任何会重新布局字形的属性;布局抖动会让文字难以阅读。改用 transform 进行缩放。
  • 不要每行动画化超过一两个属性,并且绝不要逐词揭示密集字幕——阅读会变得断断续续。
  • 不要循环、脉冲、反复弹跳或让文字持续运动;不停止的运动无法被阅读。
  • 不要动画化每个元素。lower-third、水印、持续标签和法律文本只做一次入场然后保持静止。不要用复杂的入场动画化主体/字幕文字——淡入是正确的选择。
  • 不要在此处决定底层缓动曲线或场景剪辑——那是 motion-design-principles 的职责。不要在此处编写 Remotion 组件——将填写完成的规格交给 remotion-compose。
  • 不要编造文案。动画化用户给你的文字;如果某行太长而无法停留,请让他们缩短。

兄弟技能 - 交接,不要吸收

本技能负责文字时间与阅读。相邻的决策属于兄弟技能;从它们那里获取信息,不要在此重复它们的工​​作。

  • motion-design-principles - 剪辑、非文字运动的节奏,以及缓动曲线(加速形状)。从那里获取曲线并在此处应用于文字。
  • video-storyboard - 存在哪些场景和镜头,以及它们的顺序。首先获取场景列表;本技能只处理场景内文字的时间。
  • motion-color-and-light - 文字相对于背景的颜色、对比度和可读性。如果因为颜色导致文字难以阅读,这是该技能的职责,而非在此处调整时间。
  • product-demo-director - 产品演示的整体叙事和节拍列表。它决定标题卡说什么以及何时出现;本技能决定每个标题卡如何动画化。
  • sound-and-music-sync - 在节拍或重拍上落定文字揭示。将 holdStart@ / 入场帧编号交给它,以便揭示可以对齐音轨。
  • social-video-formatter - 根据平台调整和裁剪字幕轨道(9:16 TikTok、1:1 feed、安全区域)。在此处一次制定时间;让该技能按平台重新调整。

计算器

自包含 Node 脚本。保存为 type_budget.js 并使用 node type_budget.js 运行。无依赖项。编辑 lines 数组为你实际的内容;它会根据你的 fps 返回每行的帧数预算。

// 动态排版阅读预算。编辑 lines + fps,然后:node type_budget.js
const fps = 30
const WORDS_PER_SEC = 3.5   // 舒适屏幕阅读速度(~200 wpm)
const FLOOR_SEC = 0.8       // 任何行的最短停留时间,即使只有一个词
const TERM_TAX_SEC = 0.3    // 每行包含数字/名称/术语的额外时间
const ENTRANCE_FRAMES = 12  // 0.4s 入场
const EXIT_FRAMES = 9       // 出场 ≤ 入场

const lines = [
  { text: 'Ship video in one prompt', hasUnfamiliarTerm: false }, // 标题卡
  { text: 'Rendered headless in 4K',  hasUnfamiliarTerm: true  }, // 字幕:'4K'
  { text: 'Go',                       hasUnfamiliarTerm: false }, // 主打词
]

const sec2frames = (s) => Math.ceil(s * fps)

function budget(line) {
  const words = line.text.trim().split(/\s+/).length
  const raw = words / WORDS_PER_SEC + (line.hasUnfamiliarTerm ? TERM_TAX_SEC : 0)
  const holdSec = Math.max(FLOOR_SEC, raw)
  const holdFrames = sec2frames(holdSec)
  const totalFrames = ENTRANCE_FRAMES + holdFrames + EXIT_FRAMES
  return { words, holdSec, holdFrames, totalFrames }
}

let cursor = 0
for (const line of lines) {
  const b = budget(line)
  const enterIn = cursor
  const holdStart = enterIn + ENTRANCE_FRAMES
  const holdEnd = holdStart + b.holdFrames
  const exitOut = holdEnd + EXIT_FRAMES
  console.log(`"${line.text}" (${b.words}w)`)
  console.log(`  hold:        ${b.holdSec.toFixed(2)}s = ${b.holdFrames} frames`)
  console.log(`  total slot:  ${b.totalFrames} frames (enter ${ENTRANCE_FRAMES} + hold ${b.holdFrames} + exit ${EXIT_FRAMES})`)
  console.log(`  Sequence:    enter@${enterIn}  holdStart@${holdStart}  holdEnd@${holdEnd}  exitOut@${exitOut}`)
  cursor = exitOut
}
console.log(`Total track length: ${cursor} frames (${(cursor / fps).toFixed(2)}s)`)

示例输出

"Ship video in one prompt" (5w)
  hold:        1.43s = 43 frames
  total slot:  64 frames (enter 12 + hold 43 + exit 9)
  Sequence:    enter@0  holdStart@12  holdEnd@55  exitOut@64
"Rendered headless in 4K" (4w)
  hold:        1.44s = 44 frames
  total slot:  65 frames (enter 12 + hold 44 + exit 9)
  Sequence:    enter@64  holdStart@76  holdEnd@120  exitOut@129
"Go" (1w)
  hold:        0.80s = 24 frames
  total slot:  45 frames (enter 12 + hold 24 + exit 9)
  Sequence:    enter@129  holdStart@141  holdEnd@165  exitOut@174
Total track length: 174 frames (5.80s)

解读:5 个词的标题需要 43 帧的停留、完全可读时间——而且这还不包括 12 帧的入场和 9 帧的出场,所以实际总时间为 64 帧。4 个词的字幕看起来更短,但包含一个数字(4K),所以术语税将其停留时间推高到 44 帧——尽管词数更少,但比标题略长。单个词 Go 触及了 0.8s 的最低值:即使是一个词也需要一个节拍。这些 enter@ / holdStart@ / holdEnd@ / exitOut@ 帧编号可以直接放入 remotion-compose 作为 <Sequence from={…} durationInFrames={…}> 边界——无需猜测文字应停留多久。

模板:motion-type-spec

填写此模板并交给 remotion-compose。每行文字一个块。

MOTION TYPE SPEC. [填写: 合成名称].  fps: [填写]  canvas: [填写: 1920x1080 / 1080x1920]

LINE 1
  Copy (verbatim):     [填写]
  Hierarchy role:      [填写: headline / subtitle / caption / lower-third / CTA / hero-word]
  Size:                [填写]px        Weight: [填写: 400 / 700 / variable axis]
  Reading budget:      [填写]w -> hold [填写]s = [填写] frames   (from type_budget.js)
  Entrance:            [填写: fade / rise+fade / word-by-word / pop / wipe]  over [填写: 8-15] frames
  Exit:                [填写: fade / cut-on-edit]  over [填写: <=entrance] frames
  Property animated:   [填写: opacity / opacity+translateY / scale]   (NO font-size/width)
  Accent (max one):    [填写: none / weight 400->700 on word "X" / scale-up on "X"]
  Frame numbers:       enter@[填写]
...

[为翻译而截断]

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Captions From Transcript

Produce an accurate, properly timed caption track (SRT or WebVTT) from a video

Motion Design Principles

The craft layer for motion: pick the right easing (ease-in / ease-out / ease-in-out / spring), get timing and spacing right, build the anticipation→action→follow-through arc, and apply Disney

Narration Script

Write the spoken voiceover for a tutorial or demo - the actual words, phrased for the ear and synced one-instruction-per-action to what is on screen, with a pacing budget and a confident, jargon-checked tone. Use when someone says

Product Demo Director

Direct the craft of putting a real software UI on screen - cursor choreography, zoom/pan/callout language, screen-recording vs recreated-UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking

Remotion Compose

Turns a natural-language video brief into a complete, ready-to-preview Remotion composition - extracts duration, scenes, brand colors, aspect ratio, and real copy; plans the frame budget; and writes data-driven React/TypeScript using useCurrentFrame, interpolate, spring, AbsoluteFill, and Sequence, registered in Root.tsx. Use when someone says

Remotion Render

Renders a Remotion composition to MP4 and runs the edit-and-re-render loop - CLI render commands, 1080p/4K/9:16 presets, concurrency tuning, codec selection, batch variants from a JSON data file, and Lambda for cloud rendering. Use when someone says

Remotion Setup

Scaffolds a new Remotion video project wired for Claude Code Agent Skills - Node check, create-video scaffold, skills install, folder conventions, Google Fonts, and a smoke-test render. Use whenever someone wants to start making videos with Remotion and Claude, even just

Screencast Capture

Capture clean raw screen and camera footage for a tutorial or product demo - choosing the recorder (macOS Screenshot toolbar, QuickTime, OBS, Windows Game Bar), setting resolution / frame-rate / cursor / microphone, prepping a distraction-free stage, and recording in retakeable segments. Use when someone says

SkillMedev/tutorial-video-studio

Plan a product demo, feature announcement, or launch video as a beat sheet and shot list BEFORE animating - hook in the first 3s, problem, reveal, proof, CTA - with target duration and pacing per scene type, output as a JSON scene plan that remotion-compose consumes directly. Use when someone says

Social Video Formatter

Reframe and export a finished video for social platforms - 9:16 ↔ 16:9 cropping, burned-in captions, a platform-native first frame, loop design, and per-platform specs (aspect, length, safe areas) for TikTok, Reels, Shorts, X, and LinkedIn. Use when someone says

Sound and Music Sync

Score a video like an editor: beat-match cuts to the music, land SFX on transitions, pace the voiceover so it breathes, source royalty-free tracks safely, and duck the music so the VO sits clearly on top. Use when adding music, sound effects, or voiceover to a video, when asked to

相关技能