Communitygithub.com

SaviourV2/视频叙事

设计并构建长视频中“说话人头”视觉层的一种方法:将整个视频视为一个持续存在的世界,摄像机在其中移动,而非一系列独立的图形。适用于需要编辑视频、添加动态图形、为脚本设计视觉、规划剪辑,或修复被认为令人困惑、文字过多、难以理解或“明显由AI制作”的剪辑。涵盖持续世界、摄像机语法、聚光灯规则、空间开放循环、装饰与标记纪律、字幕时间轴以及验证门。

视频叙事 是什么?

该技能(SaviourV2/video-storytelling)提供了一种系统化的方法,用于创建长视频(如新闻报道、深度解析、教程或列表类内容)的视觉层,避免传统“场景思维”导致的频繁画面切换,从而让观众在数分钟后仍能保持清晰的方向感。其核心创新在于将整个视频构建为一个“持续存在的世界”(Persistent World),所有视觉元素一旦出现便永不消失、移动或重绘,摄像机通过在该世界中的移动(推近、拉远、横向移动)来引导注意力,而非通过剪辑新图形。技能详细阐述了四大原则:持续世界、摄像机即剪辑、注意力即聚光灯(同一时间只有一个元素处于全亮度,其余保持安静但可见)、开放循环空间化(通过视觉上未完成的部分来保持观众的期待和参与)。此外,该技能还包含一套严格的设计纪律,包括仅绘制脚本中提及的元素、使用单一主题跟随对象、全局标记系统(限定线条粗细、字号、圆角半径和颜色的固定组合)以及精确的动效和构建约定,确保视觉层次清晰,避免“AI感”。该技能为开发者提供了具体的工作流程和验证门,参考实现包括设计系统文档和开放循环几何模式,是AI辅助视频编辑系统(如Claude Code、Cursor)可执行的高级、专业的视觉叙事规则集。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/SaviourV2/acevids-editor/tree/HEAD/.claude/skills/video-storytelling

在你喜欢的 AI 中提问

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

文档

视频叙事 是做什么的?

如何构建长视频的视觉层,让观众在第九分钟仍能保持方向感。适用于任何带有脚本的“说话人头”视频:新闻评论、单一主题深度解析、对比、教程、列表类内容。

该技能所要取代的失败模式是“场景思维”。每几秒出现一个新图形,迫使观众每几秒就重新开始理解,而没有哪个单独的图形是错误的,这就是为什么反馈总是笼统的“令人困惑”或“信息量太大”,而不是具体的缺陷。

如需中立练习节拍表,请阅读仓库根目录下的 docs/STORYTELLING-WORKBOOK.md。可复用的设计系统位于此技能的 reference/design-system.md 中;已完成的开放循环几何位于 reference/patterns/wall-of-slots/。不需要私有源视频。

这不是 hyperframes-video-beats。那个技能是在说话人头之上放置覆盖卡片。而这个技能设计的是视频 所讲述的 东西本身。

1 · 四大原则

一个持续存在的世界

视频存在于一个单一空间中,并且永远不会重置。观众已经看到的所有内容仍然存在于他们离开时的位置,新的素材被添加到其中,而不是替换它。一个元素一旦被绘制,就永远不会被重绘、移动或重新标记。

此技能中的其他一切都依赖于此。如果空间不断变化,摄像机将无处可去;如果屏幕上没有其他东西,聚光灯就毫无意义;在一个重置的世界中,开放循环无法保持开放。

这个世界也必须值得停留,因此要在构建任何东西之前决定空间语法,并在整个运行时间内保持它。在参考构建中:从左到右是走向结果,向上是走向人类并且是屏幕上唯一温暖的东西,向下是进入记录系统。在前两分钟学会这一点的观众,将不费吹灰之力就能理解视频的其余部分。

为了表达意义,故意且仅一次打破语法。参考构建在十分钟内唯一的一次从右到左移动,是在说到“重新开放率”这个词时,一个已解决的工单反转回队列。它无需一句话就落地,因为方向在此前三分钟里已经意味着某种东西。

