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:
@@ -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
|
||||
|
||||
@@ -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。"""
|
||||
"""#1749:clip.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。"""
|
||||
|
||||
Reference in New Issue
Block a user