VibesAI-api 1.3.2__py3-none-any.whl

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,206 @@
1
+ """
2
+ Ingredient helpers — build the payload objects that the Vibes generation
3
+ endpoints expect for applying (or inline-creating) characters, styles,
4
+ and scenes.
5
+
6
+ There are three ingredient types in Vibes:
7
+
8
+ - CHARACTER (UI label: "Character") → attaches via ``orefImageHandle``
9
+ - STYLE (UI label: "Style") → attaches via ``srefImageHandle``
10
+ - SETTING (UI label: "Scene") → attaches via ``settingImageHandles``
11
+
12
+ For each, there are three ways to reference the ingredient in a generation:
13
+
14
+ 1. By existing ingredient ID (use ``IngredientRef.by_id()``).
15
+ → goes in the ``ingredients`` array on the request body.
16
+
17
+ 2. By image entity ID of an uploaded image (use ``CreateIngredient.by_image_ent_id()``).
18
+ → goes in the ``createIngredients`` array. The server creates a new
19
+ ingredient record on the fly and attaches it.
20
+
21
+ 3. By name only (use ``CreateIngredient.by_name()``).
22
+ → also goes in ``createIngredients``. The server uses the prompt-
23
+ generated image as the ingredient image.
24
+
25
+ These helpers build the correct dict shape so you don't have to remember
26
+ the snake_case / camelCase quirks of the API.
27
+
28
+ Example
29
+ -------
30
+ from vibes_api import VibesClient, IngredientType
31
+ from vibes_api.ingredients import IngredientRef, CreateIngredient
32
+
33
+ client = VibesClient(meta_session="...")
34
+
35
+ # Use an existing character from your library
36
+ character = IngredientRef.by_id(
37
+ ingredient_id="800957099700717",
38
+ ingredient_type=IngredientType.CHARACTER,
39
+ name="Valdrin",
40
+ image_url="https://...",
41
+ )
42
+
43
+ # Create a new style on-the-fly from an uploaded image
44
+ style = CreateIngredient.by_image_ent_id(
45
+ image_ent_id="1177...",
46
+ ingredient_type=IngredientType.STYLE,
47
+ name="Cyberpunk neon",
48
+ image_url="https://...",
49
+ )
50
+
51
+ batch = client.generate_video(
52
+ project_id=project["id"],
53
+ prompt="...",
54
+ ingredients=[character],
55
+ create_ingredients=[style],
56
+ )
57
+ """
58
+
59
+ from __future__ import annotations
60
+
61
+ from typing import Optional, Union
62
+
63
+ from .models import IngredientType
64
+
65
+
66
+ def _coerce_type(t: Union[str, IngredientType]) -> str:
67
+ """Coerce IngredientType enum to its string value."""
68
+ if hasattr(t, "value"):
69
+ return t.value
70
+ return str(t)
71
+
72
+
73
+ class IngredientRef:
74
+ """Builder for an EXISTING ingredient reference (by ingredientId).
75
+
76
+ Use this when you've already saved an ingredient in your library
77
+ (via the Vibes UI or via ``client.create_ingredient()``).
78
+ """
79
+
80
+ @staticmethod
81
+ def by_id(
82
+ *,
83
+ ingredient_id: str,
84
+ ingredient_type: Union[str, IngredientType],
85
+ name: str,
86
+ image_url: str,
87
+ ) -> dict:
88
+ """Reference an existing ingredient by its ID.
89
+
90
+ Parameters
91
+ ----------
92
+ ingredient_id : str
93
+ The ``ingredientId`` from ``client.list_ingredients()``.
94
+ ingredient_type : str | IngredientType
95
+ One of CHARACTER, STYLE, SETTING.
96
+ name : str
97
+ Display name (matches the ingredient's name in the library).
98
+ image_url : str
99
+ URL of the ingredient's image. Used as a thumbnail.
100
+ """
101
+ return {
102
+ "ingredientId": ingredient_id,
103
+ "ingredientType": _coerce_type(ingredient_type),
104
+ "name": name,
105
+ "imageUrl": image_url,
106
+ }
107
+
108
+
109
+ class CreateIngredient:
110
+ """Builder for an INLINE ingredient creation (no pre-existing ingredient).
111
+
112
+ Use this when you want the server to create a new ingredient on-the-fly
113
+ during generation. There are two flavors:
114
+
115
+ - ``by_image_ent_id()`` — create from an already-uploaded image
116
+ (you've called ``client.upload_image()`` first).
117
+ - ``by_name()`` — create by name only; the server uses the prompt-
118
+ generated image as the ingredient image.
119
+ """
120
+
121
+ @staticmethod
122
+ def by_image_ent_id(
123
+ *,
124
+ image_ent_id: str,
125
+ ingredient_type: Union[str, IngredientType],
126
+ name: str,
127
+ image_url: str,
128
+ ) -> dict:
129
+ """Create a new ingredient from an uploaded image.
130
+
131
+ Parameters
132
+ ----------
133
+ image_ent_id : str
134
+ The ``imageEntId`` from ``client.upload_image()`` or
135
+ ``client.upload_image_file()``.
136
+ ingredient_type : str | IngredientType
137
+ CHARACTER, STYLE, or SETTING.
138
+ name : str
139
+ Display name for the new ingredient.
140
+ image_url : str
141
+ URL of the uploaded image (returned alongside imageEntId).
142
+ """
143
+ return {
144
+ "sourceImageEntId": image_ent_id,
145
+ "ingredientType": _coerce_type(ingredient_type),
146
+ "name": name,
147
+ "imageUrl": image_url,
148
+ }
149
+
150
+ @staticmethod
151
+ def by_name(
152
+ *,
153
+ ingredient_type: Union[str, IngredientType],
154
+ name: str,
155
+ ) -> dict:
156
+ """Create a new ingredient by name only.
157
+
158
+ The server will use the image generated by the prompt as the
159
+ ingredient image. This is the simplest form — useful for the
160
+ timeline chat assistant.
161
+ """
162
+ return {
163
+ "ingredientType": _coerce_type(ingredient_type),
164
+ "name": name,
165
+ }
166
+
167
+
168
+ def build_ingredient_payload(
169
+ *,
170
+ ingredients: Optional[list] = None,
171
+ create_ingredients: Optional[list] = None,
172
+ character: Optional[dict] = None,
173
+ style: Optional[dict] = None,
174
+ scene: Optional[dict] = None,
175
+ ) -> dict:
176
+ """Convenience builder: combine character/style/scene refs into a payload.
177
+
178
+ Pass either ``ingredients=[...]`` and ``create_ingredients=[...]``
179
+ (already-built payload dicts), or the convenience parameters
180
+ ``character=...``, ``style=...``, ``scene=...`` (each can be either
181
+ an ``IngredientRef`` or ``CreateIngredient`` dict — this function
182
+ will route it to the correct array based on its keys).
183
+
184
+ Returns
185
+ -------
186
+ dict
187
+ ``{"ingredients": [...], "createIngredients": [...]}`` —
188
+ ready to spread into a generation request body.
189
+ """
190
+ final_ingredients = list(ingredients or [])
191
+ final_create = list(create_ingredients or [])
192
+
193
+ for ing in (character, style, scene):
194
+ if ing is None:
195
+ continue
196
+ if "ingredientId" in ing:
197
+ final_ingredients.append(ing)
198
+ else:
199
+ final_create.append(ing)
200
+
201
+ payload: dict = {}
202
+ if final_ingredients:
203
+ payload["ingredients"] = final_ingredients
204
+ if final_create:
205
+ payload["createIngredients"] = final_create
206
+ return payload
vibes_api/models.py ADDED
@@ -0,0 +1,165 @@
1
+ """
2
+ Enums and constants for the Vibes API client.
3
+
4
+ All values are taken directly from the vibes.ai Next.js bundles.
5
+ """
6
+
7
+ from enum import Enum
8
+
9
+
10
+ class AspectRatio(str, Enum):
11
+ """Supported aspect ratios for image / video generation.
12
+
13
+ Only three ratios are actually supported by the server (verified live):
14
+ 1:1, 9:16, and 16:9. Other values will be rejected with
15
+ ``GENERATION_FAILED``.
16
+ """
17
+
18
+ SQUARE = "1:1" # 1280x1280 for images
19
+ PORTRAIT = "9:16" # 720x1280 (default in UI)
20
+ LANDSCAPE = "16:9" # 1280x720
21
+
22
+
23
+ class Resolution(str, Enum):
24
+ """Supported output resolutions (shown under "Advanced" in the UI)."""
25
+
26
+ P480 = "480p"
27
+ P720 = "720p"
28
+
29
+
30
+ class VideoModel(str, Enum):
31
+ """Available video generation models.
32
+
33
+ Selecting the right model is important — different generation types
34
+ require different models:
35
+
36
+ - ``midjen-short`` → text-to-video (t2v) and image-to-video (i2v)
37
+ - ``midjen-extend`` → video extension (auto/manual extend)
38
+ - ``midjen-video-edit`` → video-to-video editing (v2v)
39
+ - ``lipsync`` family → lip-sync generation
40
+ """
41
+
42
+ SHORT = "midjen-short"
43
+ EXTEND = "midjen-extend"
44
+ VIDEO_EDIT = "midjen-video-edit"
45
+ LIPSYNC = "lipsync"
46
+ LIPSYNC_ASYNC = "midjen-lipsync-async"
47
+ LIPSYNC_EXP = "midjen-lipsync-exp"
48
+ LIPSYNC_DIRECT = "midjen-lipsync-direct"
49
+
50
+
51
+ class ImageModel(str, Enum):
52
+ """Available image generation models."""
53
+
54
+ BASE = "midjen-base"
55
+
56
+
57
+ class PromptModel(str, Enum):
58
+ """LLM used for prompt enhancement / parsing."""
59
+
60
+ GEMINI_FLASH = "gemini-2.5-flash"
61
+
62
+
63
+ class GenerationType(str, Enum):
64
+ """Generation type discriminator (sent in the ``config.generationType`` field).
65
+
66
+ The server uses this to route the request to the correct pipeline:
67
+
68
+ - ``t2v`` → text-to-video
69
+ - ``t2i`` → text-to-image
70
+ - ``i2v`` → image-to-video (start frame uploaded or selected)
71
+ - ``extend`` → extend an existing video clip (auto or manual)
72
+ - ``v2v`` → video-to-video editing
73
+ - ``lipsync`` → lip-sync generation
74
+ """
75
+
76
+ TEXT_TO_VIDEO = "t2v"
77
+ TEXT_TO_IMAGE = "t2i"
78
+ IMAGE_TO_VIDEO = "i2v"
79
+ EXTEND = "extend"
80
+ VIDEO_TO_VIDEO = "v2v"
81
+ LIPSYNC = "lipsync"
82
+
83
+
84
+ class IngredientType(str, Enum):
85
+ """Type of studio ingredient.
86
+
87
+ The three types map to UI sections in the Ingredients panel:
88
+ Characters, Styles, Scenes (internally "SETTING").
89
+ """
90
+
91
+ CHARACTER = "CHARACTER"
92
+ STYLE = "STYLE"
93
+ SETTING = "SETTING" # "Scene" in the UI
94
+
95
+
96
+ class OwnerFilter(str, Enum):
97
+ """Filter for /api/studio/ingredients."""
98
+
99
+ LIBRARY = "LIBRARY" # User's saved ingredients
100
+ VIEWER = "VIEWER" # Ingredients visible to current viewer
101
+
102
+
103
+ class VoicePreset(str, Enum):
104
+ """Built-in TTS voices.
105
+
106
+ 41 voices are available — these are the most common. Use
107
+ ``client.list_voices()`` to get the full up-to-date list.
108
+ """
109
+
110
+ MARISOL = "play_ai_Marisol"
111
+ GEORGE_WASHINGTON = "play_ai_1P_George_Washington"
112
+ ABRAHAM_LINCOLN = "play_ai_1P_Abraham_Lincoln"
113
+ JANE_AUSTEN = "play_ai_1P_Jane_Austen"
114
+ SERAPHINE = "play_ai_1P_Seraphine"
115
+ CELESTE = "play_ai_Celeste"
116
+ NIGEL = "play_ai_Nigel"
117
+ CONOR = "play_ai_Conor"
118
+
119
+
120
+ class TextOverlayPreset(str, Enum):
121
+ """Effect presets for text overlays on the timeline."""
122
+
123
+ FADE = "fade"
124
+ SLIDE_UP = "slide-up"
125
+ SURROUND = "surround"
126
+ STRANGE = "strange"
127
+ FLASH = "flash"
128
+ SLIDE = "slide"
129
+ CINEFADE = "cinefade"
130
+ GLOW = "glow"
131
+ TYPEWRITER = "typewriter"
132
+ HIGHLIGHT = "highlight"
133
+ GLITCH = "glitch"
134
+
135
+
136
+ class TextOverlayPosition(str, Enum):
137
+ """Position presets for text overlays on the timeline."""
138
+
139
+ CENTER = "center"
140
+ TOP = "top"
141
+ BOTTOM = "bottom"
142
+ LEFT = "left"
143
+ RIGHT = "right"
144
+ TOP_LEFT = "top-left"
145
+ TOP_RIGHT = "top-right"
146
+ BOTTOM_LEFT = "bottom-left"
147
+ BOTTOM_RIGHT = "bottom-right"
148
+
149
+
150
+ class SyncMode(str, Enum):
151
+ """Modes used by the /api/sync endpoint (server-sent events).
152
+
153
+ The UI uses these to coordinate real-time collaboration. ``polling``
154
+ falls back to GET requests; ``sse`` opens an EventSource stream.
155
+ """
156
+
157
+ POLLING = "polling"
158
+ SSE = "sse"
159
+
160
+
161
+ class EntityType(str, Enum):
162
+ """Entity types accepted by /api/share-links, /api/sync, /api/collaborators."""
163
+
164
+ PROJECT = "project"
165
+ CONTENT_ITEM = "content-item"