轻剪云 · 短视频内容生产平台 / 混剪视频(重构)
老链路兼容与灰度回退
混剪重构的安全边界:老数据不丢、老行为不漂移、随时能退回
本篇是主篇《批量混剪功能重构 · PRD》的安全边界部分,单独成篇:主篇讲这个产品是什么,本篇讲怎么改它才不会改崩。基于真实项目脱敏重写,产品名与场景为虚构,兼容口径、改造顺序、回退判定与回归基线均来自真实交付。
目录
- 老数据兼容:只读映射
- 老行为等价:契约翻译层
- 数据只加不改
- 改造顺序与依赖铁律
- 灰度与回退
- 实践中暴露的判定分叉
- 状态与异常
三条底线
| 对象 | 要求 | 具体含义 |
| 老数据 | 只读映射 | 老表零改动,只产生新记录 |
| 老行为 | 等价翻译 | 出片参数只允许偏差 0 |
| 老入口 | 置灰即开关 | 代码与路由全程保留 |
一、老数据兼容:只读映射
老脚本与新脚本的结构并不一致(存在两代结构并存、台词多句、画面参考描述独立存放等情况)。映射规则如下。
| 老结构 | 映射结果 | 说明 |
| 一个段落/镜头 | 一个新镜头组 | 段落数 = 镜头组数 |
| 段落的台词(可能多句) | 全量进入该组口播池,首句居首 | 不截断、不拼接,保证"第一条口播"仍是用户原来写的第一句 |
| 画面参考描述 | 该组的画面描述 | 语义一致,直迁不丢 |
| 无台词的段落 | 口播池为空,标记"待补口播" | 由步骤二的 AI 生成兜底补写,属正常中间态 |
| 老素材绑定关系 | 迁入对应组的素材池 | 能迁则迁;迁不了留空,由用户在新流程里重新分配 |
| 无法归类到新结构的字段 | 原样整体存入保留区 | 见下方四条边界 |
保留区的四条边界(硬约束)
- 保留区只可出现在老数据映射的产物中,逐字节原样保存老结构对象;新建脚本不允许出现保留区。
- 除留档与页面上下文读取外,达标校验、渲染内核、生成判定一律不得依据保留区做任何判断——它是保留区,不是契约字段。
- 契约校验器需放行保留区字段(豁免必填/类型/枚举校验),否则老数据一进新流程就被判为非法。
- 缩略图类展示字段不迁入素材池,素材池只存素材 id,缩略图由页面按 id 反查。
原则:映射只产生新记录,绝不修改老表。任何一处与预期结构不符,停下回报字段差异,禁止自行假设或发明第三种结构。
二、老行为等价:契约翻译层
改造后只有一个渲染内核。旧流程(经典混剪、分镜剪辑)的提交请求,在进内核之前先过一层翻译:
旧请求 → 翻译层 → 新契约请求 + "默认参数等价体"
↓
同一个渲染内核
| 规则 | 说明 | 为什么重要 |
| 默认参数等价体 | 旧流程在旧剪辑配置里的可覆盖项 → 新契约的配置项;其余全部进入策略内部作为锁定项 | 把"线上默认行为"固化成一份可对照的快照 |
| 产物即基线 | 翻译层的输出就是"线上默认行为的快照",用它锁死旧行为,此后改内核以它为对照 | 没有基线,"改没改崩"就没有判据 |
| 偏差要求 | 旧入口在改造前后的出片,关键参数与成片结构只允许偏差 0 | 这是回退之外最重要的保险 |
| 锁定项不参与随机 | 翻译产物中被锁定的内容整包透传,不参与批量随机实例化 | 防止旧流程被批量逻辑意外改写 |
三、数据只加不改
| 改动 | 类型 | 约束 |
| 批次表、任务表、个人偏好表 | 新增表 | 只加不改 |
| 作品表「批次 id」列 | 新增列(可空 + 索引) | 历史记录保持空 = 未分组;仅由批量渲染产物回填 |
| 迁移脚本 | 幂等执行 | 老数据零改动,上线后校验老作品可正常读 |
| 历史作品 | 不触碰 | 播放/下载/删除/详情行为与改造前完全一致 |
四、改造顺序与依赖铁律
数据契约 → 存储模型 → 渲染内核 → 素材组件 → 流程页面 → 能力增强 → 聚合视图 → 数值打磨
每层只依赖已冻结的上一层,不回头改。下表说明跳序会发生什么。
| 违序动作 | 会产生的矛盾 | 所以必须先做 |
| 先做页面 | 页面字段没有契约可对,后端按页面猜字段,两端命名与结构打架 | 契约冻结 + 存储接口就绪 |
| 内核先于存储模型 | 任务进度与批次无处落库,批量只能内存态,重启或中断全丢 | 建表(含失败/中断状态机) |
| 动内核前不做等价翻译 | 旧流程出片行为漂移,"改崩"无法回退 | 翻译层 + 回归基线 |
| 先做素材槽再定数据归属 | 素材按组归属的存储规则是后定的,UI 重写 | 契约先行定义素材归属,再做组件 |
| 口播扩充先于契约的数组结构 | 口播池没有数组结构可追加 | 契约先定义口播池 |
| 聚合视图先于存储模型 | 没有批次数据可聚合 | 建表 + 真实批次数据 |
| 现在写死策略数值 | 无样片观感依据,数值必返工 | 延后,待样片评审后再定 |
各阶段放行条件
| 阶段 | 放行条件(前一阶段通过才进入下一阶段) |
| 后端内核 | 直接调接口:2 组脚本(每组口播 ≥1、素材 ≥3 段)+ N=3 + 标准策略 → 出 3 条互不相同的可播放成片;批次进度正确;口播完整收尾;同时旧入口各出一片与改造前对比无差异 |
| 页面与素材 | 端到端:N=2、T=15s → 描述生成 3 组 → 每组口播 ≥1 → 每组素材 ≥3 段 → 出片;字幕配音自动、配音完整收尾、时长落 T±20%、比例正确;旧菜单置灰可回退 |
| 能力增强 | 某组 1 条口播仿写 30 条分批追加正确;音色池 3 项 × N=10 各条抽定单值且单条内一致;二次进入自动带出偏好,恢复默认有效 |
| 聚合视图 | 前几阶段生成的批次正确聚合为卡片、展开可播放/下载/删;历史作品归未分组不受影响;整批重生成正确 |
五、灰度与回退
| 项 | 规则 |
| 入口 | 新流程走独立路由;新增菜单项「混剪视频」 |
| 开关 | 旧入口置灰即回退开关。置灰 ≠ 删除,代码与路由全程保留 |
| 回退动作 | 放开置灰,用户即可切回经典链路;新流程整体关停不影响老链路 |
| 内核调用收敛 | 老链路 = 同一内核 + 默认参数等价体;批量驱动层是新增组件,可整体关停 |
| 前端新流程 | 新路由承载,页面状态丢失不影响老页面 |
回归基线三件套(每阶段验收必跑)
- 固定回归素材:同一套真实素材与脚本,不随阶段更换;
- 历史缺陷清单:画面静止不动、配音被截断、非竖屏比例失效;
- 对照方式:改前直出与改后经等价体出片逐参数比对,三类老问题均不得复现。
六、实践中暴露的判定分叉
改造期间出现过一类反复出现的缺陷:同一条素材"列表里看得见、点进去用不了"。排查发现是不同环节对"这条素材对当前账号是否可见"用了不同的判定口径——列表用宽口径、详情用严格口径、渲染读取又是第三套。
收敛做法:把所有环节的可见性判定统一为同一套口径(平台公开内容、个人空间本人内容、跨空间可见内容三类分支),并补自动化用例覆盖。
带走的规则:
- 同一类判定只保留一个入口,禁止各处各写一套谓词;
- 失败文案必须区分"查不到这条数据"与"数据在但文件不可用"两种状态,否则会误导排障方向;
- 测试与验收必须显式固定账号上下文,登录上下文漂移是隐性变量。
七、状态与异常
| 异常场景 | 系统处理 | 用户看到 |
| 老脚本映射遇到未预期的结构 | 停下回报字段差异,不自行假设 | 该脚本暂不可用,提示联系处理;其余脚本不受影响 |
| 老请求翻译后信息缺失 | 不允许上线;翻译层必须保证渲染所需信息零丢失 | — |
| 迁移脚本执行 | 幂等,重复执行结果一致 | 老作品读写无感知 |
| 回退(放开旧入口) | 旧入口恢复可点,走原链路 | 与改造前完全一致的操作体验 |
| 新流程不可用期间 | 旧入口可放开 | 不中断用户出片 |
| 契约校验不通过 | 拒绝请求,不建批次、不落脏数据 | 明确错误文案 |