{"record":{"id":"1bd9fe09f27f8ee5","repo":"calesthio/OpenMontage","slug":"advanced-lip-sync-requires-audio-id-sound-file-s","errorCode":null,"errorMessage":"advanced_lip_sync requires audio_id, sound_file, sound_file_url, sound_file_path, or audio_path","messagePattern":"advanced_lip_sync requires audio_id, sound_file, sound_file_url, sound_file_path, or audio_path","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/avatar/kling_lip_sync.py","lineNumber":644,"sourceCode":"                if top_level_sound_file != nested_sound_file:\n                    raise ValueError(\n                        \"Conflicting audio input between top-level fields and face_choose[0]\"\n                    )\n            return {\"type\": \"sound_file\", \"source\": \"face_choose[0]\"}\n\n        if top_level_audio_id:\n            payload[\"audio_id\"] = top_level_audio_id\n            return {\"type\": \"audio_id\", \"value\": top_level_audio_id}\n\n        sound_path = inputs.get(\"sound_file_path\") or inputs.get(\"audio_path\")\n        sound_file = normalize_media_input(\n            url=inputs.get(\"sound_file_url\"),\n            path=sound_path,\n            value=inputs.get(\"sound_file\"),\n            label=\"Lip-sync audio file\",\n        )\n        if not sound_file:\n            raise ValueError(\"advanced_lip_sync requires audio_id, sound_file, sound_file_url, sound_file_path, or audio_path\")\n        payload[\"sound_file\"] = sound_file\n        return {\n            \"type\": \"sound_file\",\n            \"source\": inputs.get(\"sound_file_url\") or sound_path or \"inline\",\n        }\n\n    def _download_videos(\n        self,\n        client: KlingClient,\n        outputs: list[dict[str, Any]],\n        inputs: dict[str, Any],\n    ) -> list[Path]:\n        if not outputs:\n            raise ValueError(\"Kling lip-sync response contained no videos\")\n        base_path = Path(inputs.get(\"output_path\", \"kling_lip_sync.mp4\"))\n        paths: list[Path] = []\n        for index, item in enumerate(outputs):\n            url = self._output_url(item)","sourceCodeStart":626,"sourceCodeEnd":662,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/avatar/kling_lip_sync.py#L626-L662","documentation":"Raised by KlingLipSyncTool._copy_audio_input as the final fallback: no audio source exists anywhere — no audio_id and normalize_media_input over sound_file/sound_file_url/sound_file_path/audio_path produced nothing. Lip-sync without audio is meaningless, so the tool refuses before calling Kling.","triggerScenarios":"Calling kling_lip_sync with only video_id/face_choose and every audio field absent, empty string, or None. Also when sound_file_path points at a non-existent path such that normalization yields falsy (with no URL/value to fall back on).","commonSituations":"Forgetting the voiceover in an automated pipeline; audio field named something else in the caller's dict (typo like sound_filepath); empty-string defaults from a config loader.","solutions":["Provide exactly one of: audio_id, sound_file, sound_file_url, sound_file_path, or audio_path","Check for typos in the audio field names","If using sound_file_path, verify the file exists before the call"],"exampleFix":"# before\ninputs = {\"video_id\": vid, \"face_choose\": [{\"face_id\": \"f1\"}]}\n\n# after\ninputs = {\"video_id\": vid, \"face_choose\": [{\"face_id\": \"f1\", \"sound_file_path\": \"/tmp/vo.mp3\"}]}","handlingStrategy":"validation","validationCode":"has_audio = any([\n    str(inputs.get(\"audio_id\") or \"\").strip(),\n    inputs.get(\"sound_file\"),\n    inputs.get(\"sound_file_url\"),\n    (inputs.get(\"sound_file_path\") and __import__(\"pathlib\").Path(inputs[\"sound_file_path\"]).is_file()),\n    (inputs.get(\"audio_path\") and __import__(\"pathlib\").Path(inputs[\"audio_path\"]).is_file()),\n])\nif not has_audio:\n    raise ValueError(\"no audio source for lip-sync\")","typeGuard":"def has_lip_sync_audio(inputs) -> bool:\n    return any(inputs.get(k) for k in (\"audio_id\", \"sound_file\", \"sound_file_url\", \"sound_file_path\", \"audio_path\"))","tryCatchPattern":null,"preventionTips":["Make audio a required field in your payload schema","Verify the audio file path exists before calling","Watch for typos like sound_filepath"],"tags":["kling","lip-sync","audio-input","required-field"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}