runapi-kling 0.3.4__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/PKG-INFO +3 -3
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/pyproject.toml +3 -3
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/contract_gen.py +38 -1
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/image_to_video.py +1 -4
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/text_to_video.py +0 -10
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/tests/test_client.py +74 -73
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/README.md +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/__init__.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/client.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/py.typed +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/__init__.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/ai_avatar.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/edit_video.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/extend_video.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/motion_control.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/o1_reference_validation.py +0 -0
- {runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/types.py +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: runapi-kling
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: RunAPI Kling SDK for text-to-video, image-to-video, source-video editing, avatar, and motion-control workflows in JavaScript, Python, Ruby, Go, Java, and PHP
|
|
5
5
|
Project-URL: Homepage, https://runapi.ai/models/kling
|
|
6
6
|
Project-URL: Documentation, https://runapi.ai/docs/resources/sdks
|
|
7
7
|
Project-URL: Source, https://github.com/runapi-ai/kling-sdk
|
|
8
8
|
Project-URL: Issues, https://github.com/runapi-ai/kling-sdk/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/runapi-ai/kling-sdk/blob/main/CHANGELOG.md
|
|
10
|
-
Project-URL: Release Notes, https://github.com/runapi-ai/kling-sdk/releases/tag/python%2Fv0.
|
|
10
|
+
Project-URL: Release Notes, https://github.com/runapi-ai/kling-sdk/releases/tag/python%2Fv0.4.0
|
|
11
11
|
Author-email: RunAPI <contact@runapi.ai>
|
|
12
12
|
License-Expression: Apache-2.0
|
|
13
13
|
Keywords: api,golang,gradle,java,kling,kling-ai-api,maven,python,ruby,runapi,runapi-ai,sdk,text-to-video,typescript,video-api,video-generation
|
|
14
14
|
Requires-Python: >=3.9
|
|
15
|
-
Requires-Dist: runapi-core>=0.
|
|
15
|
+
Requires-Dist: runapi-core>=0.9.1
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
18
|
# Kling API Python SDK for RunAPI
|
|
@@ -4,14 +4,14 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "runapi-kling"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "RunAPI Kling SDK for text-to-video, image-to-video, source-video editing, avatar, and motion-control workflows in JavaScript, Python, Ruby, Go, Java, and PHP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
authors = [{ name = "RunAPI", email = "contact@runapi.ai" }]
|
|
13
13
|
keywords = ["runapi", "runapi-ai", "kling", "api", "sdk", "typescript", "python", "ruby", "golang", "java", "maven", "gradle", "video-generation", "text-to-video", "video-api", "kling-ai-api"]
|
|
14
|
-
dependencies = ["runapi-core>=0.
|
|
14
|
+
dependencies = ["runapi-core>=0.9.1"]
|
|
15
15
|
|
|
16
16
|
[project.urls]
|
|
17
17
|
Homepage = "https://runapi.ai/models/kling"
|
|
@@ -19,7 +19,7 @@ Documentation = "https://runapi.ai/docs/resources/sdks"
|
|
|
19
19
|
Source = "https://github.com/runapi-ai/kling-sdk"
|
|
20
20
|
Issues = "https://github.com/runapi-ai/kling-sdk/issues"
|
|
21
21
|
Changelog = "https://github.com/runapi-ai/kling-sdk/blob/main/CHANGELOG.md"
|
|
22
|
-
"Release Notes" = "https://github.com/runapi-ai/kling-sdk/releases/tag/python%2Fv0.
|
|
22
|
+
"Release Notes" = "https://github.com/runapi-ai/kling-sdk/releases/tag/python%2Fv0.4.0"
|
|
23
23
|
|
|
24
24
|
[tool.hatch.build.targets.wheel]
|
|
25
25
|
packages = ["src/runapi"]
|
|
@@ -500,11 +500,29 @@ CONTRACT = {
|
|
|
500
500
|
"model": "kling-v2.5-turbo-image-to-video-pro"
|
|
501
501
|
},
|
|
502
502
|
"forbidden": ["output_resolution", "enable_sound", "reference_image_urls", "reference_video_url", "reference_video_type", "preserve_reference_video_audio"]
|
|
503
|
+
}, {
|
|
504
|
+
"enum": {
|
|
505
|
+
"enable_sound": [False]
|
|
506
|
+
},
|
|
507
|
+
"when": {
|
|
508
|
+
"mode": "std",
|
|
509
|
+
"model": "kling-v2.6"
|
|
510
|
+
}
|
|
503
511
|
}, {
|
|
504
512
|
"when": {
|
|
505
513
|
"model": "kling-v2.6"
|
|
506
514
|
},
|
|
507
515
|
"forbidden": ["output_resolution", "negative_prompt", "cfg_scale", "reference_image_urls", "reference_video_url", "reference_video_type", "preserve_reference_video_audio"]
|
|
516
|
+
}, {
|
|
517
|
+
"enum": {
|
|
518
|
+
"enable_sound": [False]
|
|
519
|
+
},
|
|
520
|
+
"when": {
|
|
521
|
+
"mode": {
|
|
522
|
+
"present": False
|
|
523
|
+
},
|
|
524
|
+
"model": "kling-v2.6"
|
|
525
|
+
}
|
|
508
526
|
}, {
|
|
509
527
|
"when": {
|
|
510
528
|
"model": "kling-v3-omni"
|
|
@@ -531,7 +549,8 @@ CONTRACT = {
|
|
|
531
549
|
"required": True
|
|
532
550
|
},
|
|
533
551
|
"output_resolution": {
|
|
534
|
-
"enum": ["720p", "1080p"]
|
|
552
|
+
"enum": ["720p", "1080p"],
|
|
553
|
+
"required": True
|
|
535
554
|
},
|
|
536
555
|
"reference_video_url": {
|
|
537
556
|
"required": True
|
|
@@ -757,6 +776,24 @@ CONTRACT = {
|
|
|
757
776
|
"model": "kling-v2.6"
|
|
758
777
|
},
|
|
759
778
|
"forbidden": ["output_resolution", "negative_prompt", "cfg_scale", "multi_shots", "multi_prompt", "first_frame_image_url", "last_frame_image_url", "kling_elements", "reference_image_urls", "reference_video_url", "reference_video_type", "preserve_reference_video_audio"]
|
|
779
|
+
}, {
|
|
780
|
+
"enum": {
|
|
781
|
+
"enable_sound": [False]
|
|
782
|
+
},
|
|
783
|
+
"when": {
|
|
784
|
+
"mode": "std",
|
|
785
|
+
"model": "kling-v2.6"
|
|
786
|
+
}
|
|
787
|
+
}, {
|
|
788
|
+
"enum": {
|
|
789
|
+
"enable_sound": [False]
|
|
790
|
+
},
|
|
791
|
+
"when": {
|
|
792
|
+
"mode": {
|
|
793
|
+
"present": False
|
|
794
|
+
},
|
|
795
|
+
"model": "kling-v2.6"
|
|
796
|
+
}
|
|
760
797
|
}, {
|
|
761
798
|
"when": {
|
|
762
799
|
"model": "kling-v3-omni"
|
|
@@ -96,12 +96,9 @@ class ImageToVideo(Resource):
|
|
|
96
96
|
def _validate_v26_params(
|
|
97
97
|
self, params: Dict[str, Any], last_frame_image_url: Any
|
|
98
98
|
) -> None:
|
|
99
|
-
mode = params.get("mode") or "std"
|
|
100
|
-
if params.get("enable_sound") is True and mode != "pro":
|
|
101
|
-
raise ValidationError(f"enable_sound requires mode pro for {V26_MODEL}")
|
|
102
99
|
if not last_frame_image_url:
|
|
103
100
|
return
|
|
104
|
-
if mode != "pro":
|
|
101
|
+
if (params.get("mode") or "std") != "pro":
|
|
105
102
|
raise ValidationError(f"last_frame_image_url requires mode pro for {V26_MODEL}")
|
|
106
103
|
if params.get("duration_seconds", 5) != 5:
|
|
107
104
|
raise ValidationError(
|
|
@@ -15,7 +15,6 @@ from ..types import (
|
|
|
15
15
|
)
|
|
16
16
|
from .o1_reference_validation import validate_kling_o1_references
|
|
17
17
|
|
|
18
|
-
V26_MODEL = "kling-v2.6"
|
|
19
18
|
V3_TURBO_MODEL = "kling-v3-turbo-text-to-video"
|
|
20
19
|
V3_TURBO_UNSUPPORTED_FIELDS = (
|
|
21
20
|
"enable_sound",
|
|
@@ -76,7 +75,6 @@ class TextToVideo(Resource):
|
|
|
76
75
|
def _validate_params(self, params: Dict[str, Any]) -> None:
|
|
77
76
|
self._reject_unsupported_v3_turbo_fields(params)
|
|
78
77
|
self._validate_contract(CONTRACT["text-to-video"], params)
|
|
79
|
-
self._validate_v26_params(params)
|
|
80
78
|
validate_kling_o1_references(params)
|
|
81
79
|
|
|
82
80
|
# Bespoke cross-field rules the contract cannot express.
|
|
@@ -93,14 +91,6 @@ class TextToVideo(Resource):
|
|
|
93
91
|
if not params.get("prompt"):
|
|
94
92
|
raise ValidationError("prompt is required")
|
|
95
93
|
|
|
96
|
-
def _validate_v26_params(self, params: Dict[str, Any]) -> None:
|
|
97
|
-
if (
|
|
98
|
-
params.get("model") == V26_MODEL
|
|
99
|
-
and params.get("enable_sound") is True
|
|
100
|
-
and params.get("mode") != "pro"
|
|
101
|
-
):
|
|
102
|
-
raise ValidationError(f"enable_sound requires mode pro for {V26_MODEL}")
|
|
103
|
-
|
|
104
94
|
def _reject_unsupported_v3_turbo_fields(self, params: Dict[str, Any]) -> None:
|
|
105
95
|
if params.get("model") != V3_TURBO_MODEL:
|
|
106
96
|
return
|
|
@@ -97,8 +97,7 @@ def test_text_to_video_create_posts_compacted_body():
|
|
|
97
97
|
"post",
|
|
98
98
|
"/api/v1/kling/text_to_video",
|
|
99
99
|
{"model": "kling-3.0", "prompt": "a cat in a garden", "aspect_ratio": "16:9"},
|
|
100
|
-
)
|
|
101
|
-
]
|
|
100
|
+
)]
|
|
102
101
|
assert isinstance(result, TextToVideoResponse)
|
|
103
102
|
|
|
104
103
|
|
|
@@ -114,18 +113,14 @@ def test_text_to_video_create_posts_element_audio_and_time_fields():
|
|
|
114
113
|
"description": "dog",
|
|
115
114
|
"element_input_urls": [
|
|
116
115
|
"https://upload.wikimedia.org/wikipedia/commons/6/6e/Golde33443.jpg",
|
|
117
|
-
"https://upload.wikimedia.org/wikipedia/commons/9/9a/Pug_600.jpg",
|
|
118
|
-
],
|
|
119
|
-
"element_input_audio_urls": ["https://cdn.runapi.ai/public/samples/music.mp3"],
|
|
120
|
-
},
|
|
116
|
+
"https://upload.wikimedia.org/wikipedia/commons/9/9a/Pug_600.jpg"],
|
|
117
|
+
"element_input_audio_urls": ["https://cdn.runapi.ai/public/samples/music.mp3"]},
|
|
121
118
|
{
|
|
122
119
|
"name": "element_run",
|
|
123
120
|
"description": "running dog",
|
|
124
121
|
"element_input_urls": ["https://cdn.runapi.ai/public/samples/video.mp4"],
|
|
125
122
|
"start_time": 1000,
|
|
126
|
-
"end_time": 6000,
|
|
127
|
-
},
|
|
128
|
-
],
|
|
123
|
+
"end_time": 6000}],
|
|
129
124
|
)
|
|
130
125
|
assert fake.calls == [
|
|
131
126
|
(
|
|
@@ -140,12 +135,10 @@ def test_text_to_video_create_posts_element_audio_and_time_fields():
|
|
|
140
135
|
"description": "dog",
|
|
141
136
|
"element_input_urls": [
|
|
142
137
|
"https://upload.wikimedia.org/wikipedia/commons/6/6e/Golde33443.jpg",
|
|
143
|
-
"https://upload.wikimedia.org/wikipedia/commons/9/9a/Pug_600.jpg",
|
|
144
|
-
],
|
|
138
|
+
"https://upload.wikimedia.org/wikipedia/commons/9/9a/Pug_600.jpg"],
|
|
145
139
|
"element_input_audio_urls": [
|
|
146
140
|
"https://cdn.runapi.ai/public/samples/music.mp3"
|
|
147
|
-
],
|
|
148
|
-
},
|
|
141
|
+
]},
|
|
149
142
|
{
|
|
150
143
|
"name": "element_run",
|
|
151
144
|
"description": "running dog",
|
|
@@ -153,12 +146,8 @@ def test_text_to_video_create_posts_element_audio_and_time_fields():
|
|
|
153
146
|
"https://cdn.runapi.ai/public/samples/video.mp4"
|
|
154
147
|
],
|
|
155
148
|
"start_time": 1000,
|
|
156
|
-
"end_time": 6000,
|
|
157
|
-
|
|
158
|
-
],
|
|
159
|
-
},
|
|
160
|
-
),
|
|
161
|
-
]
|
|
149
|
+
"end_time": 6000}]},
|
|
150
|
+
)]
|
|
162
151
|
assert isinstance(result, TextToVideoResponse)
|
|
163
152
|
|
|
164
153
|
|
|
@@ -172,7 +161,7 @@ def test_text_to_video_get_fetches_by_id():
|
|
|
172
161
|
def test_text_to_video_run_narrows_completed_type():
|
|
173
162
|
fake = FakeHttp(
|
|
174
163
|
{"id": "t1", "status": "pending"},
|
|
175
|
-
{"id": "t1", "status": "completed", "videos": [{"url": "https://x/y.mp4"}]},
|
|
164
|
+
{"id": "t1", "status": "completed", "usage": {"cost": 0.05}, "videos": [{"url": "https://x/y.mp4"}]},
|
|
176
165
|
)
|
|
177
166
|
client = KlingClient(api_key="k", http_client=fake)
|
|
178
167
|
result = client.text_to_video.run(model="kling-3.0", prompt="a serene forest")
|
|
@@ -322,10 +311,8 @@ def test_text_to_video_v3_turbo_posts_body():
|
|
|
322
311
|
"prompt": "a silver train crossing a moonlit bridge",
|
|
323
312
|
"duration_seconds": 7,
|
|
324
313
|
"aspect_ratio": "16:9",
|
|
325
|
-
"output_resolution": "1080p",
|
|
326
|
-
|
|
327
|
-
),
|
|
328
|
-
]
|
|
314
|
+
"output_resolution": "1080p"},
|
|
315
|
+
)]
|
|
329
316
|
|
|
330
317
|
|
|
331
318
|
def test_text_to_video_v3_turbo_rejects_unsupported_fields():
|
|
@@ -365,8 +352,7 @@ def test_text_to_video_v26_posts_mode_and_sound_fields():
|
|
|
365
352
|
"mode": "pro",
|
|
366
353
|
"duration_seconds": 10,
|
|
367
354
|
"enable_sound": True,
|
|
368
|
-
"aspect_ratio": "16:9",
|
|
369
|
-
},
|
|
355
|
+
"aspect_ratio": "16:9"},
|
|
370
356
|
)
|
|
371
357
|
]
|
|
372
358
|
|
|
@@ -394,8 +380,7 @@ def test_text_to_video_v3_omni_posts_resolution_and_sound_fields():
|
|
|
394
380
|
"output_resolution": "1080p",
|
|
395
381
|
"duration_seconds": 10,
|
|
396
382
|
"enable_sound": True,
|
|
397
|
-
"aspect_ratio": "16:9",
|
|
398
|
-
},
|
|
383
|
+
"aspect_ratio": "16:9"},
|
|
399
384
|
)
|
|
400
385
|
]
|
|
401
386
|
|
|
@@ -405,11 +390,18 @@ def test_text_to_video_v26_rejects_sound_outside_pro_mode():
|
|
|
405
390
|
client = KlingClient(api_key="k", http_client=fake)
|
|
406
391
|
|
|
407
392
|
with pytest.raises(
|
|
408
|
-
ValidationError, match="enable_sound
|
|
393
|
+
ValidationError, match="enable_sound must be one of: false when .*model is kling-v2.6"
|
|
409
394
|
):
|
|
410
395
|
client.text_to_video.create(
|
|
411
396
|
model="kling-v2.6", prompt="test", enable_sound=True
|
|
412
397
|
)
|
|
398
|
+
with pytest.raises(
|
|
399
|
+
ValidationError,
|
|
400
|
+
match="enable_sound must be one of: false when mode is std and model is kling-v2.6",
|
|
401
|
+
):
|
|
402
|
+
client.text_to_video.create(
|
|
403
|
+
model="kling-v2.6", prompt="test", mode="std", enable_sound=True
|
|
404
|
+
)
|
|
413
405
|
assert fake.calls == []
|
|
414
406
|
|
|
415
407
|
|
|
@@ -440,8 +432,7 @@ def test_text_to_video_o1_posts_reference_fields():
|
|
|
440
432
|
"reference_video_url": "https://cdn.runapi.ai/public/samples/video.mp4",
|
|
441
433
|
"reference_video_type": "feature",
|
|
442
434
|
"preserve_reference_video_audio": True,
|
|
443
|
-
"duration_seconds": 5,
|
|
444
|
-
},
|
|
435
|
+
"duration_seconds": 5},
|
|
445
436
|
)
|
|
446
437
|
]
|
|
447
438
|
|
|
@@ -484,10 +475,8 @@ def test_ai_avatar_create_posts_body():
|
|
|
484
475
|
"model": "kling-ai-avatar-pro",
|
|
485
476
|
"prompt": "a host greeting",
|
|
486
477
|
"source_image_url": "https://x/p.jpg",
|
|
487
|
-
"source_audio_url": "https://x/a.mp3",
|
|
488
|
-
|
|
489
|
-
),
|
|
490
|
-
]
|
|
478
|
+
"source_audio_url": "https://x/a.mp3"},
|
|
479
|
+
)]
|
|
491
480
|
assert isinstance(result, AiAvatarResponse)
|
|
492
481
|
|
|
493
482
|
|
|
@@ -501,7 +490,7 @@ def test_ai_avatar_get_fetches_by_id():
|
|
|
501
490
|
def test_ai_avatar_run_narrows_completed_type():
|
|
502
491
|
fake = FakeHttp(
|
|
503
492
|
{"id": "t1", "status": "pending"},
|
|
504
|
-
{"id": "t1", "status": "completed", "videos": [{"url": "https://x/a.mp4"}]},
|
|
493
|
+
{"id": "t1", "status": "completed", "usage": {"cost": 0.05}, "videos": [{"url": "https://x/a.mp4"}]},
|
|
505
494
|
)
|
|
506
495
|
client = KlingClient(api_key="k", http_client=fake)
|
|
507
496
|
result = client.ai_avatar.run(
|
|
@@ -568,10 +557,8 @@ def test_image_to_video_create_posts_body():
|
|
|
568
557
|
{
|
|
569
558
|
"model": "kling-v2.1-pro",
|
|
570
559
|
"prompt": "zoom out slowly",
|
|
571
|
-
"first_frame_image_url": "https://x/f.jpg",
|
|
572
|
-
|
|
573
|
-
),
|
|
574
|
-
]
|
|
560
|
+
"first_frame_image_url": "https://x/f.jpg"},
|
|
561
|
+
)]
|
|
575
562
|
assert isinstance(result, ImageToVideoResponse)
|
|
576
563
|
|
|
577
564
|
|
|
@@ -585,7 +572,7 @@ def test_image_to_video_get_fetches_by_id():
|
|
|
585
572
|
def test_image_to_video_run_narrows_completed_type():
|
|
586
573
|
fake = FakeHttp(
|
|
587
574
|
{"id": "t1", "status": "pending"},
|
|
588
|
-
{"id": "t1", "status": "completed", "videos": [{"url": "https://x/i.mp4"}]},
|
|
575
|
+
{"id": "t1", "status": "completed", "usage": {"cost": 0.05}, "videos": [{"url": "https://x/i.mp4"}]},
|
|
589
576
|
)
|
|
590
577
|
client = KlingClient(api_key="k", http_client=fake)
|
|
591
578
|
result = client.image_to_video.run(
|
|
@@ -671,10 +658,8 @@ def test_image_to_video_v3_turbo_posts_body():
|
|
|
671
658
|
"prompt": "camera glides toward the lighthouse",
|
|
672
659
|
"first_frame_image_url": "https://x/lighthouse.jpg",
|
|
673
660
|
"duration_seconds": 7,
|
|
674
|
-
"output_resolution": "720p",
|
|
675
|
-
|
|
676
|
-
),
|
|
677
|
-
]
|
|
661
|
+
"output_resolution": "720p"},
|
|
662
|
+
)]
|
|
678
663
|
|
|
679
664
|
|
|
680
665
|
def test_image_to_video_v3_turbo_rejects_unsupported_fields():
|
|
@@ -719,8 +704,7 @@ def test_image_to_video_v26_posts_mode_sound_and_final_frame_fields():
|
|
|
719
704
|
"mode": "pro",
|
|
720
705
|
"duration_seconds": 5,
|
|
721
706
|
"enable_sound": True,
|
|
722
|
-
"aspect_ratio": "16:9",
|
|
723
|
-
},
|
|
707
|
+
"aspect_ratio": "16:9"},
|
|
724
708
|
)
|
|
725
709
|
]
|
|
726
710
|
|
|
@@ -752,8 +736,7 @@ def test_image_to_video_v3_omni_posts_resolution_sound_and_final_frame_fields():
|
|
|
752
736
|
"output_resolution": "4k",
|
|
753
737
|
"duration_seconds": 5,
|
|
754
738
|
"enable_sound": False,
|
|
755
|
-
"aspect_ratio": "9:16",
|
|
756
|
-
},
|
|
739
|
+
"aspect_ratio": "9:16"},
|
|
757
740
|
)
|
|
758
741
|
]
|
|
759
742
|
|
|
@@ -762,12 +745,23 @@ def test_image_to_video_v26_rejects_sound_outside_pro_mode():
|
|
|
762
745
|
client = KlingClient(api_key="k", http_client=FakeHttp())
|
|
763
746
|
|
|
764
747
|
with pytest.raises(
|
|
765
|
-
ValidationError, match="enable_sound
|
|
748
|
+
ValidationError, match="enable_sound must be one of: false when .*model is kling-v2.6"
|
|
749
|
+
):
|
|
750
|
+
client.image_to_video.create(
|
|
751
|
+
model="kling-v2.6",
|
|
752
|
+
prompt="test",
|
|
753
|
+
first_frame_image_url="https://x/first.jpg",
|
|
754
|
+
enable_sound=True,
|
|
755
|
+
)
|
|
756
|
+
with pytest.raises(
|
|
757
|
+
ValidationError,
|
|
758
|
+
match="enable_sound must be one of: false when mode is std and model is kling-v2.6",
|
|
766
759
|
):
|
|
767
760
|
client.image_to_video.create(
|
|
768
761
|
model="kling-v2.6",
|
|
769
762
|
prompt="test",
|
|
770
763
|
first_frame_image_url="https://x/first.jpg",
|
|
764
|
+
mode="std",
|
|
771
765
|
enable_sound=True,
|
|
772
766
|
)
|
|
773
767
|
|
|
@@ -779,8 +773,7 @@ def test_image_to_video_v26_rejects_sound_outside_pro_mode():
|
|
|
779
773
|
(
|
|
780
774
|
{"mode": "pro", "duration_seconds": 10},
|
|
781
775
|
"last_frame_image_url requires duration_seconds 5 for kling-v2.6",
|
|
782
|
-
),
|
|
783
|
-
],
|
|
776
|
+
)],
|
|
784
777
|
)
|
|
785
778
|
def test_image_to_video_v26_rejects_invalid_final_frame_combinations(extra, message):
|
|
786
779
|
client = KlingClient(api_key="k", http_client=FakeHttp())
|
|
@@ -871,8 +864,7 @@ def test_text_to_video_o1_rejects_missing_video_reference():
|
|
|
871
864
|
"http://2130706433/reference.jpg",
|
|
872
865
|
"http://127.1/reference.jpg",
|
|
873
866
|
"http://0177.0.0.1/reference.jpg",
|
|
874
|
-
"http://0x7f000001/reference.jpg",
|
|
875
|
-
],
|
|
867
|
+
"http://0x7f000001/reference.jpg"],
|
|
876
868
|
)
|
|
877
869
|
def test_text_to_video_o1_rejects_non_public_reference_media(reference_url):
|
|
878
870
|
fake = FakeHttp()
|
|
@@ -900,6 +892,7 @@ def test_motion_control_create_posts_body():
|
|
|
900
892
|
model="kling-3.0",
|
|
901
893
|
source_image_url="https://x/s.jpg",
|
|
902
894
|
reference_video_url="https://x/r.mp4",
|
|
895
|
+
output_resolution="720p",
|
|
903
896
|
)
|
|
904
897
|
assert fake.calls == [
|
|
905
898
|
(
|
|
@@ -909,12 +902,23 @@ def test_motion_control_create_posts_body():
|
|
|
909
902
|
"model": "kling-3.0",
|
|
910
903
|
"source_image_url": "https://x/s.jpg",
|
|
911
904
|
"reference_video_url": "https://x/r.mp4",
|
|
912
|
-
|
|
913
|
-
)
|
|
914
|
-
]
|
|
905
|
+
"output_resolution": "720p"},
|
|
906
|
+
)]
|
|
915
907
|
assert isinstance(result, MotionControlResponse)
|
|
916
908
|
|
|
917
909
|
|
|
910
|
+
def test_motion_control_kling_3_requires_output_resolution():
|
|
911
|
+
fake = FakeHttp()
|
|
912
|
+
client = KlingClient(api_key="k", http_client=fake)
|
|
913
|
+
with pytest.raises(ValidationError, match="output_resolution is required"):
|
|
914
|
+
client.motion_control.create(
|
|
915
|
+
model="kling-3.0",
|
|
916
|
+
source_image_url="https://x/s.jpg",
|
|
917
|
+
reference_video_url="https://x/r.mp4",
|
|
918
|
+
)
|
|
919
|
+
assert fake.calls == []
|
|
920
|
+
|
|
921
|
+
|
|
918
922
|
def test_motion_control_create_posts_v26_body():
|
|
919
923
|
fake = FakeHttp({"id": "t26", "status": "pending"})
|
|
920
924
|
client = KlingClient(api_key="k", http_client=fake)
|
|
@@ -934,8 +938,7 @@ def test_motion_control_create_posts_v26_body():
|
|
|
934
938
|
("missing", "message"),
|
|
935
939
|
[
|
|
936
940
|
("output_resolution", "output_resolution is required"),
|
|
937
|
-
("character_orientation", "character_orientation is required"),
|
|
938
|
-
],
|
|
941
|
+
("character_orientation", "character_orientation is required")],
|
|
939
942
|
)
|
|
940
943
|
def test_motion_control_v26_requires_model_fields(missing, message):
|
|
941
944
|
fake = FakeHttp()
|
|
@@ -945,8 +948,7 @@ def test_motion_control_v26_requires_model_fields(missing, message):
|
|
|
945
948
|
"source_image_url": "https://x/s.jpg",
|
|
946
949
|
"reference_video_url": "https://x/r.mp4",
|
|
947
950
|
"output_resolution": "720p",
|
|
948
|
-
"character_orientation": "video"
|
|
949
|
-
}
|
|
951
|
+
"character_orientation": "video"}
|
|
950
952
|
del params[missing]
|
|
951
953
|
|
|
952
954
|
with pytest.raises(ValidationError, match=message):
|
|
@@ -982,13 +984,14 @@ def test_motion_control_get_fetches_by_id():
|
|
|
982
984
|
def test_motion_control_run_narrows_completed_type():
|
|
983
985
|
fake = FakeHttp(
|
|
984
986
|
{"id": "t1", "status": "pending"},
|
|
985
|
-
{"id": "t1", "status": "completed", "videos": [{"url": "https://x/m.mp4"}]},
|
|
987
|
+
{"id": "t1", "status": "completed", "usage": {"cost": 0.05}, "videos": [{"url": "https://x/m.mp4"}]},
|
|
986
988
|
)
|
|
987
989
|
client = KlingClient(api_key="k", http_client=fake)
|
|
988
990
|
result = client.motion_control.run(
|
|
989
991
|
model="kling-3.0",
|
|
990
992
|
source_image_url="https://x/s.jpg",
|
|
991
993
|
reference_video_url="https://x/r.mp4",
|
|
994
|
+
output_resolution="720p",
|
|
992
995
|
)
|
|
993
996
|
assert isinstance(result, CompletedMotionControlResponse)
|
|
994
997
|
assert result.videos[0].url == "https://x/m.mp4"
|
|
@@ -1022,14 +1025,16 @@ def test_motion_control_requires_source_image_url():
|
|
|
1022
1025
|
client = KlingClient(api_key="k", http_client=FakeHttp())
|
|
1023
1026
|
with pytest.raises(ValidationError, match="source_image_url is required"):
|
|
1024
1027
|
client.motion_control.create(
|
|
1025
|
-
model="kling-3.0", reference_video_url="https://x/r.mp4"
|
|
1028
|
+
model="kling-3.0", reference_video_url="https://x/r.mp4", output_resolution="720p"
|
|
1026
1029
|
)
|
|
1027
1030
|
|
|
1028
1031
|
|
|
1029
1032
|
def test_motion_control_requires_reference_video_url():
|
|
1030
1033
|
client = KlingClient(api_key="k", http_client=FakeHttp())
|
|
1031
1034
|
with pytest.raises(ValidationError, match="reference_video_url is required"):
|
|
1032
|
-
client.motion_control.create(
|
|
1035
|
+
client.motion_control.create(
|
|
1036
|
+
model="kling-3.0", source_image_url="https://x/s.jpg", output_resolution="720p"
|
|
1037
|
+
)
|
|
1033
1038
|
|
|
1034
1039
|
|
|
1035
1040
|
def test_text_to_video_non_numeric_duration_raises_validation_error():
|
|
@@ -1058,8 +1063,7 @@ def test_text_to_video_accepts_reference_image_model():
|
|
|
1058
1063
|
"model": "kling-v3-omni-reference",
|
|
1059
1064
|
"prompt": "Keep the subject from the reference image",
|
|
1060
1065
|
"reference_image_urls": ["https://cdn.runapi.ai/public/samples/image.jpg"],
|
|
1061
|
-
"aspect_ratio": "16:9"
|
|
1062
|
-
}
|
|
1066
|
+
"aspect_ratio": "16:9"}
|
|
1063
1067
|
|
|
1064
1068
|
client.text_to_video.create(**params)
|
|
1065
1069
|
assert fake.calls == [("post", "/api/v1/kling/text_to_video", params)]
|
|
@@ -1070,15 +1074,14 @@ def test_edit_video_create_get_and_run_for_edit_model():
|
|
|
1070
1074
|
{"id": "edit-create", "status": "processing"},
|
|
1071
1075
|
{"id": "edit-get", "status": "processing"},
|
|
1072
1076
|
{"id": "edit-run", "status": "processing"},
|
|
1073
|
-
{"id": "edit-run", "status": "completed", "videos": [{"url": "https://file.runapi.ai/edit.mp4"}]},
|
|
1077
|
+
{"id": "edit-run", "status": "completed", "usage": {"cost": 0.05}, "videos": [{"url": "https://file.runapi.ai/edit.mp4"}]},
|
|
1074
1078
|
)
|
|
1075
1079
|
client = KlingClient(api_key="k", http_client=fake)
|
|
1076
1080
|
params = {
|
|
1077
1081
|
"model": "kling-v3-omni-edit",
|
|
1078
1082
|
"prompt": "Turn the source video into a watercolor scene",
|
|
1079
1083
|
"source_video_url": "https://cdn.runapi.ai/public/samples/video.mp4",
|
|
1080
|
-
"aspect_ratio": "auto"
|
|
1081
|
-
}
|
|
1084
|
+
"aspect_ratio": "auto"}
|
|
1082
1085
|
|
|
1083
1086
|
client.edit_video.create(**params)
|
|
1084
1087
|
client.edit_video.get("edit-get")
|
|
@@ -1088,8 +1091,7 @@ def test_edit_video_create_get_and_run_for_edit_model():
|
|
|
1088
1091
|
("post", "/api/v1/kling/edit_video", params),
|
|
1089
1092
|
("get", "/api/v1/kling/edit_video/edit-get", None),
|
|
1090
1093
|
("post", "/api/v1/kling/edit_video", params),
|
|
1091
|
-
("get", "/api/v1/kling/edit_video/edit-run", None)
|
|
1092
|
-
]
|
|
1094
|
+
("get", "/api/v1/kling/edit_video/edit-run", None)]
|
|
1093
1095
|
assert result.status == "completed"
|
|
1094
1096
|
|
|
1095
1097
|
|
|
@@ -1102,8 +1104,7 @@ def test_edit_video_accepts_reference_model_and_requires_model():
|
|
|
1102
1104
|
"source_video_url": "https://cdn.runapi.ai/public/samples/video.mp4",
|
|
1103
1105
|
"reference_image_urls": ["https://cdn.runapi.ai/public/samples/image.jpg"],
|
|
1104
1106
|
"aspect_ratio": "16:9",
|
|
1105
|
-
"enable_sound": False
|
|
1106
|
-
}
|
|
1107
|
+
"enable_sound": False}
|
|
1107
1108
|
|
|
1108
1109
|
client.edit_video.create(**params)
|
|
1109
1110
|
assert fake.calls == [("post", "/api/v1/kling/edit_video", params)]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{runapi_kling-0.3.4 → runapi_kling-0.4.0}/src/runapi/kling/resources/o1_reference_validation.py
RENAMED
|
File without changes
|
|
File without changes
|