calesthio/OpenMontage · error · ValueError
advanced_lip_sync requires at least 2000ms of cropped audio
Error message
advanced_lip_sync requires at least 2000ms of cropped audio
What it means
Raised by KlingLipSyncTool._copy_timing_fields on the advanced lip-sync path when sound_end_time - sound_start_time < 2000 ms. Kling's advanced lip-sync API rejects cropped audio segments shorter than 2 seconds, so the tool enforces the floor before sending the request.
Source
Thrown at tools/avatar/kling_lip_sync.py:563
value = default
face_item[key] = int(value)
nested_end = face_item.get("sound_end_time")
top_level_end = inputs.get("sound_end_time")
if (
nested_end is not None
and top_level_end is not None
and int(nested_end) != int(top_level_end)
):
raise ValueError(
"Conflicting sound_end_time values between top-level input and face_choose[0]"
)
sound_end = nested_end if nested_end is not None else top_level_end
if sound_end is None:
raise ValueError("advanced_lip_sync requires sound_end_time")
face_item["sound_end_time"] = int(sound_end)
if face_item["sound_end_time"] - face_item["sound_start_time"] < 2000:
raise ValueError("advanced_lip_sync requires at least 2000ms of cropped audio")
for key in ("sound_volume", "original_audio_volume"):
nested = face_item.get(key)
top_level = inputs.get(key)
if nested is not None and top_level is not None and float(nested) != float(top_level):
raise ValueError(
f"Conflicting {key} values between top-level input and face_choose[0]"
)
value = nested if nested is not None else top_level
if value is not None:
face_item[key] = float(value)
@staticmethod
def _face_choose_result_metadata(
face_choose: list[dict[str, Any]],
) -> list[dict[str, Any]]:
metadata: list[dict[str, Any]] = []
for item in face_choose:View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Extend the crop window so end - start >= 2000 ms (pad with silence if the speech is shorter)
- Shift sound_start_time closer to sound_end_time if you accidentally left it at 0 while the audio lives later in the file
- If the clip genuinely must be <2s, use the non-advanced lip-sync path or pad the audio file itself
Example fix
# before
face = {"sound_start_time": 0, "sound_end_time": 1500}
# after
face = {"sound_start_time": 0, "sound_end_time": 2000} Defensive patterns
Strategy: validation
Validate before calling
face_item = (inputs.get("face_choose") or [{}])[0]
start = int(face_item.get("sound_start_time") or inputs.get("sound_start_time") or 0)
end = face_item.get("sound_end_time") if face_item.get("sound_end_time") is not None else inputs.get("sound_end_time")
if end is None or int(end) - start < 2000:
raise ValueError("crop window must be >= 2000ms") Prevention
- Budget at least 2s of audio per lip-sync call
- Pad short voice lines with silence to reach 2000ms
- Double-check sound_start_time defaults to 0 — end must exceed it by 2000
When it happens
Trigger: advanced_lip_sync with sound_start_time=0 and sound_end_time=1500; or face_choose[0] = {'sound_start_time': 4000, 'sound_end_time': 5500}. Defaults matter too: if sound_start_time defaults to 0, sound_end_time must be >= 2000.
Common situations: Trying to lip-sync a single short word or a 1-second SFX cue; computing the crop window from a transcript where a spoken phrase lasted under 2s.
Related errors
- full_lip_sync could not infer sound_end_time; provide it exp
- Conflicting {key} values between top-level input and face_ch
- Conflicting sound_end_time values between top-level input an
- advanced_lip_sync requires sound_end_time
- Unsupported Kling lip-sync operation: {operation}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/bdf62bab97186321.
Report an issue: GitHub.