VIDEO.md 为什么是这个样子
规范 讲一个包里有什么。这一页讲为什么:它解决什么问题,想法从哪来,每个决定背后的理由。
一句话
每个技能有一个 SKILL.md,每条视频也有一个 VIDEO.md。它从一张几百 token 的卡片开始,逐层展开,直到单个镜头。每一层都写明自己有多大,并把看到的和推断的分开。
卡片是这条视频的身份证:它是什么、怎么做的、有多确定。整个包是它的档案:概览、时间线、单个镜头。需要哪一页就翻哪一页,不用把整个档案读完。
要解决的问题
拆解一条视频会产出很多东西:逐镜的测量值、每一镜制作方式的概率、证据、字幕时间、音效位置、复刻提示词、帧图、分轨音频。三类读者想从中拿到的东西不一样:
| 读者 | 想要 | 难处 |
|---|---|---|
| 人 | 结论、好在哪、复刻步骤 | 细节零散、太技术 |
| 模型和 agent | 能回答用户问题的那些事实 | 上下文成本、在细节里迷路、把推断当事实 |
| 程序 | 稳定的字段和取值 | 格式悄悄变化、要解析文字 |
人有报告,程序有原始数据,模型没有专门给它的东西。
把原始数据交给模型行不通。一条三分钟的口播视频,JSON 约 19 万 token;一条 75 镜的影视解说约 24 万。每个问题都读一遍,又慢又贵。而且测量值、推断和结论并排放着,「工具认为这一镜有 41% 可能是录屏」就变成了「这是录屏」。
把给人看的报告交给模型也不行。报告是按从头读到尾写的,有折叠、有叙述,没有稳定的结构,没法只读其中一部分。
VIDEO.md 就是给这个缺位的读者准备的格式。
想法从哪来
VIDEO.md 里没有新东西。它把几种已经好用的做法组合在一起。
Agent Skills:渐进式展开
一个技能就是一个文件夹。SKILL.md 前置信息里的 name 和 description 常驻 agent 的上下文,只有几十个 token。只有技能用得上时,agent 才读正文;正文指向 references/ 下的文件,需要时才打开。
VIDEO.md 用的是同样的结构,只是把一项能力换成了一条视频:
| Agent Skill | VIDEO.md |
|---|---|
SKILL.md 前置信息:name、description |
VIDEO.md 前置信息:卡片(name、description、制作方式占比、置信度) |
SKILL.md 正文:指令 |
VIDEO.md 正文:结论、待复核的问题、地图 |
references/*.md,按需打开 |
video/*.md,每个一个主题,按需打开 |
| 脚本和资源文件 | 原始数据、帧图、分轨音频 |
它多走了一步:每个文件都写明自己有多少 token,地图里也有。技能告诉 agent 有什么;VIDEO.md 还告诉它打开要花多少,模型读之前就能权衡。
小型 DSL:一行一个镜头
时间线是整个包的主干。它不是 JSON 数组,也不是 Markdown 表格,而是一种很小的行格式:
#07 16.2-18.5 | seen man talking, chat screenshots pop up | camera static | made~ screen capture 41% | flag low confidence
思路和 SRT 字幕、EDL 剪辑表、日志行一样:一行一条记录,先写编号和时间,再写 key value 对。这样做的原因:
- 密。 同样的数据写成 JSON,大量 token 花在键名、引号和括号上。75 镜的时间线约 3.5k token,模型能一次读完整条视频。
- 直接能读。 人和模型不用渲染就能读,模型写起来也不容易出错。
-
好解析。 三条规则:行首是 #n start-end,字段用 `` 分隔,第一个空格前面是键。值里不会有 |。参考解析器只有十几行。 - 推断写在语法里。 以
~结尾的键(made~、material~)是推断的,不带的是看到的或测得的。读的一方不用从上下文里去猜。
DSL 只用在这一处。卡片和镜头数据是 YAML 前置信息,用 JSON Schema 校验;说明文字是普通 Markdown。紧凑的语法放在最需要密度的地方,其他地方都用大家已经会读的格式。
另外
- Markdown 加 YAML 前置信息,和静态站点生成器、Agent Skills 一样:正文给模型,前置信息给程序,一个文件两用。
- JSON Schema 覆盖每种前置信息,
videomd check可以据此校验一个包。 - 一个目录就是一个包,和技能一样:没有打包格式,没有索引数据库。复制、压缩、提交到仓库都行。
VIDEO.md 里的地图和时间线用同一种行格式(path | tokens | about),所以一个包只有一套小语法,不是两套。
设计决定
必需的核心很小
一张卡片只需要六个字段:版本、名字、描述、来源、镜头数、语言。一个镜头只需要编号和时间。其他都是可选的,包括判断每一镜是怎么做的。
技能也是这样:只有 name 和 description 是必需的。一个只总结内容的工具,或者一位描述自己视频的创作者,不用编造手里没有的数据,也能写出合格的包。会判断制作方式的工具再加上 made_mix 和 inferred,懂这些字段的读取方就会用上。
身份
卡片叫身份证,就得有身份:source.sha256 是整个文件的哈希;视频来自链接时,还有 source.url。两个工具为同一条视频写的两个包,可以据此对上、比较、合并。
四层,每层大一个量级
| 层 | 大小 | 够回答什么 |
|---|---|---|
| L0 卡片 | 100–300 token | 讲什么,要不要打开 |
| L1 概览和地图 | 1–2k | 结论、复刻概要、哪里不确定、下一步读哪个文件 |
| L2 主题 | 几百到几千 | 某一方面的完整信息:时间线、声音、包装、复刻 |
| L3 镜头 | 500–1000 | 某一镜:看到的、推断的和依据、提示词、帧图 |
| L4 原始 | 10 万以上 | 程序 |
多数问题(「这条怎么做的」「要准备什么素材」「哪几镜要复核」)在 L1 就能回答。按镜头的问题加上时间线,总共约 4k token。只有核实某一镜才需要 L3。
分层跟着人提问的顺序:先问整条视频,再问某一方面,最后问某一镜。
读之前就知道代价
每个文件的前置信息里都有 tokens,地图里也有一列。这改变了模型读文件的方式:不是「打开看看」,而是「这个问题值得花 14k token 读复刻方案吗,还是时间线里的 remake 字段就够了?」
看到的和推断的分开
这是最重要的一条规则。拆解里有两种性质很不一样的内容:
- 看到的:有人在讲话,右上角有标题,镜头固定。能对着帧图核实。
- 推断的:根据噪声和帧率,这一镜是 AI 生成的(72%)。人眼不一定能核实。
两者混在一起,模型会把推断当事实转述,用户也分不清哪句该信。所以 VIDEO.md 在三处把它们分开:时间线里用 ~ 键;镜头文件里看到的和推断的各占一节;所有推断的字段都放在 inferred 下,附概率、次选和 decided_by(tools、model、agent、human)。两者对不上时,以帧图为准。
时间线是主干
视频是线性的,几乎所有问题最后都落到「第几秒、哪一镜」。时间线是唯一值得整个读完的 L2 文件;主题文件和镜头文件都按镜头编号挂在它上面。它的 flag 字段标出需要复核的镜头,模型扫一遍就知道该打开哪些帧图。
形式固定,内容开放
程序依赖的部分是固定的:前置信息字段、时间线语法、取值表里的 id。能扩展的部分是开放的:新的时间线键、新的主题文件、新的叠加层 id,以及取值表以外的 x- id。读的一方忽略不认识的内容。只做增加时版本号不变,改变含义才升版本。
这样生成方能力变强时(比如多了一个运镜维度),现有的读取方照常工作。
随视频一起扩展
六秒的广告和两小时的电影用的是同一个格式。广告只用卡片、时间线和两个镜头文件。电影多一份场景列表,模型先读几千 token 再决定看哪里,时间线也按场景拆开。一小时的长镜头按内容拆成多行,共用一个 take;反应视频在 layers 下描述画面的每一部分;先环绕再甩镜的镜头按顺序列出两个运镜动作。这些都是可选的,视频需要时才加,简单的视频依然简单。
文字给模型,id 给程序
时间线的值是用包的语言写的文字:「screen capture 41%」或「屏幕录制 41%」,因为读它的是模型。screen_capture 这类稳定的 id 放在镜头文件的前置信息和 made_mix 里,程序只读这些。每一层只做一件事,谁都不用从另一层里解析出来。
它带来什么
agent
- 回答一个问题花几千 token,而不是几十万,一次对话可以涉及好几条视频、来回追问很多次。
- 不需要了解任何生成方的内部数据,会读 Markdown 就够了。
- 推断有标记,转述给用户时更不容易说过头。
- 有地图和 token 数,agent 自己决定读多深,不用照着固定的流程走。
程序
- 有 schema、校验器和参考读取实现。程序只靠前置信息和时间线行就够了,不用解析文字或原始数据。
- 新增内容不会弄坏现有的解析器。
人
- 拆片包就是 Markdown,不用任何工具也能读。
- 每个结论从哪来都有记录(
readers、decided_by):测量得出、模型看过、agent 复核过,还是人改过。
生态
- 生成方和使用方解耦。任何能写出合格拆片包的拆解工具,都能配合任何能读它的 agent 或程序。
- 复核有了落点:要复核的镜头在时间线里标着;复核结果写回后重新生成包,
decided_by随之改变。
它不是什么
- 不是报告。 报告给人看:讲故事、给步骤。VIDEO.md 给模型看:给事实、给结构。两者可以来自同一份数据。
- 不是剪辑交换格式。 EDL 和 OpenTimelineIO 描述片段怎么拼成成片,给剪辑软件用。VIDEO.md 描述视频里有什么、是怎么做的,用来理解和复刻。
- 不是数据库。 没有查询语言,没有索引。一条视频一个目录,靠地图和文件名找东西。
其他做法
| 做法 | 问题 |
|---|---|
| 把原始 JSON 交给模型 | 太大;测量、推断和结论混在一起 |
| 把报告交给模型 | 没有稳定结构,没法只读一部分 |
| 每次让模型看一遍视频 | 慢、贵、不可复现,也看不到帧率、噪声和元数据 |
| 一个大 Markdown 文件 | 要么太长读不完,要么太短没用;没法按需展开 |
| 只提供 JSON API | 适合程序,对模型浪费,人读不了 |
VIDEO.md 不是从中挑一个,而是把它们分层:上层给模型,中层给模型和程序,底层给程序。