摄像机就是剪辑

每次切换到新图形都会让观众重新迷失方向。在一个保持不动的空间中移动则不会让观众付出任何代价。推近的镜头读作“更仔细地看你已经理解的那部分东西”,而拉远则是工作得到回报的地方,因为到目前为止构建的所有东西都还在那里。

在三个高度层级上工作,并在相邻层级之间移动:

高度展示内容用途
世界整个空间定位、回报、“我们在这里”
区域正在讨论的子图大部分运行时间
细节一个元素一个数字、状态变化、决策

从细节跳到世界会让人迷失方向,除非这是一个有意的回报节拍,在这种情况下,这是最好的选择。

每条规则都需要一次重构才能学会:

  • 将取景命名为精确的世界窗口,而非比例因子。 窗口边界必须落在 标签之间。将取景指定为“比例 0.6”会在帧边缘将单词切成两半。
  • 为相同目的重复使用相同窗口。 如果定位镜头是一个特定的窗口,始终使用那个精确的窗口。几乎相同的取景会被读作漂移。
  • 根据旅行距离变化持续时间,而不是使用一个全局预设。
  • 摄像机和全帧擦拭按顺序进行,从不重叠。 同时进行时,它们会将内容斩断。先是摄像机,然后是擦拭。
  • 覆盖层在摄像机在其下方移动之前变为不透明。 相反顺序下,部分移动会暴露出来,读作跳切。
  • 标签距离帧边缘至少 60 像素。 元素可以出血并读作“世界在继续”;一个被从中间切断的单词则读作错误。通过放置解决,而不是通过遮罩,因为羽化效果无法捕捉以约 1800 像素/秒速度移动的刀刃。
  • 两个连续的同主体移动读作故障。 一个先完成的重取景,然后才开始的一个擦拭,是缩放、完全停止和第二次运动——客户称之为“故障和停顿”。将它们合并为 ONE 手势:共享对称缓动(power2.inOut),落在同一帧上,这样面板读作将素材推到一旁。相关:在 可见素材 移动上使用前端加载缓动(power3/4.out)会在前端加载约 90% 的行程并缓慢停止;将它们保留给元素入场,此时缓慢停止读作稳定动画。(在示例简介中花费了一次客户标记的修订。)

注意力即聚光灯

在任何时刻,只有一个元素处于全亮度。其他所有已绘制的元素保持安静但清晰可读。 不是可选的。这是让一个世界可以累积到十几个元素而从不显得拥挤的规则,也是让拉远镜头可读而不是压倒性的原因。

层次结构来自活动与安静元素之间的 比例,而非让所有东西都变暗。参考构建的第一个原型的最亮像素为 101/255,在 960x540 分辨率下无法阅读;解决方法是使用更亮的墨水,而不是更多调暗。

状态目标亮度 (Y, 16-235)参考中的不透明度
活动的描边+标签200-2351.0
上下文,已绘制且仍然相关120-1500.56
已使用,已完成其作用85-1050.33
任何标签,任何状态永不低于 90

实现是一个函数,在每个旁白节拍处被调用,参数为正在讨论的 id(build_s01.py,lit()):

def lit(t, active, warm=(), dur=0.5, floor=FLOOR):
    active = list(active) + [g + "-l" for g in active if g + "-l" in order]
    for gid in order:
        if gid not in opac:      # 从未绘制:无需点亮
            continue
        tgt = 1.0 if gid in active else (WARM if gid in warm else floor)
        if gid not in active:
            tgt = min(tgt, MUTED.get(gid, 1.0))
        ...

