fix(video-gen): omit duration for range-based FAL families when unspecified

_clamp_duration returned durations[0] for all families when duration=None,
causing pixverse-v6, seedance-2.0, and kling-v3-4k to always send their
minimum value (1s, 4s, 3s respectively) instead of omitting the field and
letting the FAL endpoint apply its own default.

Range families are now detected via the existing _is_duration_range
heuristic and return None (field omitted) when no duration is requested.
Enum families like veo3.1 keep sending their first entry as the default.
This commit is contained in:
AhmetArif0 2026-05-31 23:33:31 +03:00 committed by Teknium
parent a3c0de1a36
commit 5a39f0501c
2 changed files with 28 additions and 1 deletions

View file

@ -180,7 +180,11 @@ def _clamp_duration(family: Dict[str, Any], duration: Optional[int]) -> Optional
if not durations:
return duration
if duration is None:
return durations[0]
# Range families (e.g. pixverse-v6 (1,15)) should omit the field so
# the FAL endpoint applies its own default rather than receiving the
# minimum value. Enum families (e.g. veo3.1 (4,6,8)) keep sending
# their first entry as the default.
return None if _is_duration_range(durations) else durations[0]
if _is_duration_range(durations):
lo, hi = durations
return max(lo, min(hi, duration))

View file

@ -322,6 +322,29 @@ class TestPayloadBuilder:
assert p["generate_audio"] is True
assert p["negative_prompt"] == "ugly"
def test_range_families_omit_duration_when_unspecified(self):
"""Range-based families must omit `duration` when the caller doesn't
specify one so FAL applies its endpoint default, not the minimum."""
from plugins.video_gen.fal import FAL_FAMILIES, _build_payload
for family_id in ("pixverse-v6", "seedance-2.0", "kling-v3-4k"):
meta = FAL_FAMILIES[family_id]
p = _build_payload(
meta,
prompt="x",
image_url=None,
duration=None,
aspect_ratio="16:9",
resolution="720p",
negative_prompt=None,
audio=None,
seed=None,
)
assert "duration" not in p, (
f"{family_id}: duration=None should omit the field, "
f"got {p.get('duration')!r}"
)
def test_happy_horse_minimal_payload(self):
"""Happy Horse has sparse docs — payload should be minimal."""
from plugins.video_gen.fal import FAL_FAMILIES, _build_payload