runapi-vidu 0.1.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.
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.5
2
+ Name: runapi-vidu
3
+ Version: 0.1.0
4
+ Summary: RunAPI Vidu SDK for image-to-video and reference-to-video workflows in JavaScript, Python, Ruby, Go, Java, and PHP
5
+ Project-URL: Homepage, https://runapi.ai/models/vidu
6
+ Project-URL: Documentation, https://runapi.ai/docs/resources/sdks
7
+ Project-URL: Source, https://github.com/runapi-ai/vidu-sdk
8
+ Project-URL: Issues, https://github.com/runapi-ai/vidu-sdk/issues
9
+ Project-URL: Changelog, https://github.com/runapi-ai/vidu-sdk/blob/main/CHANGELOG.md
10
+ Project-URL: Release Notes, https://github.com/runapi-ai/vidu-sdk/releases/tag/python%2Fv0.1.0
11
+ Author-email: RunAPI <contact@runapi.ai>
12
+ License-Expression: Apache-2.0
13
+ Keywords: api,golang,gradle,java,maven,python,reference-to-video,ruby,runapi,runapi-ai,sdk,typescript,video-api,video-generation,vidu,vidu-ai-api
14
+ Requires-Python: >=3.9
15
+ Requires-Dist: runapi-core~=0.10.1
16
+ Description-Content-Type: text/markdown
17
+
18
+ # Vidu Python SDK for RunAPI
19
+
20
+ Create image-to-video or reference-to-video tasks, retrieve their status, or use `run` to poll until completion. Validation runs on the RunAPI server.
21
+
22
+ ## Install
23
+
24
+ ```sh
25
+ pip install runapi-vidu
26
+ ```
27
+
28
+ ## Quick start
29
+
30
+ Set `RUNAPI_API_KEY` in your environment. Replace the example image URL with a publicly accessible reference image.
31
+
32
+ ```python
33
+ from runapi.vidu import ViduClient
34
+
35
+ client = ViduClient() # reads RUNAPI_API_KEY
36
+ result = client.reference_to_video.run(
37
+ model="vidu-q4-reference-to-video",
38
+ prompt="Animate the referenced scene with a slow camera pan",
39
+ reference_image_urls=["https://cdn.runapi.ai/public/samples/image.jpg"],
40
+ audio=False,
41
+ )
42
+ print(result.videos[0].url)
43
+ ```
44
+
45
+ Use `create` to submit without waiting and `get` to retrieve the task by ID. Reference generation requires a prompt and 1–15 image URLs; it also accepts up to 3 MP3 reference audio URLs. Images must be JPG/JPEG/PNG/WEBP, at most 50 MB each; MP3 references must be 3–12 seconds and at most 50 MB each. Remote file properties are checked during provider processing, so a task can fail asynchronously.
46
+
47
+ See the [API reference](https://runapi.ai/docs/api/vidu/reference-to-video) and [SDK guide](https://runapi.ai/docs/resources/sdks). For current pricing, use the canonical model pages: [image-to-video](https://runapi.ai/models/vidu/q4-image-to-video) and [reference-to-video](https://runapi.ai/models/vidu/q4-reference-to-video).
@@ -0,0 +1,30 @@
1
+ # Vidu Python SDK for RunAPI
2
+
3
+ Create image-to-video or reference-to-video tasks, retrieve their status, or use `run` to poll until completion. Validation runs on the RunAPI server.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ pip install runapi-vidu
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ Set `RUNAPI_API_KEY` in your environment. Replace the example image URL with a publicly accessible reference image.
14
+
15
+ ```python
16
+ from runapi.vidu import ViduClient
17
+
18
+ client = ViduClient() # reads RUNAPI_API_KEY
19
+ result = client.reference_to_video.run(
20
+ model="vidu-q4-reference-to-video",
21
+ prompt="Animate the referenced scene with a slow camera pan",
22
+ reference_image_urls=["https://cdn.runapi.ai/public/samples/image.jpg"],
23
+ audio=False,
24
+ )
25
+ print(result.videos[0].url)
26
+ ```
27
+
28
+ Use `create` to submit without waiting and `get` to retrieve the task by ID. Reference generation requires a prompt and 1–15 image URLs; it also accepts up to 3 MP3 reference audio URLs. Images must be JPG/JPEG/PNG/WEBP, at most 50 MB each; MP3 references must be 3–12 seconds and at most 50 MB each. Remote file properties are checked during provider processing, so a task can fail asynchronously.
29
+
30
+ See the [API reference](https://runapi.ai/docs/api/vidu/reference-to-video) and [SDK guide](https://runapi.ai/docs/resources/sdks). For current pricing, use the canonical model pages: [image-to-video](https://runapi.ai/models/vidu/q4-image-to-video) and [reference-to-video](https://runapi.ai/models/vidu/q4-reference-to-video).
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "runapi-vidu"
7
+ version = "0.1.0"
8
+ description = "RunAPI Vidu SDK for image-to-video and reference-to-video workflows in JavaScript, Python, Ruby, Go, Java, and PHP"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "RunAPI", email = "contact@runapi.ai" }]
13
+ keywords = ["runapi", "runapi-ai", "vidu", "api", "sdk", "typescript", "python", "ruby", "golang", "java", "maven", "gradle", "video-generation", "reference-to-video", "video-api", "vidu-ai-api"]
14
+ dependencies = ["runapi-core~=0.10.1"]
15
+
16
+ [project.urls]
17
+ Homepage = "https://runapi.ai/models/vidu"
18
+ Documentation = "https://runapi.ai/docs/resources/sdks"
19
+ Source = "https://github.com/runapi-ai/vidu-sdk"
20
+ Issues = "https://github.com/runapi-ai/vidu-sdk/issues"
21
+ Changelog = "https://github.com/runapi-ai/vidu-sdk/blob/main/CHANGELOG.md"
22
+ "Release Notes" = "https://github.com/runapi-ai/vidu-sdk/releases/tag/python%2Fv0.1.0"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["src/runapi"]
26
+
27
+ [tool.uv]
28
+ package = true
29
+
30
+ [dependency-groups]
31
+ dev = ["pytest>=8"]
32
+
33
+ [tool.runapi]
34
+ slug = "vidu"
@@ -0,0 +1,24 @@
1
+ """Vidu client for RunAPI."""
2
+
3
+ from runapi.core import (
4
+ AuthenticationError,
5
+ InsufficientCreditsError,
6
+ NotFoundError,
7
+ RateLimitError,
8
+ TaskFailedError,
9
+ TaskTimeoutError,
10
+ ValidationError,
11
+ )
12
+
13
+ from .client import ViduClient
14
+
15
+ __all__ = [
16
+ "ViduClient",
17
+ "AuthenticationError",
18
+ "RateLimitError",
19
+ "InsufficientCreditsError",
20
+ "NotFoundError",
21
+ "ValidationError",
22
+ "TaskFailedError",
23
+ "TaskTimeoutError",
24
+ ]
@@ -0,0 +1,20 @@
1
+ """Vidu client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import ProviderClient
8
+
9
+ from .resources.image_to_video import ImageToVideo
10
+ from .resources.reference_to_video import ReferenceToVideo
11
+
12
+
13
+ class ViduClient(ProviderClient):
14
+ """Vidu image-to-video and reference-to-video client."""
15
+
16
+ def __init__(self, api_key: Optional[str] = None, **options: Any) -> None:
17
+ super().__init__(api_key, **options)
18
+ http = self._http
19
+ self.image_to_video = ImageToVideo(http)
20
+ self.reference_to_video = ReferenceToVideo(http)
File without changes
@@ -0,0 +1,4 @@
1
+ from .image_to_video import ImageToVideo
2
+ from .reference_to_video import ReferenceToVideo
3
+
4
+ __all__ = ["ImageToVideo", "ReferenceToVideo"]
@@ -0,0 +1,56 @@
1
+ """Vidu image-to-video resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import Resource, RequestOptions
8
+
9
+ from ..types import (
10
+ CompletedImageToVideoResponse,
11
+ ImageToVideoResponse,
12
+ )
13
+
14
+
15
+ class ImageToVideo(Resource):
16
+ """Generate videos from a first-frame image with Vidu models."""
17
+
18
+ ENDPOINT = "/api/v1/vidu/image_to_video"
19
+
20
+ RESPONSE_CLASS = ImageToVideoResponse
21
+ COMPLETED_RESPONSE_CLASS = CompletedImageToVideoResponse
22
+
23
+ def run(self, options: Optional[RequestOptions] = None, **params: Any) -> Any:
24
+ """Create an image-to-video task and poll until it completes.
25
+
26
+ Args:
27
+ **params: Image-to-video parameters (model, first_frame_image_url, ...).
28
+
29
+ Returns:
30
+ The completed task with videos.
31
+ """
32
+ task = self.create(options=options, **params)
33
+ return self._poll_until_complete(lambda: self.get(task.id, options=options))
34
+
35
+ def create(self, options: Optional[RequestOptions] = None, **params: Any) -> Any:
36
+ """Create an image-to-video task and return immediately with an ``id``.
37
+
38
+ Args:
39
+ **params: Image-to-video parameters (model, first_frame_image_url, ...).
40
+
41
+ Returns:
42
+ The task creation result with an id.
43
+ """
44
+ compacted = self._compact_params(params)
45
+ return self._request("post", self.ENDPOINT, body=compacted, options=options)
46
+
47
+ def get(self, id: str, options: Optional[RequestOptions] = None) -> Any:
48
+ """Fetch the current status of an image-to-video task.
49
+
50
+ Args:
51
+ id: The task id.
52
+
53
+ Returns:
54
+ The current task status.
55
+ """
56
+ return self._request("get", f"{self.ENDPOINT}/{id}", options=options)
@@ -0,0 +1,56 @@
1
+ """Vidu reference-to-video resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from runapi.core import Resource, RequestOptions
8
+
9
+ from ..types import (
10
+ CompletedReferenceToVideoResponse,
11
+ ReferenceToVideoResponse,
12
+ )
13
+
14
+
15
+ class ReferenceToVideo(Resource):
16
+ """Generate videos from a first-frame image with Vidu models."""
17
+
18
+ ENDPOINT = "/api/v1/vidu/reference_to_video"
19
+
20
+ RESPONSE_CLASS = ReferenceToVideoResponse
21
+ COMPLETED_RESPONSE_CLASS = CompletedReferenceToVideoResponse
22
+
23
+ def run(self, options: Optional[RequestOptions] = None, **params: Any) -> Any:
24
+ """Create an reference-to-video task and poll until it completes.
25
+
26
+ Args:
27
+ **params: Image-to-video parameters (model, reference_image_urls, ...).
28
+
29
+ Returns:
30
+ The completed task with videos.
31
+ """
32
+ task = self.create(options=options, **params)
33
+ return self._poll_until_complete(lambda: self.get(task.id, options=options))
34
+
35
+ def create(self, options: Optional[RequestOptions] = None, **params: Any) -> Any:
36
+ """Create an reference-to-video task and return immediately with an ``id``.
37
+
38
+ Args:
39
+ **params: Image-to-video parameters (model, reference_image_urls, ...).
40
+
41
+ Returns:
42
+ The task creation result with an id.
43
+ """
44
+ compacted = self._compact_params(params)
45
+ return self._request("post", self.ENDPOINT, body=compacted, options=options)
46
+
47
+ def get(self, id: str, options: Optional[RequestOptions] = None) -> Any:
48
+ """Fetch the current status of an reference-to-video task.
49
+
50
+ Args:
51
+ id: The task id.
52
+
53
+ Returns:
54
+ The current task status.
55
+ """
56
+ return self._request("get", f"{self.ENDPOINT}/{id}", options=options)
@@ -0,0 +1,32 @@
1
+ """Vidu model lists, enums, and response models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from runapi.core import BaseModel, TaskResponse, optional, required
6
+
7
+
8
+
9
+ class MediaUrl(BaseModel):
10
+ url = optional(str)
11
+
12
+
13
+ class VideoResponse(TaskResponse):
14
+ """Response for a video generation task."""
15
+
16
+ id = required(str)
17
+ status = optional(str, enum=lambda: TaskResponse.Status.ALL)
18
+ videos = optional([lambda: MediaUrl])
19
+ error = optional(str)
20
+
21
+
22
+ class CompletedVideoResponse(VideoResponse):
23
+ """Narrowed response from ``run()`` once polling observes completion."""
24
+
25
+ videos = required([lambda: MediaUrl])
26
+
27
+
28
+ ImageToVideoResponse = VideoResponse
29
+ CompletedImageToVideoResponse = CompletedVideoResponse
30
+
31
+ ReferenceToVideoResponse = VideoResponse
32
+ CompletedReferenceToVideoResponse = CompletedVideoResponse
@@ -0,0 +1,26 @@
1
+ import pytest
2
+ from runapi.vidu import ViduClient
3
+
4
+ class FakeHttp:
5
+ def __init__(self, *responses):
6
+ self.responses = list(responses)
7
+ self.calls = []
8
+ def request(self, method, path, body=None, options=None):
9
+ self.calls.append((method, path, body))
10
+ return self.responses.pop(0)
11
+
12
+ @pytest.mark.parametrize("resource,fields", [
13
+ ("image_to_video", {"first_frame_image_url": "https://x/image.jpg"}),
14
+ ("reference_to_video", {"reference_image_urls": ["https://x/1.jpg", "https://x/2.jpg"], "reference_audio_urls": ["https://x/a.mp3"], "aspect_ratio": "16:9"}),
15
+ ])
16
+ def test_create_get_and_run(resource, fields):
17
+ completed = {"id": "t1", "status": "completed", "videos": [{"url": "https://x/v.mp4"}]}
18
+ fake = FakeHttp({"id": "t1", "status": "pending"}, completed, {"id": "t1", "status": "pending"}, completed)
19
+ client = ViduClient(api_key="test", http_client=fake)
20
+ api = getattr(client, resource)
21
+ params = dict(model="vidu-q4-" + resource.replace("_", "-"), prompt="animate", duration_seconds=5, output_resolution="720p", audio=False, callback_url="https://x/callback", **fields)
22
+ assert api.create(**params).id == "t1"
23
+ assert fake.calls[0] == ("post", "/api/v1/vidu/" + resource, params)
24
+ assert api.get("t1").videos[0].url == "https://x/v.mp4"
25
+ assert fake.calls[1] == ("get", "/api/v1/vidu/" + resource + "/t1", None)
26
+ assert api.run(**params).videos[0].url == "https://x/v.mp4"