fix(#1749): resolver 空列表/长度1归一化(统一配音口径)+ p02 trim 测试改为 freeze 新行为

- voice_library_ids 空列表/全空白视为未提供,修复 count=1 无配音误 400
- 长度 1 且 count>1 视为统一配音(与 cover_urls/titles 口径一致)
- 严格校验基于原始长度,缺值/数量不符仍 400
- test_p02_p03 trim 断言更新为新行为:trim=目标段长、tpad 末帧冻结、无慢放
This commit is contained in:
saas-backend-agent
2026-09-07 01:27:12 +08:00
parent b76617aa78
commit c9fc7a8cce
2 changed files with 21 additions and 9 deletions
+14 -8
View File
@@ -45,23 +45,29 @@ def resolve_variant_voice_ids(
raise VariantVoiceError("变体数量 count 必须 >= 1")
single = (voice_library_id or "").strip()
multi = [str(v).strip() for v in (voice_library_ids or []) if str(v or "").strip()]
# 归一化:None / 空列表 / 全空白 → 未提供独立配音(走统一配音或无配音)
raw_multi = [str(v or "").strip() for v in (voice_library_ids or [])]
multi = [v for v in raw_multi if v]
if voice_library_ids:
# 显式传了独立配音列表:严格校验,禁止静默 fallback
raw = [str(v or "").strip() for v in voice_library_ids]
if len(raw) != count:
if multi:
# 显式传了独立配音列表:
# - 恰好 1 个非空且 count > 1:视为统一配音(与 cover_urls/titles 长度1=共用一致);
# - 否则按独立配音严格校验:原始长度必须 == count 且逐项非空,禁止静默 fallback;
# - 其余长度/缺值 → 400。
if len(raw_multi) == 1 and count > 1:
return [multi[0]] * count
if len(raw_multi) != count:
raise VariantVoiceError(
f"独立配音数量({len(raw)})与视频数量({count})不一致;"
f"独立配音数量({len(raw_multi)})与视频数量({count})不一致;"
f"批量独立配音必须为每个视频分别指定配音,或改用统一配音 voice_library_id"
)
missing = [i for i, v in enumerate(raw) if not v]
missing = [i for i, v in enumerate(raw_multi) if not v]
if missing:
raise VariantVoiceError(
f"{[i + 1 for i in missing]} 个视频缺少独立配音 voice_library_id"
f"独立配音不允许缺值,也不会回退为统一配音"
)
return raw
return list(raw_multi)
if single:
return [single] * count
+7 -1
View File
@@ -234,12 +234,18 @@ class TestEffectiveDurationTrim:
assert "trim=duration=7.5" in fc
def test_trim_uses_min_of_duration_and_actual(self):
"""clip.duration > actual_duration → trim 到 actual_duration"""
"""#1749clip.duration > actual_duration → 目标段长为准 + tpad 末帧冻结(禁慢放/禁截断)"""
clip = self._make_clip("c1", duration=10.0, actual_duration=2.0)
# 模拟 _resolve_clips 写入的冻结标记(10s 目标 − 2s 素材 = 8s 冻结)
clip.config = {"_freeze_seconds": 8.0}
svc = self._make_service([clip])
layers = svc._group_clips_into_layers([clip])
fc, _ = svc._build_filter_complex(layers)
# 素材内只取 2s,末帧冻结 8s 铺满目标 10s
assert "trim=duration=2.0" in fc
assert "tpad=stop_mode=clone:stop_duration=8.0" in fc
# 不再有慢放(setpts 调速系数应为 1.0,即无 setpts=PTS/ 出现)
assert "setpts=PTS/" not in fc
def test_no_trim_when_both_zero(self):
"""duration=0 且 actual_duration=0 → 不做 trim。"""