From 5a39f0501c5a9026cc8e2936da32c714c1f1de2e Mon Sep 17 00:00:00 2001 From: AhmetArif0 <147827411+AhmetArif0@users.noreply.github.com> Date: Sun, 31 May 2026 23:33:31 +0300 Subject: [PATCH] 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. --- plugins/video_gen/fal/__init__.py | 6 +++++- tests/plugins/video_gen/test_fal_plugin.py | 23 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/plugins/video_gen/fal/__init__.py b/plugins/video_gen/fal/__init__.py index 1290d92d1..1a67a5260 100644 --- a/plugins/video_gen/fal/__init__.py +++ b/plugins/video_gen/fal/__init__.py @@ -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)) diff --git a/tests/plugins/video_gen/test_fal_plugin.py b/tests/plugins/video_gen/test_fal_plugin.py index 7af1bd409..8f522a8e5 100644 --- a/tests/plugins/video_gen/test_fal_plugin.py +++ b/tests/plugins/video_gen/test_fal_plugin.py @@ -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