如何用数字给AI视频质检?Anything2Explainer量化质量指标frame_metrics深度解析
如何用数字给AI视频质检?Anything2Explainer量化质量指标frame_metrics深度解析
Anything2Explainer 是一款把任意主题变成黑底动效解说视频的 AI 技能,而它的 AI 视频质检核心正是 frame_metrics.py:渲染完成后,脚本逐镜头把画面变成一组数字——主体高度、柔光面积、紫色碎片数、静止帧数——替代"看着还行"的主观判断。下面带你看懂这套量化质量指标是怎么工作的。
为什么质检要靠数字?
这个项目的完整流程是:调研 → 解说词 → TTS 配音 → 分镜表 → 多个 AI agent 并行写 Remotion 镜头代码 → 渲染 → 质检修复(见 SKILL.md)。
质检环节一开始只靠 QC agent "肉眼"查缺陷:文字遮挡、拼写错误、衔接跳变。结果在 reference/lessons.md 里留下一条扎心教训:
QC 只查缺陷不查"空 / 小 / 暗":四轮 QC 全过,画面还是小而暗。
主观规则("主体要够大")传不进审美判断。修复办法就是量化:把"画多大、谁发光"写成阈值,让脚本先跑一遍,给每个镜头打上 高 / 中 / 低 三档标记,QC agent 再带着标记去看帧确认。这就是 frame_metrics.py 的由来。
frame_metrics 是什么、在哪跑
脚本位于 template/scripts/frame_metrics.py,随模板拷贝到每个视频项目后运行。依赖只有 numpy、pillow、scipy(其中 scipy 在仓库里只被这个脚本使用)。
基本用法:
python3 scripts/frame_metrics.py \
--frames fin_frames \
--storyboard 分镜表.md \
--out qc/frame_metrics_v1.md
- 它从 分镜表.md 里自动解析
| SCxx | 帧区间 |形式的镜头列表,默认每 4 帧抽样一帧(--step) - 也可以手动指定
--shots SC11:1627-1806,SC12:1852-1965 - 有流程轨的镜头可传
--rail-top 175抬高内容区上界 - 输出是一张 Markdown 表 + 全片标记合计(高 N / 中 N / 低 N),直接并入 QC 报告
统计只发生在"内容区"(y 100–621,排除顶部 HUD 和底部字幕带),亮度计算用 int32 防溢出——这些细节都写在脚本注释里。
六大量化指标:脚本到底量了什么
指标一:主体尺度(hero 尺寸)
每帧先找出内容区里最亮的连通物体(亮度 >120),然后做几件事:
- 用 13×41 的结构元膨胀,把一行大字里字距 ≤40px 的字并成一个物体,但不会把间距 ≥50px 的胶囊行并到一起
- 星点、碎屑只有 2–16px 墨迹,直接按"墨迹 <30px"排除
- 宽而不细的物体(一行大字、宽卡)按
min(宽, 4×高) / 2.5折算高度,避免一根细线被当成大主体
最终每个镜头输出主体尺度的中位数 / 最小值。对照 reference/composition-and-light.md 的三档尺寸规则:主角 ≥170px、配角 60–110px、标签 22–30px。
下面这张就是典型反例:一根 6px 的时间轴 + 34px 小字在空屏上停 100 帧,主体尺度指标会直接给它打标记:
指标二:空场检测(还懂"光效帧"豁免)
"空场"的定义是:没有 ≥110px 的主体,且没有大面积光活动,最长连续帧数 >45 帧就触发标记。
关键在第二个条件:扫光、舞台光线、光环这类高光时刻,主角还没登场,但全内容区柔光面积 ≥10000px²,脚本会把这类帧豁免,不算空场,也不计入主体中位数——否则高光时刻会被误判成"主角缺席"。
指标三:柔光面积(主角有没有光)
"柔光"的像素判据:饱和度 >0.25 且亮度在 10–110 之间(排除过曝与纯黑)。脚本统计两处:
- 全区柔光:判断"这一帧是不是光效帧"(上面的豁免条件就靠它)
- 主角区柔光:以最大主体的包围盒外扩 30px 为区域,取其中最大连通斑的面积
主角区柔光中位数 <800px² → 标记"低:主角无光"。正例长这样:150px 的主角大字配双层紫光,光牢牢打在主角身上:
还有一个容易被忽略的细节:如果项目用点阵波幕底(config.bg='dots',实现见 template/src/common/DotFieldBg.tsx),脚本会按与幕底组件完全相同的一组网格常量(设计坐标 960×540、步距 36、起点 24,18)把背景点阵从统计里抠掉——否则波前 40–60 个亮点会被数成背景碎屑。点阵底色 #0b0c11 本身略带蓝,也会整屏落进"柔光"判据,所以 dots 模式下柔光亮度下限从 10 抬到 22(实测底色+噪点 ≤18)。这段逻辑见 frame_metrics.py。
指标四:紫色碎片指数
"紫色撒在配角上"是黑底紫调风格最常见的审美崩坏。脚本提取实心紫像素(蓝>红>绿、饱和度 >0.45、亮度 >45),把一行字的逐字硬投影并成一块后,数 ≥80px 的独立色块。中位数 ≥8 块 → 标记"低:紫色碎片≥8",提示紫色光应该集中给主角,而不是满屏撒。
指标五:背景碎屑
一帧内 <60px 的散落小图形(不含星点/幕底点阵)≥10 个 → 标记"中:背景碎屑"。规则来源是"表现'多'用矩阵,不用碎屑"——整齐的点云阵列也可能触发这条,属于设计允许,QC 看帧确认即可。
指标六:最长静止帧
把每帧缩到 320×180 灰度图,算相邻帧平均差值。连续 >45 帧差值 <0.15 → 标记"低:静止 N 帧"。它抓的是"整句解说配的画面几乎不动"这类节奏缺陷。
标记怎么生成:阈值速查表
所有指标汇总成每镜头一行,阈值定义在 composition-and-light.md §6:
| 指标 | 判定条件 | 标记 |
|---|---|---|
| 空场 | 主体 <110px 且无大面积光,持续 >45 帧 | 中 |
| 空场 | 同上但期间主体中位 <80px | 高 |
| 主体尺度 | 中位数 <170px | 低 |
| 主角区柔光 | 中位数 <800px² | 低(主角无光) |
| 紫色碎片 | 中位数 ≥8 块 | 低 |
| 背景碎屑 | 散落小图形 ≥10 个 | 中 |
| 静止帧 | 连续 >45 帧 | 低 |
标记生成逻辑见 frame_metrics.py,输出表头与合计行紧随其后。
它在质检流程里的位置
frame_metrics 不是孤立工具,而是贯穿三个阶段(见 SKILL.md 阶段 6–7 与 reference/prompts.md):
- 渲染后:主会话先自己跑一遍,"空场 / 主角无光 / 碎屑标记先于 QC 派修"
- QC agent 开工前:agent-qc-rules.md 第 8 条要求"先跑 frame_metrics,把本章镜头的标记逐条并入报告并看帧确认"——数字负责发现问题,眼睛负责确认问题(因为整齐点阵会误触发碎屑)
- 终检复核:v2/v3 重渲后再跑一次,确认空场/无光/碎屑指标没有回归
样片的完整质检报告可以在 examples/rag/qc/ 看到,比如 qc_v1_C1.md 里连"标题 63% 亮度时被硬切消失"这种问题都给出了逐帧亮度读数。
实测对比:数字揭示了多大的差距
这套指标的价值,看 composition-and-light.md 开头的对照表最直观——两部动效数量、节奏、柔光总面积几乎相同的片子:
| 指标 | 广告竞价 | RAG 样片 |
|---|---|---|
| 最大物体高度中位数 | 172px | 219px |
| 最大物体 <110px 持续 ≥1.5s 的时长占比 | 29% | 12% |
"看起来差不多"的两部片子,数字一拉,差距全在主体尺寸和空场时长上。对应的修法也不是加动效,而是给细小题材配主角——比如时间轴题材直接上一个大数字:
完整的 6 组正反例帧对照(主角尺寸、高光时刻编排、大数字、背景碎屑等)见 examples/contrast/README.md,样片全片资料在 examples/rag/README.md。
上手清单:跑通一次量化质检
- 渲染完成,拿到逐帧图
fin_frames/f_%04d.jpg(1 起编) - 确认 分镜表.md 里每行有
| SCxx | a–b |帧区间 - 执行
python3 scripts/frame_metrics.py --frames fin_frames --storyboard 分镜表.md --out qc/frame_metrics_v1.md - 先看标记合计行:高 >0 必须修;再逐镜头对照阈值表
- 把报告交给 QC agent(或直接按 agent-qc-rules.md 自查),可疑标记逐帧确认后再派修
小结:Anything2Explainer 用 frame_metrics.py 把"好画面"拆成了 6 个可计算的数字——主体够不够大、光打没打在主角身上、空场多长、紫色撒没撒、背景干不干净、画面动不动。这正是 AI 视频质检的通用思路:先量化,再肉眼确认,让审美标准变成可复现的阈值。
更多推荐





所有评论(0)