其中三个细节是承载性的:

  • 标签始终继承其元素的状态(通过 -l 后缀折叠)。一个点亮的元素下面有一个不可读的标签,正是要修复的缺陷。
  • 已完成其作用的道具通过 MUTED 上限退回到不透明度 0,而不是 0.3。静默到 0.3 会在屏幕上方为本节剩余时间留下无法解释的纸屑。生成器规则:在稍后开始的任何 lit() 之前发出 mute(),否则当补间完成时静默会被覆盖。
  • 不透明度事件必须按时间轴顺序发出,否则跟踪器会看到过时状态并计算出错误的目标。保持一个 seq() 守卫,在发出顺序错误时抛出。
  • 每个窗口的每个元素有一个不透明度权限。 两个同时活动的、将同一元素的不透明度驱动到不同值的补间,在独立部分中平滑渲染,但在组装后的母版中会以约 10Hz 闪烁,因为获胜的补间每帧交替出现。参考构建在每个对接点都发布了此缺陷。当像 lit() 这样的扫描与显式的变亮或静默重叠时,稍后开始的补间是唯一驱动者,并且扫描跳过这些 id(lit(..., skip=(...)))。防范措施:扫描组装后的渲染,检查每个过渡窗口中是否有单帧的亮度来回跳动(参考构建中的 qa/v4/flicker/qa-flicker.mjs)。

开放循环是空间化的

永远不要说“我们稍后再回来”。在世界上留下一些视觉上不完整的东西,然后返回它。观众能看到承诺,就是他们能感受到未完成承诺的承诺。

无论形状如何,机制都是相同的:

  1. 在钩子中植入它,在空间中,在做出承诺的那行上。
  2. 在每个边界处重新展示它。 任何章节交接都是边界。重新展示耗时约两秒钟,是保持注意力的机制;跳过它,回报就会变得毫无意义。
  3. 使其可见地推进。 观众必须看到不完整性的缩小。
  4. 在你打开的那个图像上关闭。

根据脚本选择形状:

脚本形状世界什么是不完整的
N 个并行项目脊线上的 N 个插槽空槽位(参见 reference/patterns/wall-of-slots/)
单流程,深入完整的管道,已布局断裂或缺失的链接
层级或级别向上构建的堆栈堆栈顶部是虚影
比较共享轴上的两列一列为空,或未填写的计分卡
新闻或公告时间线或景观地图右侧,未来,是空白的
教程或一起构建已完成的架构,虚化每个尚未构建的节点

将项目交给其插槽是一次实时的摄像机移动,约 1.4 秒,绝不是剪切到已填充状态的预制图片。观众看着他们刚刚了解到的东西变成那个图块。如果视频有数字或计数器,在同一个移动中将其滚动,作为里程表,使用相同的开始时间、持续时间和缓动,否则两个数字会在滚动中途合并成一个条带。

计数器需要一个名称,而不仅仅是一个数字。 角落的数字告诉观众他们在序列中的位置,但没有告诉他们当前项目是 什么;九分钟时,“03”不传达任何信息。将数字与 1-2 个词的标签(SUPPORT, VOICE AI)配对,使用相同的“铭牌”样式,作为与数字相同的刚性固定装置,在同一个里程表滚动中交换。客户对参考构建的评论正是要求这个:视觉效果很好,但观众仍然失去了对屏幕上哪个用例的追踪。

2 · 纪律

如果没有词语,就不绘制

每个形状都是一个带标签的元素、带标签元素之间的连接器、正在移动的主体或环境背景。没有其他东西。

这源于一次静音测试审查,该审查的得分为 7/10(理解度),并指出了原因:图表很干净,但装饰不是。一打未标记的形状以与有意义的形状相同的粗细和调色板绘制,因此首次观看的观众无法区分信号和纹理,并花费真正的注意力来解码那些从未打算被解码的东西。这就是“信息量太大”从文字转移到形状。

预算:每节约 20 个屏幕单词。 没有句子。标签是 1-2 个词,位于其元素下方。参考的第一节在 84 秒内有 21 个单词。

推论:反模式视觉从不覆盖推荐。 首先将世界变到近乎黑色,或者将反例放在好的图表不在的地方。

