feat: 片段重复率控制(受控复用+15%双闸门+批量plan独立)与素材余量四字段 #1549
Reference in New Issue
Block a user
Delete Branch "feat/segment-duplication-control"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
目标:任意两条成片画面重复率 ≤15%。此前自动轮回机制会清空历史区间并无限复用,且 MediaKit 智能选片不避让历史区间、批量生成多条视频共用同一 plan/clips,导致成片间画面重复。
Task G:片段重复率控制
1. MediaKit 智能选片避让历史区间
_recommended_time_conflicts冲突检查,边缘间隙SEGMENT_EDGE_GAP=0.3s(与随机选片同口径)2. 自动轮回 → 受控复用
used_time_ranges: [{start, end, plan_id, created_at, use_count=1, last_used_at}]last_used_at最老且use_count < MAX_RANGE_USE_COUNT(=3)的区间;复用判定在 record_used_segments 内部(重叠率 ≥60% 累加 use_count)reused/assigned > REUSE_RATIO_LIMIT(0.15)则停止分配该素材(reused+clip)/(assigned+clip) > limit预判拒绝(返回 None),拦住「导致超限的那次复用」_calc_random_start_time直接返回 None(删除末尾/0.0 重叠降级,避免放回已用画面);无回调旧路径保留末尾降级(向后兼容)3. 批量 N 条视频片段独立(合并 Issue #1282)
count>1时第 2 条起clone_plan_for_variant克隆独立 plan(新 plan_id、独立 clips、独立随机起点),禁止共用 source_edit_plan_id/clipsTask H:素材余量透出与已用尽素材排除
AssetResponse新增四字段:used_duration/available_duration/used_ratio(float|None)、usable(bool,默认 True)used_duration= 历史区间合并后总时长(秒,封顶 total)available_duration= total - used_durationused_ratio= used_duration / total(0~1)usable=false:扩边(0.3s)后无 ≥3s 空闲段(零重复可切区间耗尽)且所有历史区间 use_count 均达上限 3GET /assets列表与GET /assets/{id}详情统一经_to_asset_response一处注入POST /assets/smart-match结果层过滤 usable=false 素材(评分逻辑不动)配置常量(tracker 模块)
测试
前端配合(另 PR)
素材库卡片余量角标:红「已用尽」/ 红「即将用尽」(used_ratio≥0.85) / 橙「已用 xx%」(≥0.5);Step2 过滤 usable=false;字段缺失按可用处理。
Closes #1282
🚀 预览环境已部署
【阻塞级判定】
📊 审查概览
🔴 阻塞级问题(必须修复)
无
💡 改进建议(不阻塞合并)
[apps/api/app/api/routes/assets.py: 591-603] 潜在的 N+1 查询性能风险
smart_match_assets函数中,代码遍历results列表并对每个元素调用compute_asset_availability(r.asset)。如果compute_asset_availability内部涉及数据库查询(例如查询该素材的历史使用片段),且results列表较长,这将导致 N+1 查询问题,显著降低接口响应速度。compute_asset_availability的实现。如果涉及 DB 查询,考虑在循环外批量获取所有相关素材的元数据或使用信息,然后批量计算,或者限制单次返回的results数量。[apps/api/app/api/routes/templates_editor/clips.py: 866] 浮点数精度风险
set(other_segments) | set(historical_segments.get(asset_id, []))对时间段进行去重。时间段由浮点数元组(float, float)组成。由于浮点数精度问题(如0.1 + 0.2 != 0.3),数学上相等的时间点可能被视为不同,导致去重失败或冲突检测不准确。round(..., 1),降低了风险,但在处理集合操作时,建议将时间转换为整数(如毫秒)或确定精度的字符串后再进行集合操作,以确保去重的准确性。✅ 良好实践
make_reuse_callback)和复用比率限制(REUSE_RATIO_LIMIT),有效防止了素材过度复用导致的视频内容重复问题,逻辑设计较为严谨。_asset_availability_fields中增加了异常捕获和降级处理,当计算失败时默认返回usable=True,保证了素材列表接口的可用性不被下游计算错误阻断,且保留了日志记录便于排查。✅ 格式检查通过 | ✅ 逻辑审查通过 | ⚠️ 建议关注性能
🤖 由 AI 代码审查机器人自动生成 | 2026-08-29 18:42:33 | 模型:
CI全绿,自动审批通过。
CI全绿,自动审批通过。
🗑️ 预览环境已清理
PR #1549 已关闭或合并,对应的预览环境已被清理。