关于 video-add-b-roll
video-add-b-roll 是为视频项目添加有证据依据的 B-roll 的工作流技能,要求先准备经过验证的转录文本和时间线。它涵盖规划、素材审查、验证与交付,并保留现有剪辑及可追溯的素材来源。
主要功能
- 01依据转录文本和时间线规划顺序片段
- 02通过脚本搜索 Pexels 或导入本地素材
- 03分析候选画面、裁切、质量和重复项
- 04跟踪审批、依赖项、哈希与回执
- 05支持普通和说话者嵌入布局
适用场景
- 01为已剪辑视频添加相关插入镜头
- 02依据转录证据审查候选素材
- 03时间线或调色变化后刷新 B-roll
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ whitetowerai/ cut-as-code --skill video-add-b-roll安装后在 Claude Code 中输入/video-add-b-roll确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/broll-review.htmlexamples/example-broll-plan.jsonexample-candidate-ranking.jsonreference/broll-rules.mdscripts/broll_plan.pybuild_review_page.pycandidate_analysis.pycheck_broll.pynormalize_broll.pypexels.pyspeaker_inset.pytests/test_broll.pytest_normalize_broll_frames.py详细介绍
视频添加 B-Roll
为已理解的规范 Project Protocol 序列添加少量有证据支持的视觉插入镜头。规划或获取任何媒体前,请先阅读 broll-rules.md。使用 example-broll-plan.json 作为计划格式参考。
不容妥协的约定
遵循 broll-rules.md 中的所有编辑、来源、静帧、审查、恢复和交付规则。操作上:
- 使用提供的脚本进行获取、验证、标准化、应用回执和核验。绝不使用原始下载路径,也不以其他素材来源替代。
- 绝不伪造人工授权。Agent 审查必须有明确委托和真实的 Agent 回执。
- 缺失、质量较差或被下载器拒绝的媒体应标记为
skipped;绝不使用随机素材或静帧作为替代。
要求和输入
需要 Python、ffmpeg、ffprobe 和 Pillow。对于 Pexels,先使用环境中的 PEXELS_API_KEY,再查找 skills/video-add-b-roll/.env 中的密钥。如果两处都缺失或为空,请停止并要求用户在该文件中添加 PEXELS_API_KEY=<key>,并在用户确认后重试。请用户通过本地 .env 文件提供密钥,绝不要通过聊天提供。绝不要将其放入或打印到命令参数、计划、URL、日志、审查材料或回复中。
/video-understand 是前置条件。先运行它,确保 B-Roll 使用经过验证的逐词转录稿和规范时间线。
开始前,确认该前置步骤已安装。如果未安装,请告知用户缺少此前置条件,并在处理媒体前停止。
从仓库根目录运行,并解析独立的项目根目录:
$RepoRoot = (Resolve-Path '.').Path
$ProjectRoot = (Resolve-Path 'path/to/video-project').Path
$BrollEnv = Join-Path $RepoRoot 'skills/video-add-b-roll/.env'
if ([string]::IsNullOrWhiteSpace($env:PEXELS_API_KEY) -and (Test-Path -LiteralPath $BrollEnv)) {
$PexelsKeyLine = Get-Content -LiteralPath $BrollEnv | Where-Object { $_ -match '^\s*PEXELS_API_KEY\s*=' } | Select-Object -Last 1
if ($PexelsKeyLine) { $env:PEXELS_API_KEY = ($PexelsKeyLine -split '=', 2)[1].Trim().Trim('"').Trim("'") }
}
$BrollScripts = Join-Path $RepoRoot 'skills/video-add-b-roll/scripts'
$ProjectLib = Join-Path $RepoRoot 'skills/video-understand/scripts'
$ReviewVideo = & python -c "import sys; from pathlib import Path; sys.path.insert(0,sys.argv[2]); import projectlib; root=Path(sys.argv[1]); project=projectlib.load_json(root/'work/project.json'); assert project.get('render',{}).get('status') == 'verified', 'current upstream delivery is not verified'; path=projectlib.resolve_project_path(root,project['render']['output']); assert path.is_file(), 'current upstream delivery is missing'; print(path)" $ProjectRoot $ProjectLib
if ($LASTEXITCODE -ne 0) { throw 'Complete the active upstream delivery before B-roll review.' }
$ReviewVideo = (Resolve-Path -LiteralPath $ReviewVideo).Path
使用以下规范输入,不要重新转录或重新分析:
work/project.jsonwork/timeline.jsonwork/understand/transcript.jsonwork/understand/understanding.json- 当前的节目时间审查视频,其画面包含已完成的剪辑和调色工作
$ReviewVideo 指的是现有且已验证的上游交付物,而不是需要臆造的文件名或新的 B-Roll 渲染文件。它必须已经与当前时间线的时长、尺寸和 FPS 相匹配。如果它不存在或已过时,请先完成上游剪辑/调色交付,然后解析并计算其哈希,再继续。
此操作始终依赖 understanding;如果目标序列启用了 cut 和 color-grade 操作,则也依赖这两项。将它们当前的正整数修订号复制到 based_on。启用调色时,记录调色计划和所选 LUT 的哈希;标准化时必须传入该确切的所选 LUT,并在应用前将其预先应用于每个选定的 B-Roll 镜头。
规范的序列顺序为:
cut -> color-grade -> b-roll -> captions -> content-cards -> motion-graphics
已注册的操作必须设置 changes_video_pixels: true、添加 b-roll 轨道,并保持时间线、几何参数和音频不变。broll_plan.register_operation() 会写入此约定;不要手动构建该操作。
持久文件和临时文件
work/b-roll/broll-plan.json # durable domain plan
work/b-roll/presentation-decision.json # durable Agent-chat route decision
work/b-roll/broll-interaction.json # durable applied receipt
work/b-roll/broll-selection.json # durable approved exact selection and consumed-page binding
work/b-roll/speaker-inset-analysis.json # durable scene/evidence packet
work/b-roll/speaker-inset-agent-input.json # durable Agent ROI decisions
work/b-roll/speaker-inset-preview.json # durable exact preview bindings
work/b-roll/speaker-inset-clearance.json # durable Agent obstruction check
work/b-roll/broll-revision-request-<UUID>.json # durable unapproved request bytes
work/b-roll/candidate-search.json # durable query and provider order
work/b-roll/candidate-analysis.json # durable deterministic evidence
work/b-roll/candidate-ranking.json # durable Agent ranking and Top 3
work/cache/b-roll/candidate-analysis/media/ # disposable analysis variants
work/cache/b-roll/candidate-analysis/frames/ # reproducible samples and crops
work/cache/b-roll/candidates/ # frozen acquired media
work/cache/b-roll/speaker-inset/ # reproducible evidence and previews
work/cache/b-roll/normalized/ # reproducible silent overlays
review/03-b-roll/candidate-analysis-<UUID>/ # immutable analysis packet
review/03-b-roll/candidate-analysis-<UUID>.md # analysis and baseline summary
review/03-b-roll/candidate-analysis-<UUID>/candidate-index.html
review/03-b-roll/b-roll-review-<UUID>.html # immutable candidate review
review/03-b-roll/b-roll-review.html # latest convenience alias
review/03-b-roll/stills/ # first/middle/last verification frames
review/03-b-roll/contact-sheet.jpg
review/03-b-roll/boundary-reel.mp4
review/03-b-roll/b-roll-summary.md
将计划和回执保存在 work/cache/ 之外。候选文件和标准化文件可重新生成,但必须作为与哈希绑定的输入处理。
工作流程
1. 确认当前依赖项
读取当前序列、操作修订号、时间线、转录稿、理解结果、当前调色计划和所选 LUT。确认审查视频与当前时间线的时长、尺寸和有理数 FPS 相匹配。将转录稿、时间线、审查视频和当前调色输入的哈希写入 input_hashes。
使用 broll_plan.active_dependencies(project) 推导确切的依赖项列表。时间线、转录稿、依赖项修订号、调色计划、LUT、审查视频、候选清单或已审查素材发生变化,都会导致下游工作过时;请刷新计划并重新审查,不要沿用旧回执。
2. 编写动态社交视频计划
手动编写 work/b-roll/broll-plan.json;脚本负责精确性,而非编辑判断。
对于每个拟议镜头:
- 按时间顺序选择一个正值、左闭右开的、不重叠的节目区间;
- 通过
work/timeline.json将其映射为精确的source_ranges; - 至少保留一个精确映射的转录词,并附上来源区间、节目区间和片段 ID;
- 说明具体的
editorial_reason和visual_intent; - 将
brief.search_context设为包含具体的topic、visual_direction和 1-12 个不重复关键词; - 将每个
semantic_role设为direct、supportive或atmospheric; - 编写两到三个分层的英文直述查询:一个
direct subject/action查询,一个defensible context/process查询;如果第三个查询有用,再加入一个theme-enhancing variant; - 从
planned开始,素材获取后转为candidates_ready;如果没有相关候选项,则使用skipped。
保持 brief.density 为 dynamic-social。计划覆盖范围应先完整扫描映射后的转录稿和时间线中的 A-roll,然后按时间顺序手动编写有效且不重叠的区间。将 0.40 到 0.70 视为软性目标。低于 0.40 时,再进行一轮检查,只添加或扩展有充分依据的区间。高于 0.70 时,在内部审查对 A-roll 的遮挡情况。绝不可为了达到目标而添加无关填充内容,或降低相关性、权利、质量或其他资格门槛。tech 或 entertainment 等宽泛主题词只能用于细化查询,绝不能取代每个镜头中候选素材与转录内容之间可见的对应关系。如果没有任何时刻适合加入 B-roll,获批的全跳过计划也是有效的空操作。
编写草稿时,不要添加 speaker_inset_style。候选素材获取完成后,由明确的 Agent-chat 呈现方式决策选择普通路线或说话者画中画路线。后者会自动安装严格的项目级圆角矩形样式:width_ratio: 0.39、灰色边框、宽高比、圆角半径、边距和字幕安全底部区域。预设和锚点不属于样式。Agent 检查所选的确切媒体后,记录 project_layout_strategy,并为每个镜头记录一个 layout_recommendation。绝不可引入人脸检测器、分割模型、跨镜头身份追踪器或猜测的 ROI。使用保持宽高比的覆盖缩放,将说话者 ROI 像素适配到窗口;绝不可将其拉伸至配置的宽高比。水平居中裁剪,并锚定到顶部,让完整的头部和面部优先于下半身的覆盖范围。
每次实质性编辑后都要验证草稿:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; plan=projectlib.load_json(root/'work/b-roll/broll-plan.json'); timeline=projectlib.load_json(root/'work/timeline.json'); transcript=projectlib.load_json(root/'work/understand/transcript.json'); project=projectlib.load_json(root/'work/project.json'); errors=broll_plan.validate_plan(plan,timeline,transcript,project=project,project_root=root,verify_files=True); print('\n'.join(errors) if errors else 'B-roll plan valid'); raise SystemExit(bool(errors))" $ProjectRoot $BrollScripts
3. 分析、排序并冻结候选项
候选项分析是进入 candidates_ready 之前的参考证据。它不会选择媒体、批准镜头、添加凭据或更改生命周期。为每个镜头保留现有的两到三个直述查询。
对于本地视频,填写真实的来源信息,并通过现有的获取路径导入:
python "$BrollScripts/pexels.py" import-local `
"$ProjectRoot/input/example-owned-footage.mp4" `
"$ProjectRoot/work/cache/b-roll/candidates/example-owned-footage.mp4" `
"$ProjectRoot/work/b-roll/example-local-provenance.json"
将返回的记录复制到镜头的 candidates 中。候选项分析读取该精确的冻结缓存文件;不会将其复制到其他提供方或分析系统。如果计划不应查询 Pexels,请使用 --local-only。
使用轮询方式合并查询结果,按提供方 ID 去重,并将每个镜头的提供方视频数量限制为最多八个,以收集 Pexels 结果。选择与时间线方向相符的画面方向:
$CandidateAnalysis = Join-Path $BrollScripts 'candidate_analysis.py'
python $CandidateAnalysis search `
$ProjectRoot `
"$ProjectRoot/work/b-roll/broll-plan.json" `
"$ProjectRoot/work/b-roll/candidate-search.json" `
--orientation portrait `
--per-page 8
仅分析本地素材时,添加 --local-only。搜索记录会保留每个直述查询、其原始提供方顺序、轮询顺序以及两个 Pexels 变体。分析变体是方向匹配且短边至少为 480 像素的最小文件;如果没有符合条件的文件,则使用最大的有效匹配文件。交付变体则始终使用分辨率最高的方向匹配文件。
仅下载并完整解码分析变体,以 10/30/50/70/90 百分比位置抽帧,并写入确定性的机器证据:
python $CandidateAnalysis analyze `
$ProjectRoot `
"$ProjectRoot/work/b-roll/broll-plan.json" `
"$ProjectRoot/work/b-roll/candidate-search.json" `
"$ProjectRoot/work/timeline.json" `
"$ProjectRoot/work/b-roll/candidate-analysis.json"
分析包含硬性检查、客观警告、采样帧与中心裁剪哈希、联系表、亮度/过曝/边缘/运动证据,以及重复证据。它会保留镜头内的精确拒绝规则和严格感知阈值,并新增项目范围内的精确身份、严格感知分组,以及不会抑制候选项的 possible_series 提示。硬性拒绝仅限于 reference/broll-rules.md 中的客观失败项。
检查确切的转录证据、五帧、裁剪模拟、警告和重复证据。按以下结构编写 work/cache/b-roll/candidate-ranking-input.json:
{
"schema_version": 1,
"analysis_sha256": "<canonical SHA-256 of candidate-analysis.json>",
"mode": "agent",
"actor": "<real Agent name>",
"timestamp": "<timezone-aware timestamp>",
"overall_rationale": "<non-empty rationale>",
"near_duplicate_groups": [{
"group_id": "<stable group id>",
"match_type": "same_series",
"actor": "<real Agent name>",
"timestamp": "<timezone-aware timestamp>",
"members": [
{"shot_id": "<shot id>", "candidate_id": "<candidate id>"},
{"shot_id": "<other shot id>", "candidate_id": "<other candidate id>"}
],
"rationale": "<specific visible repetition across the two transcript moments>"
}],
"shots": [{
"shot_id": "<shot id>",
"candidates": [{
"candidate_id": "<candidate id>",
"semantic_fit": 0,
"context_fit": 0,
"composition_fit": 0,
"style_fit": 0,
"text_logo_risk": "uncertain",
"avoid_violation": false,
"primary_subject_visible": true,
"near_duplicate_group": null,
"rationale": "<candidate-specific evidence>"
}]
}]
}
根据可见的冻结帧证据,使用 0 到 4 的整数拟合分数:0 表示不匹配或不可用,1 表示较弱,2 表示可以接受但存在顾虑,3 表示很强,4 表示异常出色。text_logo_risk 的取值为 0 到 4 或 uncertain;绝不可声称使用了 OCR。semantic_fit == 0 和 context_fit == 0 均保留为硬性资格排除保护。semantic_fit == 0 会因语义不匹配而拒绝候选项;context_fit == 0 会因缺乏依据的上下文而拒绝候选项。若候选项通过上下文门槛和其他独立门槛,semantic_fit 为 1 时仍可作为 weak_semantic_match 入选,但排名低于语义分数为 2–4 的匹配项。为每个可分析候选项评分,保留真实的 Agent 身份,排名时不要使用 mode: "human"。只有在比较冻结帧、转录证据、视觉意图、提供方身份、创作者和来源标题后,才能确认项目范围内的近重复分组。不要仅凭创作者身份确认。若未确认任何分组,则省略 near_duplicate_groups;为兼容较早的镜头内记录,仍接受每个候选项中的 near_duplicate_group 字段。
验证并应用固定的公开排名规则:
python $CandidateAnalysis rank `
$ProjectRoot `
"$ProjectRoot/work/b-roll/candidate-analysis.json" `
"$ProjectRoot/work/cache/b-roll/candidate-ranking-input.json" `
"$ProjectRoot/work/b-roll/candidate-ranking.json"
耐久排名结构请参阅 example-candidate-ranking.json。按语义优先的字典序为符合条件的候选项排名:依次比较 semantic_fit、context_fit、composition_fit + style_fit 的合计分数、较少的确定性警告,最后比较稳定的提供方和候选项 ID。将项目中完全相同的重复项和经 Agent 确认的近重复项分配给语义/上下文证据最强的镜头,然后让每个受影响的镜头从下一个独立且符合条件的候选项补位。possible_series 绝不会自动抑制候选项。候选列表最多包含三个候选项;少于三个也有效,若没有符合条件的结果,则必须使用 no_eligible_candidates。
仅在排名完成后,才获取完整的交付版本,并将其确切字节以及当前分析/排名哈希绑定到计划中:
python $CandidateAnalysis acquire `
$ProjectRoot `
"$ProjectRoot/work/b-roll/broll-plan.json" `
"$ProjectRoot/work/b-roll/candidate-analysis.json" `
"$ProjectRoot/work/b-roll/candidate-ranking.json"
获取命令只会将镜头状态变更为 candidates_ready 或 skipped。它不能选择候选项或批准计划。下载器负责处理分析版本和交付版本的 .part 文件恢复。绝不要手动提升、重命名或删除 .part 文件。
在审查确切候选项之前,发布不可变的分析数据包:
python $CandidateAnalysis publish `
$ProjectRoot `
"$ProjectRoot/work/b-roll/candidate-analysis.json" `
"$ProjectRoot/work/b-roll/candidate-ranking.json"
外部生成仍须使用 source_type: "external-generated" 执行 import-local,并提供完整且真实的来源信息。这仅用于导入,并不授权调用生成服务。
3a. 在 Agent 聊天中选择呈现方式
素材获取完成并生成 candidates_ready 或 skipped 镜头后,检查确切的 A-roll 和冻结的候选证据。在当前 Agent 聊天中,针对全屏普通 B-roll 或 speaker-inset,提供 Agent 的建议并说明具体理由。然后用自然语言询问用户明确选择哪种方式。不得根据原始草稿、候选项选择或沉默来推断这一选择。
使用 broll_plan.record_chat_presentation_decision() 记录回复。其输入必须保留实际的 user_response、Agent 的 presentation_mode 建议及理由、真实的用户身份、UUID 和时间戳、explicit_user_action: true,以及 rationale_source: "agent_chat_explicit_action"。此操作会写入哈希绑定的 work/b-roll/presentation-decision.json 回执,以及计划的 presentation 绑定。回执会绑定审阅视频、候选清单和审阅前计划的哈希。候选清单或审阅视频一旦更改,必须在发布审阅页面前重新通过聊天作出选择。候选项修订可以更改镜头时长和片段默认设置,同时保留原有的呈现方式绑定。
选择 ordinary 会移除任何说话人样式,并继续使用现有的单页精确候选项审阅流程。选择 speaker-inset 会安装默认的圆角矩形样式,同时保留第一页对确切的 B-roll 候选项、时间、片段顺序、速度和跳过决定的权威性。该页面会生成 submission_intent: "approve_selection",并设置 approval_scope: "b-roll-selection";应用该结果后,所选镜头会保持 composite_pending,原因仅在于新的说话人呈现方式仍需审阅。聊天回复用于选择呈现方式,不能替代任一网页上的明确审阅操作。
4. 发布并完成精确候选项审阅
将 input_hashes.review_video_sha256 设为当前实际审阅视频的 SHA-256,重新验证,然后确认当前的 Agent 聊天呈现方式回执,并发布不可变的本地审阅页面:
$ReviewPublication = & python "$BrollScripts/build_review_page.py" `
"$ProjectRoot/work/b-roll/broll-plan.json" `
"$ProjectRoot/review/03-b-roll" `
--video $ReviewVideo `
--timeline "$ProjectRoot/work/timeline.json" `
--transcript "$ProjectRoot/work/understand/transcript.json" `
--project-root "$ProjectRoot" | ConvertFrom-Json
Start-Process (Resolve-Path "$ProjectRoot/review/03-b-roll/b-roll-review.html")
按照 reference/broll-rules.md 应用审阅规则。该页面使用可读的映射转录作为 A-roll 的主要上下文。在负载中保留词语时间、片段映射、搜索查询和完整出处,同时将技术细节置于可折叠的说明中。可见时间值最多保留两位小数。插入起点/终点只能在显示的原始值上下两秒范围内按明确的 0.5 秒步长移动,然后将导出值吸附到有理数时间轴帧网格。对于一个镜头,从哈希绑定的 Top 3 中选择一至三个有序且不重复的候选项。对于新的多候选项选择,页面会按整数时间轴帧划分,并允许用户重新排列片段或调整相邻边界,同时保持镜头总范围不变。片段起点使用 0.1s 输入步长。普通的 Boundary 点击会移动到最接近 0.1s 对应的整数帧;在 Windows/Linux 上按住 Alt,或在 macOS 上按住 Option,则会精确移动一个时间轴帧。每个片段只能选择 0.5x、1x、1.5x 或 2x 播放速度。源片段终点为只读值,根据源片段起点、分配的节目帧数、帧时长和播放速率推导得出。当源片段覆盖范围无效时,页面会立即提供英文说明,包括时长不足量、最晚合法起点、可行速率以及可用的 Boundary/候选项修复方式。这些仅用于显示的诊断信息绝不会包含在审阅回执中。导出前必须显示可见的 Fit to A-roll 结果。当不存在合法适配方案时,Copy 和 Download JSON 会保持禁用;生成的 JSON 会以帧精度记录每个有序片段、范围和播放速率。
在 Agent 聊天中,于首个候选页面出现前选择路线。使用该页面控件所做的候选项、跳过、节目/素材时长、片段边界/顺序/速度、适配 A-roll 和 Ken Burns 编辑都不会触发修订。将 Modification notes 留空,并明确选择 Approve,以导出当前的精确配置:普通路线使用 submission_intent: approve,说话人嵌入路线使用 submission_intent: approve_selection。Python 会在直接应用前重新验证导出内容。
只有在页面控件无法表达所请求的更改时,才填写非空的自然语言 Modification notes。这会选择 Request changes,并导出 submission_intent: request_revision;空白的 Request changes 无效。只有这类自然语言请求才会进入修订、重建和新页面流程。重建后的提案会保留最初的 ordinary 或 speaker-inset 路线;不要再次要求用户选择 ordinary 或 speaker-inset。presentation-decision.json 回执保持不变;只会沿用其中现有的计划绑定,并附加明确的修订标记。候选项选择与说话人合成画面审批彼此独立。
Copy 是主要交接方式;在可用时,它会将完整 JSON 同时放入只读文本区域和剪贴板。Download JSON 会下载相同字节,以便可靠地在本地传递。两种方式都会保留相同的明确审批回执字节;在 Agent 验证并应用传递的 JSON 之前,都不会修改计划。
Download JSON 后,应绑定操作员实际选择的下载位置,而非假定文件位于审阅目录中:
$ReviewExport = (Resolve-Path -LiteralPath "<browser-download-directory>/b-roll-review-$($ReviewPublication.review_id).json").Path
对于人工模式,展示页面后停止。仅应用用户明确复制或下载的完整 JSON;验证前,必须将复制的 JSON 原封不动地保存到文件中。它必须包含 explicit_user_action: true。对于 Agent 模式,仅当用户明确委托该决定或要求自主完成时才继续。检查完全相同的素材,在 mode: "agent" 下记录真实的决定,注明实际的 Agent 操作者,并给出非空的决定理由。绝不能根据沉默或推断创建人工模式回执。
同时展示候选分析摘要和此完整候选页面,然后停止。在用户于之后的轮次明确复制、下载或批准精确的候选项选择之前,不要应用审阅、规范化、构建渲染计划或渲染交付内容。Agent 排名不等于用户批准。
应用有效的候选项导出后,将该 UUID 页面视为已使用的不可变证据。将其保留在磁盘上,但不得再次展示、重新打开其便捷别名,或要求用户确认相同的 B-roll 选择。只有导出无效或已过期、用户明确提出候选项 request_revision、哈希绑定的输入已更改,或用户明确要求时,才重新打开或重新发布候选项审阅。重试剪贴板/下载只是传递相同的回执,不属于再次进行编辑审批。
应用任何内容前,先检查 submission_intent。对于 request_revision,将精确的导出字节保存在 work/b-roll 下,根据旧的不可变页面验证这些字节,重建未经批准的提案,并重新分类时长证据;不要重新下载或重新采样:
$Revision = Get-Content -LiteralPath $ReviewExport -Raw -Encoding UTF8 | ConvertFrom-Json
if ($Revision.submission_intent -ne 'request_revision') { throw 'Expected request_revision.' }
$SavedRequest = Join-Path $ProjectRoot "work/b-roll/broll-revision-request-$($Revision.review_id).json"
[IO.File]::Copy($ReviewExport, $SavedRequest, $false)
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; plan=projectlib.load_json(root/'work/b-roll/broll-plan.json'); request=projectlib.load_json(sys.argv[3]); timeline=projectlib.load_json(root/'work/timeline.json'); transcript=projectlib.load_json(root/'work/understand/transcript.json'); errors=broll_plan.validate_revision_request(plan,request,timeline,transcript); print('\n'.join(errors) if errors else 'Revision request valid'); raise SystemExit(bool(errors))" $ProjectRoot $BrollScripts $SavedRequest
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; path=root/'work/b-roll/broll-plan.json'; plan=projectlib.load_json(path); request=projectlib.load_json(sys.argv[3]); timeline=projectlib.load_json(root/'work/timeline.json'); transcript=projectlib.load_json(root/'work/understand/transcript.json'); projectlib.write_json(path,broll_plan.rebuild_plan_from_revision(plan,request,timeline,transcript))" $ProjectRoot $BrollScripts $SavedRequest
python "$BrollScripts/candidate_analysis.py" reclassify `
$ProjectRoot `
"$ProjectRoot/work/b-roll/broll-plan.json" `
"$ProjectRoot/work/b-roll/candidate-analysis.json" `
"$ProjectRoot/work/timeline.json" `
"$ProjectRoot/work/b-roll/candidate-analysis.json"
重建后的提案会保留原始的 presentation 决定;若为 speaker-inset,还会保留其已验证的样式。候选项修订后,不要再次调用 record_chat_presentation_decision()。原始的 presentation-decision.json 回执保持不变,其候选清单和审阅视频绑定仍为必需项。
检查每一个 agent_rescore_required 标记。若为 true,请将修订后的转录证据与相同的冻结帧进行比较,并如实更新 Agent 评分;绝不可根据推断,将语义理由沿用到已变化的证据上。重新运行 rank 和 acquire,使计划绑定新的分析/排名哈希。SHA-256 相同的现有分析和交付媒体会被复用。使用 build_review_page.py 发布新的 UUID 审核页面,展示该页面,然后再次停止。绝不可将修订请求路由到 apply_review(),也不可将 revision_notes 转换为人工理由。
对于 ordinary 聊天决策,应用收到的单页审批 JSON,并持久绑定交互回执:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; path=root/'work/b-roll/broll-plan.json'; plan=projectlib.load_json(path); review=projectlib.load_json(sys.argv[3]); timeline=projectlib.load_json(root/'work/timeline.json'); transcript=projectlib.load_json(root/'work/understand/transcript.json'); updated=broll_plan.apply_review(plan,review,mode=sys.argv[4],actor=sys.argv[5],rationale=review['rationale'],interaction_path=root/'work/b-roll/broll-interaction.json',timeline=timeline,transcript=transcript,project_root=root); projectlib.write_json(path,updated)" $ProjectRoot $BrollScripts $ReviewExport human "Actual user name"
只有在用户明确导出后,才能使用 human 和实际的人类参与者。新的人工批准使用页面中的事实性 review_ui_explicit_action 理由;不得声称引用了用户撰写的理由。Agent 模式仍要求使用真实的 Agent 参与者和具体导出的 Agent 理由。
对于 speaker-inset 聊天决策,应用第一页中的权威选择:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; path=root/'work/b-roll/broll-plan.json'; plan=projectlib.load_json(path); selection=projectlib.load_json(sys.argv[3]); timeline=projectlib.load_json(root/'work/timeline.json'); transcript=projectlib.load_json(root/'work/understand/transcript.json'); updated=broll_plan.approve_selection(plan,selection,mode=sys.argv[4],actor=sys.argv[5],rationale=selection['rationale'],project_root=root,timeline=timeline,transcript=transcript); projectlib.write_json(path,updated)" $ProjectRoot $BrollScripts $ReviewExport human "Actual user name"
然后使用
speaker_inset.py 获取证据、Agent ROI、布局建议、精确锚点预览和间距信息;遵循
reference/broll-rules.md。Agent 必须评估 focused-panel、full-bleed-wash 和
corner-pip,选择项目的主预设,并为每个完整镜头固定一个预设和锚点。远景、全身、侧面或背面视图并不自动属于 occluded:首先结合时间连续性、舞台位置、服装、动作和转录上下文,判断当前说话者是否已确认。对于每个已确认的子镜头,尝试使用稳定的全时长 ROI 关键帧,并将完整头部、下巴和适当头部留白作为硬性约束;手势、身体和讲台上下文为次要考虑。放弃前,应将 ROI 扩展至稳定的说话区域;绝不可仅为让人物显得更大而裁掉头部。对于已确认的说话者,Agent 输入仍须使用 enabled,以便在任何质量回退方案启用前生成精确预览。corner-pip 仅支持镜头级的 top-left 和 top-right 锚点。仅发布绑定新哈希的 review_stage: composite 页面。在该页面中,将已批准的 B-roll 作为只读、默认折叠的上下文展示;不得呈现候选复选框、跳过/时长/速度控件,也不得在回执中输出候选 shots。用户的合成决策仅涵盖 ROI、布局、间距信息、连续性、样式和精确的合成像素。Agent 的建议仅供参考;展示精确的合成页面,然后停止并等待用户批准。
候选修订会创建新的候选 UUID 页面和选择回执,然后再重建说话者相关产物,同时保留首次选定的 ordinary 或 speaker-inset 路由。仅合成内容的修订会创建新的合成 UUID 页面,同时保留已批准的 selection_sha256;不得静默更改 B-roll。合成获批后,根据已批准的选择推导候选决策,并转换 composite_pending 镜头,无需再次询问相同的内容决策。
在接受 ambiguous 之前,请在该子镜头内请求密集的补充证据,并重新构建分析哈希。
在审核阶段,须在精确最终尺寸的预览中检查入场、中段、出场以及经评估的运动风险帧;如果没有额外的运动风险点,请注明 not_applicable 并说明原因。使用 build_pixel_budget() 记录实际封面裁切、嵌入画面像素、缩放比例、最大缩放比例,以及 low(<=1.5x)、medium(>1.5x 且 <=3.0x)或 high(>3.0x)警告。像素风险仅作为证据,绝不改变 display_mode。每个显示的子镜头都必须满足 subject_legibility: pass。若已确认的说话者在精确预览中始终无法辨认,则只能在审核阶段将其设为 pure_broll,并设定 subject_legibility: fail 和 clearance_status: subject_illegible;保留其 ROI/关键帧和与预览绑定的证据以供审计。仅对 B-roll 遮挡使用 no_safe_position,并设置 subject_legibility: not_applicable。如果只有持续的一段内容无法辨认,请在合法帧边界拆分子镜头;不要因一两帧模糊画面而停用整个镜头。记录镜头级连续性决策。若启用片段短于 1.5 秒,且后面跟着更长的纯 B-roll 片段,则将其视为 short_flash;扩展经独立确认的 ROI、停用整个镜头的嵌入画面,或记录具体的有意转场。绝不要放宽已确认说话者规则来掩盖连续性问题。
5. 规范化已批准的选段
启用色彩分级时,传入分级计划中选定的确切 .cube 路径:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import normalize_broll; normalize_broll.normalize_plan(root/'work/b-roll/broll-plan.json',root/'work/timeline.json',root,lut=Path(sys.argv[3]).resolve())" $ProjectRoot $BrollScripts "$ProjectRoot/final/selected-color-look.cube"
未启用色彩分级时,使用 lut=None 调用同一 API。色彩分级启用时,绝不省略 LUT,也绝不应用未选定的风格。对于未启用色彩分级的嵌入画面,请显式传入与哈希绑定的确切审阅视频:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import normalize_broll; normalize_broll.normalize_plan(root/'work/b-roll/broll-plan.json',root/'work/timeline.json',root,lut=None,review_video=Path(sys.argv[3]).resolve())" $ProjectRoot $BrollScripts $ReviewVideo
启用色彩分级且启用嵌入画面时,请传入两个确切输入:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import normalize_broll; normalize_broll.normalize_plan(root/'work/b-roll/broll-plan.json',root/'work/timeline.json',root,lut=Path(sys.argv[3]).resolve(),review_video=Path(sys.argv[4]).resolve())" $ProjectRoot $BrollScripts "$ProjectRoot/final/selected-color-look.cube" $ReviewVideo
对于每个规范化的一至三段视频选段,规范化器会直接读取冻结的原始候选素材,并在一个滤镜图和一次编码器调用中完成修剪、播放速率、缩放/裁切、SAR、有理数 FPS、精确帧分配、可选 LUT 和硬拼接。单段选段会直接映射其处理链。不要创建、读取或恢复每段的 MP4 文件或旁文件。
每个新的 B-roll 交付中间文件都使用固定的 libx264 / CRF 18 / preset medium / yuv420p / MP4 / +faststart / no audio 配置,并记录完整的带版本配置以及源片段和分级绑定信息。这适用于普通的 broll-NNN.mp4、说话者的 broll-NNN-base.mp4,以及最终的说话者合成文件 broll-NNN.mp4。候选素材/上下文/锚点预览、边界片段和共享最终渲染器继续沿用现有编码行为。基于旧组件的记录仍可只读兼容,但不得报告为直接源素材处理,也不得升级为固定配置。
每个资源都先写入 .part.mp4,再检查探测结果、完整解码、几何尺寸、FPS、时长、静音和 SHA-256,随后使用 os.replace 发布。规范计划另行写入 .part.json;不得声称这构成跨文件事务。失败时,将当前镜头保留为 selected,移除本次尝试产生的部分文件和新发布但未被镜头引用的资源,并保留已完成的镜头。从原始候选素材完整重跑失败的镜头;不要恢复片段状态。
6. 验证并预注册
针对同一段当前节目时间的审核视频运行验证器:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import check_broll; check_broll.verify_plan(root/'work/b-roll/broll-plan.json',root/'work/timeline.json',root,Path(sys.argv[3]))" $ProjectRoot $BrollScripts $ReviewVideo
验证器会重新验证哈希和回执,探测并解码标准化片段,将选中的镜头标记为
verified,并发布首帧/中间帧/末帧静帧、联系表、简短的边界片段,以及不可变的机器摘要。摘要会特意保留 Manual review status: pending.。使用 reference/broll-rules.md 检查适用的产物。如果任一项检查失败,请修复计划或选择,并重新执行审核、标准化和验证。不要直接修改受哈希保护的验证产物。
在构建交付内容之前,根据已验证的计划进行预注册。选中的镜头会创建一个 approved 操作,其检查状态仍为待定,并以机器摘要为依据;渲染器会使用此操作。若计划中的镜头全部跳过,则移除任何过期的 B-roll 操作,不保留空的活动操作:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; project_path=root/'work/project.json'; project=projectlib.load_json(project_path); plan=projectlib.load_json(root/'work/b-roll/broll-plan.json'); projectlib.write_json(project_path,broll_plan.register_operation(project,plan))" $ProjectRoot $BrollScripts
7. 构建交付内容,完成视觉审核并最终确认
编译已批准的活动操作,并渲染一次交付内容:
python "$RepoRoot/skills/video-understand/scripts/build_render_plan.py" $ProjectRoot
python "$RepoRoot/skills/video-understand/scripts/render_project.py" `
"$ProjectRoot/work/render/render-plan.json"
打开并检查最终交付内容、联系表、边界片段,以及具有代表性的首帧/中间帧/末帧静帧:
Start-Process "$ProjectRoot/final/final-video.mp4"
$ContactSheet = "$ProjectRoot/review/03-b-roll/contact-sheet.jpg"
$BoundaryReel = "$ProjectRoot/review/03-b-roll/boundary-reel.mp4"
$Stills = "$ProjectRoot/review/03-b-roll/stills"
if (Test-Path -LiteralPath $ContactSheet) { Start-Process $ContactSheet }
if (Test-Path -LiteralPath $BoundaryReel) { Start-Process $BoundaryReel }
if (Test-Path -LiteralPath $Stills) { Get-ChildItem $Stills -File | Select-Object -First 3 | ForEach-Object { Start-Process $_.FullName } }
Get-Content "$ProjectRoot/review/03-b-roll/b-roll-summary.md"
实际检查后,创建由 Agent 或人工编写的 JSON 导出,其中包含活动的 review_id、不含 visual_review 的已验证计划的规范 SHA-256、带时区的 timestamp、mode、真实的 actor、非空的 rationale,以及且仅包含以下布尔结果:semantic_fit、unwanted_logos_or_text、jump_cuts、entry_exit_boundaries 和 grade_match。启用画中画时,还必须包含 speaker_layout_fidelity、speaker_legibility 和 broll_focal_clearance。所有适用的结果都必须为 true。仅在用户明确执行操作后,才使用 mode: "human" 和 explicit_user_action: true;否则使用委托模式 mode: "agent"。绝不可推断或伪造人工审核通过。
在最终注册前完成最终视觉审核。这会写入持久回执和已完成的报告,并通过 SHA-256 绑定计划 UUID/哈希、验证器静帧、联系表、边界片段、待定的机器摘要以及最终视频:
$VisualReviewExport = "$ProjectRoot/work/b-roll/b-roll-visual-review-export.json"
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]).resolve(); sys.path.insert(0,sys.argv[2]); import check_broll,projectlib; check_broll.complete_visual_review(root/'work/b-roll/broll-plan.json',root,projectlib.load_json(sys.argv[3]),root/'final/final-video.mp4')" $ProjectRoot $BrollScripts $VisualReviewExport
再次运行注册。这会将确切的预注册操作原地最终确认为 verified,将 operation.check.report 指向 b-roll-visual-review.md,并保留其修订版本、渲染贡献、序列位置以及已验证的交付状态。无需再次渲染:
python -c "import sys; from pathlib import Path; root=Path(sys.argv[1]); sys.path.insert(0,sys.argv[2]); import broll_plan,projectlib; project_path=root/'work/project.json'; project=projectlib.load_json(project_path); plan=projectlib.load_json(root/'work/b-roll/broll-plan.json'); projectlib.write_json(project_path,broll_plan.register_operation(project,plan))" $ProjectRoot $BrollScripts
对于全部跳过的无操作情况,只需要摘要和最终交付内容;不会生成联系表、边界片段和静帧。
对于选用了 B-roll 的情况,只有在已完成视觉审核回执、最终像素检查和注册验证均通过后,才能完成。仅仅成功运行渲染或机器验证命令并不等于自我检查。