diff --git a/kie_api/kling26motion_i2v.py b/kie_api/kling26motion_i2v.py index 93148b5..b5522ba 100644 --- a/kie_api/kling26motion_i2v.py +++ b/kie_api/kling26motion_i2v.py @@ -13,7 +13,7 @@ from .http import TransientKieError, requests from .jobs import _poll_task_until_complete from .log import _log from .results import _extract_result_urls -from .upload import _image_tensor_to_png_bytes, _truncate_url, _upload_image +from .upload import _image_tensor_to_png_bytes, _truncate_url, _upload_image, _upload_video from .validation import _validate_prompt from .video import _download_video, _video_bytes_to_comfy_video @@ -133,7 +133,7 @@ def run_kling26motion_i2v_video( # Upload the motion reference video using the shared upload helper. _log(log, "Uploading motion reference video for Kling 2.6 Motion I2V...") - video_url = _upload_image(api_key, video_bytes) + video_url = _upload_video(api_key, video_bytes) _log(log, f"Video upload success: {_truncate_url(video_url)}") # Normalize the resolution mode to the API's expected values. diff --git a/kie_api/upload.py b/kie_api/upload.py index c5cb822..c5591f4 100644 --- a/kie_api/upload.py +++ b/kie_api/upload.py @@ -77,3 +77,40 @@ def _upload_image(api_key: str, png_bytes: bytes) -> str: raise RuntimeError("Upload response missing downloadUrl.") return url + + +def _upload_video(api_key: str, video_bytes: bytes, filename: str = "video.mp4") -> str: + if not filename: + raise RuntimeError("filename is required for video uploads.") + try: + response = requests.post( + UPLOAD_URL, + headers={"Authorization": f"Bearer {api_key}"}, + files={"file": (filename, video_bytes, "video/mp4")}, + data={"uploadPath": UPLOAD_PATH, "fileName": filename}, + timeout=180, + ) + except requests.RequestException as exc: + raise RuntimeError(f"Failed to upload video: {exc}") from exc + + if response.status_code == 429 or response.status_code >= 500: + raise TransientKieError( + f"upload returned HTTP {response.status_code}: {response.text}", status_code=response.status_code + ) + + try: + payload_json: Any = response.json() + except json.JSONDecodeError as exc: + raise RuntimeError("Upload endpoint did not return valid JSON.") from exc + + success = payload_json.get("success") + code = payload_json.get("code") + if not success or code != 200: + raise RuntimeError(f"Upload failed (code={code}): {payload_json.get('msg')}") + + data = payload_json.get("data") or {} + url = data.get("downloadUrl") + if not url: + raise RuntimeError("Upload response missing downloadUrl.") + + return url