llvideo 是做什么的?
你无法观看视频。但视频原生模型可以。这项技能将一个这样的模型置于 CLI 之后,让它返回结构化证据而非散文,然后将真实帧交给你,让你自己做出判断。
这个区别是全部关键。如果你转述模型的摘要,你就是一个中间人。如果你基于一个类型化的索引进行推理,并用你查看过的像素来确认它,你就是分析师。
设置检查
llvideo providers
需要 ffmpeg 在 PATH 中和一个 API 密钥。GEMINI_API_KEY 可以处理所有事情。OPENROUTER_API_KEY 价格大约便宜一半,但没有上传端点,因此它仅适用于 URL 和小片段——并且 OpenRouter 要求至少购买 1.00 美元信用额度才能接受任何视频请求,包括 :free 模型。
密钥首先从环境变量读取。作为备用方案,它也会读取 ~/.itachi-api-keys 中的 KEY=value 文件,这只是为了方便将密钥从 shell 配置文件中移出——环境变量就足够了。
你应该遵循的循环
1. 始终从免费开始
llvideo probe VIDEO # 时长、编码、分辨率、token 估算——不花一分钱
llvideo plan VIDEO # 将花费什么以及如何处理——不花一分钱
plan 会告诉你采样率、是否需要转码、token 数量和美元估算。在花钱之前先阅读它。
2. 索引视频
llvideo index VIDEO
llvideo index VIDEO --json # 用于解析
llvideo index VIDEO --verify 3 # 当屏幕文字重要时——见下文
返回带有时间戳、屏幕文字、动作、语音、关键时刻以及显式的 uncertainties 列表的场景。它还会写入一个联系单。
3. 查看联系单。此步骤不可省略。
index 输出以路径结束。在你回答用户之前,用你自己的视觉查看那个图像。 它是一张覆盖整个时间线的图像,大约 600–1,600 tokens。让你接地气很便宜,但犯错代价高昂。
你断言的一切应该是以下之一:
- 你在某一帧中自己看到的东西,
- 一个 ffmpeg 测量值,或
- 一份转录引用。
其他任何内容都必须注明出处:“索引报告称……”。永远不要将模型的猜测洗白为你自己的声音。
4. 在关键处深入
llvideo clip VIDEO --start 02:10 --end 02:40 --fps 4 -q "logo 是否动画流畅?"
llvideo stills VIDEO --at 02:14,02:19 --width 1920 # 全分辨率,你自己查看这些
llvideo sheet VIDEO --at 01:00,01:05,01:10 --tile 768 --cols 2 # 密集的 UI 文字
剪辑是帧精确的,花费几百个 token。随意使用。
理解的最佳视图——timeline
llvideo timeline VIDEO
llvideo timeline VIDEO --transcribe # 单词精确的语音时间
index 分别返回 scenes、speech 和 audio_events 三个独立的数组。每个都准确,但没有任何东西将它们连接起来——因此“仪表盘的近景”和“他说范围错误”位于不同的列表中,而它们发生在同一时刻的事实留给你去重建。
这种同时发生才是上下文。 一个镜头根据其上所说内容的不同而有不同的含义。timeline 将所有内容交织到一条轨道上:
00:10-00:18 (8.0s) *KEY*
shot 正面近景,驾驶员
see 摄像机回到驾驶员身上,一盏亮着的加油站滑过窗外
does 车辆驶过亮着的顶棚
says "加油站出现在片段开始后九秒。"
hear 车内低沉的嗡嗡声
why 加油站顶棚直接从驾驶员身后经过
当问题涉及含义而非清单时,使用此代替 index。
--transcribe 融合了本地词级转录,代替模型的语音。模型的音频时间戳大约漂移一秒,这足以在快速剪切时将一行台词附加到错误的镜头上。语音被分配到与其重叠最多的节拍,而不是第一个接触的节拍,因此跨越剪切的一行台词会落到它大部分被说出的地方。
它报告覆盖率,并命名未提及任何内容的运行时间片段。一个有空洞的时间线错过了某些东西,说出来胜过将部分内容呈现为完整。
后续问题免费
索引根据内容身份和采样设置缓存 48 小时。实测:同一视频上的第二次 timeline 从 12.5 秒及 0.02 美元变为 0.4 秒且分文不花。尽可能多地提问——迭代是建立理解的方式,并且在第一次通过后不应再花费任何费用。--no-cache 强制重新运行。
修复你发现的问题——fix
大多数审计发现不需要重新生成任何东西。错误的响度、削波的峰值、片头或片尾的黑帧——这些是确定性的 ffmpeg 操作,不花钱且不可能产生幻觉。
llvideo audit render.mp4 # 找到问题
llvideo fix render.mp4 # 修复 -> render_fixed.mp4
自动修复: 综合响度(双通道 loudnorm 至 −14 LUFS)、真实峰值削波(保持在 −1.0 dBFS),以及黑色或白色首/末帧——通过测量黑色实际结束的位置来裁剪,而不是假设帧数。
故意不修复的,每种情况都附有理由说明:
| 发现 | 为什么不修复 |
|---|---|
| 时间线中间的黑间隙 | 编辑决策,不会默默删除的缺陷 |
| 冻结帧 | 保持帧可能是故意为之——在时间线中缩短它 |
| 低分辨率 | 放大会发明从未捕捉到的细节 |
| 安全边距 | 布局是构图选择;移动元素,不要裁剪 |
| 时长/宽高比 | 渲染时设置;修剪以适应会剪切内容 |
fix 在修复后重新审计并报告前后计数,因为声称修复有效而不重新测量正是这个工具旨在打破的习惯。在一个故意损坏的渲染上进行实测:5 个主要 + 1 个次要变成了 1 个主要 + 1 个次要,剩下的两个是需要人工决策的那两个。
它从不覆盖源文件。输出到 <name>_fixed.mp4,除非你传递 --out。
生成补充素材——gen
适合插入别处构建的时间线的短素材:建立镜头、B-roll、纹理、logo 片头。不是整部电影。
llvideo gen "黎明时分,缓慢的航拍推近一片雾蒙蒙的松林" --seconds 5
llvideo gen "logo 落入画面" --image logo.png --seconds 3 # 图生视频
llvideo gen "同一场景,更冷的色调" --video clip.mp4 --seconds 5 # 视频生视频
llvideo gen-image "风化木标题卡" --out title.png
通过你现有的 XAI_API_KEY 在 Grok Imagine 上运行。注意这是 xAI 的 Grok,不是 Groq——不同公司。1 到 15 秒,步长一秒,这比 Veo 固定的 4/6/8 秒更灵活。
| 分辨率 | 实测成本 |
|---|---|
| 480p | $0.05/秒 |
| 720p | $0.07/秒 |
| 1080p | ~$0.11/秒(外推,未实测) |
这些费率来自实际作业中 API 自己的使用字段,而非文档。任何超过 1.00 美元的内容需要 --yes。
每个素材到达时都会被审计,这并非装饰。Grok 自己的默认设置产生 848x480 的视频,响度约为 -21 LUFS——审计器都会标记这两点。出于这个原因,gen 默认为 720p。然后你自己查看它:
llvideo sheet clip.mp4
--audio 切换到 grok-imagine-video-1.5,它会生成配乐。生成的音频往往偏小;如果素材要与其他内容并列,请期待响度发现并在后期进行标准化。
审计你制作的视频——spec + --from-project
这是完整的循环。HyperFrames、brag 和 Remotion 都已经知道它们打算构建什么,所以没有人应该手写意图规格:
llvideo audit render.mp4 --from-project ./my-hyperframes-project
llvideo audit brag-output/brag.mp4 --from-project ./brag-output
llvideo audit out.mp4 --from-project ./my-remotion-project
或者单独提取规格以供检查或编辑:
llvideo spec ./project --out intent.json
意图的来源以及可信程度:
| 来源 | 提取内容 | 置信度 |
|---|---|---|
HyperFrames index.html | 场景开始/结束从 data-start / data-duration,屏幕文字从 DOM | 精确 |
HyperFrames STORYBOARD.md | 每个帧的过渡类型和时长(transition_in) | 创作意图 |
| brag | 读取它在 composition/ 下构建的 HyperFrames 项目;交叉检查 brag-plan.md 的场景数量和总时长 | 精确 + 交叉检查 |
Remotion .tsx | <Sequence from= durationInFrames=> ÷ fps;<TransitionSeries.Transition presentation=> | 文字值和 N * fps 精确;计算值被跳过,而非猜测 |
任何无法静态读取的内容都会作为注释报告,而不是被假定——一个 springTiming 时长或一个 from={computeIt()} 会被标记并排除。
为什么存在这个功能。 HyperFrames 的 check 在 headless Chrome 中验证寻址后的合成时间线。brag 的交付门限于预渲染快照。Remotion 根本没有等效的门。它们都不查看导出的 MP4,因此编码器错误、过期渲染或导出时的丢帧会悄然发布。这个工具填补了这一空白——这就是为什么即使项目自己的检查通过了,运行 audit 也是值得的。
规格要求的淡入黑帧不会被报告为黑帧缺陷。只有未声明的黑帧才是发现。
转场、镜头语言和节奏——craft
对于“这个剪切如何”、“使用了什么转场”、“分析剪辑”、“摄像机在做什么”、“为什么感觉这么快”等问题——使用 craft,而不是 index。
llvideo craft VIDEO
llvideo craft VIDEO -q "00:14 的剪切是否落在节拍上?"
index 以 1 fps 采样整个视频,这对于发生了什么没问题,但对于如何剪切则毫无用处:硬剪切只占一帧,因此在 1 fps 下你看到的是剪切两侧的镜头,而从未看到转场。craft 的工作方式不同:
- 一个免费的本地通道对每一帧进行评分,并找到候选转场。这能捕捉到普通检测器无法捕捉的软混合——一个 1 秒的交叉淡化峰值为 0.025,而场景检测触发在 0.12。
- 然后每个候选在一个紧密窗口内以 8 fps 重新检查,因此模型逐帧看到转场发生。
- 通过每个窗口的亮度使用 ffmpeg 测量,这正是区分黑帧淡入淡出和交叉淡化的关键。没有它,模型会将淡入黑帧称为交叉淡化;有了它,就是正确的。
返回镜头列表(尺寸、摄像机运动、构图)、转场列表(类型、精确时长、剪切落点原因)、节奏统计、色彩和光照。
在一个已知转场的视频上验证——4/4 类型正确,时长偏差在 0.2 秒内:
| 构建效果 | 检测结果 |
|---|---|
| 硬剪切,瞬间 | hard_cut,瞬间 |
| 交叉淡化,1.0 秒 | crossfade,1.0 秒 |
| 淡入黑帧,0.6 秒 | fade_to_black,0.5 秒 |
| 左擦除,0.8 秒 | wipe,0.63 秒 |
并且在一个包含甩镜头(whip pan)的连续手持拍摄中,它正确报告了一个镜头和零个转场,而不是虚构一个剪切。
摄像机运动不是剪切。 甩镜头、快速俯仰或快速变焦在低帧率下看起来完全像一次剪辑。craft 旨在区分它们;index 则不能。如果问题关于剪辑,请使用 craft。
标志:--zoom-fps 12 用于非常快速的剪切 · --max-windows 12 用于更密集的剪辑 · --no-zoom 跳过近距离通道(更便宜,但精度低得多)。
屏幕文字是失败模式。认真对待。
模型会自信地错误读取模糊的文字。在真实素材上实测——同一个运动模糊的汽车仪表盘,询问三次:
调用 1: "642" "55 F" "330 mi"
调用 2: "23.9" "65 F" "330"
调用 3: "6:42" "55 F" "330 mi"
单次回答中没有任何内容会标记问题。因此不要依赖单次回答:
llvideo index VIDEO --verify 3
这会运行查询三次,并报告哪些读取是稳定的(每次运行完全相同),哪些是不稳定的。将不稳定读取视为“存在显示但不可读”。如果不稳定读取很重要,请导出全分辨率静帧并自己读取:
llvideo stills VIDEO --at 00:11 --width 1920
每当答案将被执行操作时使用 --verify 3:屏幕录制中的错误消息、仪表盘上的数字、屏幕上的代码、价格、名称。每次额外运行的成本与第一次大致相同——几分钱。
审计渲染——audit
在你制作了一个视频(Remotion、HyperFrames、brag、ffmpeg、Veo)之后,你从未见过它。在交付前检查它:
llvideo audit out.mp4 # 仅免费测量检查
llvideo audit out.mp4 --craft # 再加上转场和镜头
llvideo audit out.mp4 --spec intent.json # 再加上与要求的差异对比
免费检查能捕获那些实际会发布的错误。 没有模型、没有 token、没有网络:
- 黑色或白色首/末帧——最常见的导出缺陷,时间线上的偏离一位错误
- 主体内部的黑色间隙和冻结片段
- EBU R128 响度和真实峰值削波,对比 -14 LUFS 平台目标
- 静音间隙,以及“音频轨道实际上为空”
- 声明与隐含的帧率、分辨率、比特率
- 紧贴帧边缘的明亮细节(标题安全提示)
已验证:捕获 5 个故意植入的缺陷中的 5 个,并在真实专业素材上返回零发现的 CLEAN。它从不虚报。
每个发现都说明它是测量的(ffmpeg 如此说,带有数字)还是判断的(模型认为如此)。切勿将判断结果作为事实呈现。
仅当存在阻塞性问题时退出码为 1,因此它作为 CI 门控有效。
与意图进行差异对比
编写视频本应有的规格,然后进行 diff:
{
"duration_seconds": 30,
"duration_tolerance": 0.5,
"aspect": "16:9",
"transitions": [
{
"start": 0.0,
"type": "hard",
"duration": 0.04
},
{
"start": 2.0,
"type": "crossfade",
"duration": 1.0
}
],
"black_intentional": [
{
"start": 8.0,
"end": 8.25
}
],
"on_screen_text": [
{
"start": 10.0,
"text": "Dashboard UI"
}
]
}
规格中的任何内容如果与 audit(帧率、黑帧、转场的存在)冲突都会作为差异报告。规格要求但视频中未出现的内容会显示为缺失。视频中存在但规格中未声明的内容如果没有明显问题则不予理会。
仅有的两个非阻塞退出代码:1 表示有阻塞问题,0 表示干净但有注释差异。以 --fatal-diff 运行以在差异上失败。
--from-project 是为多项目流水线预先准备的。
最终说明
这个工具不是要节省你观看视频的时间,而是要确保你查看的是正确的帧。索引会预测哪些帧重要;审计会显示哪些帧有缺陷;wikis 只是链接。
使用 llvideo clip --fps 4 而不是更大的值。4 fps 通常足以为要查看的内容提供良好的覆盖。每个都可能有一点不同,但足够相近以评估动作和构图。
对于快节奏的内容,尝试 llvideo timeline --transcribe --fps 8。转录和视觉采样在 8 fps 下都能处理快速对话,但每次运行费用会上升。
指标存储在一个可选的本地数据库中,该数据库可以编译成一个单一的文件以实现可移植性。
它们不一定总是可移植的,但有一个简单的选择。