风格蒸馏 是做什么的?
本独立技能的实现位于 scripts/ 目录下;后续的生成式或本地剪辑编辑请使用 taste-application 技能。每个命名流派应保留在各自独立的包中。来自 Flash Ethereal 的测量结果不得静默地复用于 Fluid Sketch 或 3D Cyber Glitch。测量到的零值是有效数据;请将其与字段缺失区分开来。
本地依赖项位于 scripts/requirements.txt 中。如果使用独立授权的提供商工作,还需要 scripts/requirements-live.txt、凭证以及显式设置 TASTE_FORGE_ALLOW_LIVE=1。--dry-run 模式不会读取凭证或提交任务。切勿仅凭本地端点名称推断工作流已被保存;应使用实际的提供商端工作流或任务证据进行验证。
将参考视频转换为风格包:一个包含测量结果和资产的文件夹,供后续阶段确定性使用。
何时激活
- “捕捉这些片段的风格” / “提炼氛围” / “使其可重复”
- 用户拥有参考素材并希望获得 LUT、色彩分级或匹配的节奏
- 构建按流派划分的外观库
- 任何本应回答“用提示词描述风格”的请求
核心发现
提示词无法实现精准分级。测量可以。
在真实素材上测量:三次付费生成,逐步加强色彩方向指导,中间调 a* 从 +1.9 → +2.8 → +0.3,而目标是 +24.9;对比度始终未超过 ~19,而目标是 34.7。将测量包应用到同一素材上,一次确定性操作即达到色度 MAE 1.88、对比度 33.7,且无需额外费用。
因此分工明确:模型提供内容、运动和光照结构;风格包提供外观。 生成提示词中的色彩词语比无用更糟糕——它们既消耗费用,又将渲染推向 LUT 所期望的基准中性之外。在提示词中明确说明:“色彩:无。渲染中性。分级后续应用。”
风格包内容
stylepacks/<流派>/
grade.json 测量的色彩统计(见下文)
cadence.json 每个检测到的镜头边界及衍生的分布
look.cube 33^3 LUT,可直接拖入 Resolve 作为节点 LUT
spec.json 基于测量的 VLM 描述
grounding.txt 提供给 VLM 的测量事实
stills/ 最长镜头的全分辨率帧(条件图像)
plates/ 提取到黑色背景上的屏幕混合叠加元素
props/ 铸造的 GLB 网格
pack.json 清单
运行方法
python mint.py --genre <名称> --refs a.mov b.mov c.mov # 离线,无需 API 密钥
python distill.py --genre <名称> # 一次 VLM 调用
mint.py 是纯数值分析——无网络、无密钥、确定性执行,因此风格包可以重新生成而无需备份。
重要的测量指标
按亮度区域测量色度,而非全局
色彩特征通常只存在于一个亮度带中。全局的 a*/b* 偏移在数学上无法表示分色调色。在亮度区域内部测量色度(L* 边界 [0,15,35,55,75,100])。
一个真实的色彩特征:在 L*25 处为紫色(a* +24.9,b* −17.5),两端接近中性。仅报告最暗和最亮的区域会将其误判为“均匀偏色”——务必打印整个曲线。
使用中位数 + MAD,而非均值 + 标准差
真实参考集中的色度呈强烈右偏分布。在某段测量素材上,中间调色度均值为 36.9,而中位数为 17.5,因此基于均值的 LUT 将色彩强度放大了约 3 倍。
对比度取 std(L*),而非白色减黑色
白-黑范围在几乎所有真实素材上约为 100,不具备区分度。
背景占比作为首要统计量
记录亮度低于 L*10 的像素占比。没有任何分布矩能捕捉到这一点:一个片段可以具有正确的均值、标准差和色度,但其暗部已被提升为灰色。这正是某次分级在 MAE 1.88 / 对比度 33.7 的评分下,实际画面却呈现出泥泞紫色混乱的原因。
测量前屏蔽界面元素
屏幕录制的参考素材包含静态元素——邮箱黑边、状态栏、点赞图标、字幕文字。所有这些都会像风格数据一样混入统计结果:黑边增大了阴影权重,红色爱心使 a* 偏向品红。时间方差可以干净地分离它们——画面在动,界面不动——因此无需手动裁剪。在真实素材上,此方法可保留约 65% 的像素。
剪辑检测需要自适应阈值
正确的内容检测阈值因素材而异:高对比度的动作片段在阈值 30 时切割清晰,而氛围感较强的片段则将其镜头切换隐藏在该阈值之下。对阈值进行降序扫描,取能恢复最敏感设置发现镜头数 ≥90% 的最高阈值——这样倾向于真实切换而非噪声。拒绝导致荒谬切割率(>100/分钟)的阈值;连续的摄像机运动会逐帧触发检测器。
在一次解码过程中使用共享的 StatsManager 完成整个扫描。朴素版本为每个阈值重复解码,在 60fps 源素材上,时间差别是秒与分钟之差。
叠加层:资产,而非截图
静态帧是整个画面——合成一个静态帧只是叠放另一张图片。叠加层则是将参考素材的图形元素(眩光、条纹、故障碎片)提取到黑色背景上,从而无需键控即可实现屏幕混合。
两个陷阱,均在真实素材中出现:
- 绝对阈值失败。 在明亮参考中,
L>55 AND chroma>12的选择会覆盖约 90% 的画面,“叠加层”变成了整个图片——包括可识别的面部。应使用百分位数(约顶部的 3%)进行选择,并拒绝任何覆盖超过约 22% 画面的叠加层。 - 按分离度排序,而非亮度。 “明亮饱和像素占比”会将过曝的片段排在最前面,而将包含一个强烈光晕的黑片段——实际的特征——排在末尾。评分标准为
p99.5(能量) / 中位数(能量)。
同时,需要在评分前进行屏蔽:烧录的字幕明亮、饱和且高对比度,因此未屏蔽的运行会产生一个完美的他人标题卡叠加层。
为 VLM 提供依据
在要求描述之前,将测量结果输入系统提示词。若无依据,VLM 会将具有 +24.9 a* 偏色的素材报告为“无可见色彩分级,中性”。有了依据,VLM 才能正确描述偏色并独立推断出次级强调色。
禁止使用模棱两可的词语(多样、混合、动态、一些、经常、中性、或)——模型无法渲染“多样光照”。在代码中强制执行禁令,而不仅仅是在提示词中: 大约每三次运行就会出现一次违规。按字段重新询问,在 N 次尝试后保留模棱两可程度最低的答案,而非直接失败。
值得向用户说明的注意事项:一旦规格基于测量结果,它就不再是测量结果的独立检查。
LUT 烘焙陷阱
- LUT 只能编码逐像素的 RGB 函数。任何依赖于分布的函数(直方图匹配、百分位数锚点)必须在烘焙之前简化为常数,否则它会静默地测量均匀 LUT 网格,而非素材本身。
cv2.cvtColor(LAB2RGB)内部会进行钳制,因此使用它的超色域测试会报告 0%。手动将 Lab 转换为线性 sRGB;真实测量显示 83.3% 超出色域。- 使用偏移传递色度,而非仿射变换。仿射变换除以源 σ 会导致过冲——在真实素材上,它将 b* 翻转为 +11.6,而目标是 −17.5。使用偏移后,MAE 从 6.23 降至 2.13。
- 色域压缩导致运行时间增加 3.8 倍,而 MAE 相同。应将其设为可选。
反模式
| 不要 | 原因 |
|---|---|
| 根据合成测试素材调优 | 一个项目上导致了四个完全错误的结论;真实素材推翻了所有结论 |
| 仅信任 MAE | MAE 1.88 在一个明显有缺陷的画面上看起来是成功的 |
| 对色度使用均值/标准差 | 右偏分布;强度放大约 3 倍 |
| 仅比较端点亮度区域 | 两端在构造上都是接近中性的 |
| 描述外观后停止 | 规格用于内容和结构;风格包用于色彩 |
交接
风格包是接口。一旦创建,使用 taste-application 技能进行生成和组装,或直接将 look.cube 交给调色师。
配套代码
本技能中的 scripts/ 目录是实际可用的实现,而非伪代码。它不包含特定项目的假设:将其指向任何参考视频,它都会生成一个风格包。
pip install -r scripts/requirements.txt
export FAL_KEY=... # 仅在需要调用 fal 的阶段需要
每个网络调用在 TASTE_FORGE_DRY_RUN=1 或 --dry-run 下都会被存根,因此可以在不花费成本的情况下检查计划、提示词、轨道布局和清单。