让观众有一个东西可以跟随

通过一个其状态可见地变化的单一移动主体来承载故事:一个带有数据行和分数栏的芯片、一份文档、一个请求。行被填充,栏移动,边框改变颜色。观众必须能够仅通过观看那个物体来跟随整个章节,并且它决不能传送;它沿着已绘制的连接器以恒定速度移动。

一个全局标记集

完整细节在 reference/design-system.md 中。

标记值
描边1.5 / 2.5 / 4 / 7,没有其他
字体22 / 30 / 42 / 60 / 84
圆角10 / 22 / 40,始终是 superellipse(2)

五种颜色,五种固定含义,零装饰。暖色意味着涉及人类,并且其他任何东西都永远不会是暖色。永远不要使用纯白色作为字体;它在深色背景上会产生光晕。

此纪律防止的失败,来自第一次构建的工艺审查:“每个决策都是本地且正确地做出的;没有做出全局决策。” 18 种描边粗细和 9 种字体大小,其中大多数相差 0.2 个单位,单独看不可见,合起来则是致命的。眼睛得到的是噪音而不是层次结构。使用一个标记检查工具来防范,该工具在构建失败时报告。

动效

入场使用 cubic-bezier(0.16,1,0.3,1),退出比入场更快,持续时间根据质量而变化,因此一个 290px 的节点和一个 40px 的标签不会以相同方式减速,并且 back.out 每节正好一次,用在值得的节拍上。

永远不要使用交叉淡化。 全出血层通过在一个已经不透明的背景上进行裁剪来进入和退出。在任何时刻,一个像素要么是图形,要么是素材。

3 · 构建约定

  • 每节一个生成器。 scripts/build_<id>.py 只写 compositions/<id>.html。编辑生成器,永远不要编辑生成的 HTML。节的根文件 index-*.html 是手动维护的,因此取景更改在那里进行。
  • 共享模块保持共享。 任何定义共享几何的东西都由每节导入。如果节由并行 agent 构建,禁止它们接触共享模块;分叉的几何会无声地破坏每个交接。
  • 在组装前为 SVG 定义命名空间。 每节定义自己的 gEdge、shadow、edgeFade。在一个组装后的 DOM 中,url(#id) 解析为文档顺序中的第一个匹配项,因此一旦较早的组合被卸载,稍后的每个图形都会绘制 无。参考构建中的代价:35 秒的空屏幕,所有门都是绿色的。只有查看组装后的渲染才能发现它。
  • 所有时间对齐到单词的开始,基于单词级别的转录本,在锚定单词之前 0.15-0.25 秒 进入。永远不要将一节均匀地划分为节拍。
  • 审核间隙。 任何超过约 1.5 秒且没有任何事情发生的片段都是死屏;让生成器打印它们。
  • 在剪辑中留出空气。 激进的停顿压缩会在句子边界产生接近零的间隙,客户会听到“结巴”和跳切式剪辑。根据说话者自己的规范进行校准:标记句子边界间隙比其中位数紧约 10 倍的连接点(参考说话者中位数为 470ms;标记的连接点约为 20-40ms),并通过插入 4-8 帧的空气来修复,不要触碰单词。空气是音轨真实房间音的捐赠切片,带有 10ms 淡入淡出,永远不要使用 anullsrc:相对于 -50dBFS 底噪的数字静音是可听见的缺失。视频保持帧;句子之间,说话人头是近乎静止的,4-8 帧的保持是不可见的。仅插入更改会确定性地偏移转录本,因此无需重新转录。插入的边缘必须尊重语音包络:将捐赠音紧贴单词尾部在 1ms 处会导致可听见的点击;在捐赠音的开始和结束处使用 5ms 淡入淡出,并让淡入的起始点位于单词尾部的能量降至中值以下时,这自然导致插入偏移一个或两个额外的帧。

[其余内容将被翻译]

Individual skills in this repo

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

相关技能