ixspy-ai-api 1.0.1__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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 IXSPY Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: ixspy-ai-api
3
+ Version: 1.0.1
4
+ Summary: A client of IXSPY AI Api
5
+ Home-page: https://github.com/ixspyinc/ixspy-ai-api-python
6
+ Author: IXSPY Team
7
+ Author-email: tech@ixspy.com
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3.5
10
+ Classifier: Programming Language :: Python :: 3.6
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: requests>=2
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: keywords
28
+ Dynamic: license
29
+ Dynamic: license-file
30
+ Dynamic: requires-dist
31
+ Dynamic: summary
32
+
33
+ # IXSPY AI API
34
+
35
+ IXSPY AI API V1.0 official python version
36
+
37
+ ## README.md
38
+
39
+ ## Installation
40
+
41
+ 1. pypi install
42
+ ```BASH
43
+ pip install ixspy-ai-api
44
+ ```
45
+
46
+ 2. Source code install
47
+ ```BASH
48
+ git clone https://github.com/ixspyinc/ixspy-ai-api-python.git
49
+ cd ixspy-ai-api-python
50
+ python setup.py install
51
+ ```
52
+
53
+ ## Usage
54
+
55
+ Basic usage
56
+ ```python
57
+ import os
58
+ import sys
59
+ from ixspy_ai_api import ImageClient
60
+
61
+ # 分步骤调用, 任务方法和参数都已约定好
62
+
63
+ API_KEY = 'YOUR_KEY'
64
+ FOLDER_PATH = os.path.dirname(os.path.abspath(sys.argv[0])) + os.sep
65
+ original_image_path = FOLDER_PATH + 'images/speaker.jpg'
66
+
67
+ client = ImageClient(api_key=API_KEY)
68
+
69
+ task_id = client.create_custom_composition(
70
+ original_image=original_image_path,
71
+ prompt="移除产品背景,只保留白色背景产品图",
72
+ )
73
+ print(f"任务ID: {task_id}")
74
+
75
+ # 轮询等待完成
76
+ result = client.wait_for_completion(task_id, poll_interval=3, timeout=180)
77
+
78
+ # 可和预生成的图片 examples/images/demo_result_create_custom_composition.png 对比
79
+ print("标清图URL:", result['sd_image_url'])
80
+
81
+ # 高清圖需要額外時間,這裏選擇多等待半分鐘
82
+ print('等待半分钟后获取高清图')
83
+ time.sleep(30)
84
+
85
+ # 获取高清图
86
+ hd_url = client.get_hd_image(task_id)
87
+ print("高清图URL:", hd_url)
88
+
89
+ ```
90
+
91
+ Advance use
92
+
93
+ For detailed usage, please refer to the files in the /examples directory.
94
+
95
+
96
+
97
+ ## API document
98
+ https://img.ixspy.com/api-doc.html
@@ -0,0 +1,66 @@
1
+ # IXSPY AI API
2
+
3
+ IXSPY AI API V1.0 official python version
4
+
5
+ ## README.md
6
+
7
+ ## Installation
8
+
9
+ 1. pypi install
10
+ ```BASH
11
+ pip install ixspy-ai-api
12
+ ```
13
+
14
+ 2. Source code install
15
+ ```BASH
16
+ git clone https://github.com/ixspyinc/ixspy-ai-api-python.git
17
+ cd ixspy-ai-api-python
18
+ python setup.py install
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Basic usage
24
+ ```python
25
+ import os
26
+ import sys
27
+ from ixspy_ai_api import ImageClient
28
+
29
+ # 分步骤调用, 任务方法和参数都已约定好
30
+
31
+ API_KEY = 'YOUR_KEY'
32
+ FOLDER_PATH = os.path.dirname(os.path.abspath(sys.argv[0])) + os.sep
33
+ original_image_path = FOLDER_PATH + 'images/speaker.jpg'
34
+
35
+ client = ImageClient(api_key=API_KEY)
36
+
37
+ task_id = client.create_custom_composition(
38
+ original_image=original_image_path,
39
+ prompt="移除产品背景,只保留白色背景产品图",
40
+ )
41
+ print(f"任务ID: {task_id}")
42
+
43
+ # 轮询等待完成
44
+ result = client.wait_for_completion(task_id, poll_interval=3, timeout=180)
45
+
46
+ # 可和预生成的图片 examples/images/demo_result_create_custom_composition.png 对比
47
+ print("标清图URL:", result['sd_image_url'])
48
+
49
+ # 高清圖需要額外時間,這裏選擇多等待半分鐘
50
+ print('等待半分钟后获取高清图')
51
+ time.sleep(30)
52
+
53
+ # 获取高清图
54
+ hd_url = client.get_hd_image(task_id)
55
+ print("高清图URL:", hd_url)
56
+
57
+ ```
58
+
59
+ Advance use
60
+
61
+ For detailed usage, please refer to the files in the /examples directory.
62
+
63
+
64
+
65
+ ## API document
66
+ https://img.ixspy.com/api-doc.html
@@ -0,0 +1,3 @@
1
+ from .ai_client import AIClient, APIError
2
+ from .image_client import ImageClient
3
+ from .video_client import VideoClient
@@ -0,0 +1,150 @@
1
+ """
2
+ AI 图像/视频生成 Python SDK
3
+ - 基类: AIClient (通用请求、认证、图片上传)
4
+ - 图片客户端: ImageClient (9种作图、状态轮询、高清图、任务列表)
5
+ - 视频客户端: VideoClient (视频生成、状态轮询、任务列表)
6
+ """
7
+
8
+ import os
9
+ import time
10
+ from typing import Dict, Any, List, Optional, Union
11
+ from pathlib import Path
12
+
13
+ import requests
14
+
15
+
16
+ class APIError(Exception):
17
+ """API 调用异常"""
18
+ def __init__(self, code: int, message: str, time: int):
19
+ self.code = code
20
+ self.message = message
21
+ self.time = time
22
+ super().__init__(f"API Error {code}: {message}")
23
+
24
+
25
+ class AIClient:
26
+ """AI 服务基础客户端,封装通用 HTTP 请求和图片上传"""
27
+
28
+ BASE_URL = "https://ixspy.com/ai-tool/api"
29
+
30
+ def __init__(self, api_key: str, base_url: Optional[str] = None):
31
+ """
32
+ 初始化基础客户端
33
+
34
+ Args:
35
+ api_key: API 密钥,从控制台获取
36
+ base_url: 可选的自定义基础地址
37
+ """
38
+ self.api_key = api_key
39
+ self.base_url = (base_url or self.BASE_URL).rstrip('/')
40
+ self.session = requests.Session()
41
+ self.session.headers.update({
42
+ "Authorization": f"Bearer {self.api_key}"
43
+ })
44
+
45
+ def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]:
46
+ """
47
+ 发送 HTTP 请求并解析统一响应格式
48
+
49
+ Returns:
50
+ 响应中的 data 字段
51
+
52
+ Raises:
53
+ APIError: 当 error.code != 0 时抛出
54
+ """
55
+ url = f"{self.base_url}{endpoint}"
56
+ # 根据请求类型自动设置 Content-Type
57
+ if 'files' in kwargs:
58
+ # multipart/form-data,让 requests 自动处理
59
+ pass
60
+ elif 'json' in kwargs:
61
+ kwargs.setdefault('headers', {})['Content-Type'] = 'application/json'
62
+ elif 'data' in kwargs and not kwargs.get('files'):
63
+ # application/x-www-form-urlencoded
64
+ kwargs.setdefault('headers', {})['Content-Type'] = 'application/x-www-form-urlencoded'
65
+
66
+ response = self.session.request(method, url, **kwargs)
67
+ try:
68
+ resp_json = response.json()
69
+ except ValueError:
70
+ raise APIError(-1, f"Invalid JSON response: {response.text[:200]}", 0)
71
+
72
+ error = resp_json.get('error', {})
73
+ code = error.get('code', -1)
74
+ if code != 0:
75
+ raise APIError(
76
+ code=code,
77
+ message=error.get('message', 'Unknown error'),
78
+ time=error.get('time', 0)
79
+ )
80
+ return resp_json.get('data', {})
81
+
82
+ # ---------- 图片上传(公用) ----------
83
+ def upload_image_file(self, file_path: Union[str, Path]) -> str:
84
+ """
85
+ 上传本地图片文件(文件模式)
86
+
87
+ Args:
88
+ file_path: 本地图片路径
89
+
90
+ Returns:
91
+ CDN 图片 URL
92
+ """
93
+ file_path = str(file_path)
94
+ with open(file_path, 'rb') as f:
95
+ files = {'image': (os.path.basename(file_path), f)}
96
+ data = self._request('POST', '/v1/images/upload', files=files)
97
+ return data['url']
98
+
99
+ def upload_image_base64(self, base64_str: str) -> str:
100
+ """
101
+ 上传 Base64 编码的图片(Base64 模式)
102
+
103
+ Args:
104
+ base64_str: Base64 字符串,可带 data:image/... 前缀
105
+
106
+ Returns:
107
+ CDN 图片 URL
108
+ """
109
+ payload = {"image_base64": base64_str}
110
+ data = self._request('POST', '/v1/images/upload', json=payload)
111
+ return data['url']
112
+
113
+ def _prepare_single_image(self, image_input: Union[str, Path]) -> str:
114
+ """
115
+ 将单个图片输入标准化为 CDN URL(自动上传本地文件或 Base64)
116
+
117
+ Args:
118
+ image_input: 本地路径、Base64 字符串或已有 URL
119
+
120
+ Returns:
121
+ CDN URL
122
+ """
123
+ input_str = str(image_input)
124
+ # 已经是 URL
125
+ if input_str.startswith(('http://', 'https://')):
126
+ return input_str
127
+ # 可能是 Base64
128
+ if input_str.startswith('data:image') or (len(input_str) > 100 and '/' not in input_str[:50]):
129
+ return self.upload_image_base64(input_str)
130
+ # 本地文件路径
131
+ if os.path.exists(input_str):
132
+ return self.upload_image_file(input_str)
133
+ # 未知格式,直接返回原值(让服务端判断)
134
+ return input_str
135
+
136
+ def _prepare_images(self, images: Union[str, Path, List[Union[str, Path]]]) -> Union[str, List[str]]:
137
+ """
138
+ 批量标准化图片输入
139
+
140
+ Args:
141
+ images: 单个图片或图片列表
142
+
143
+ Returns:
144
+ 单个 URL 字符串或 URL 列表
145
+ """
146
+ if isinstance(images, (str, Path)):
147
+ return self._prepare_single_image(images)
148
+ if isinstance(images, list):
149
+ return [self._prepare_single_image(img) for img in images]
150
+ raise ValueError("images 必须是字符串、Path对象或列表")
@@ -0,0 +1,309 @@
1
+ """
2
+ AI 图像/视频生成 Python SDK
3
+ - 基类: AIClient (通用请求、认证、图片上传)
4
+ - 图片客户端: ImageClient (9种作图、状态轮询、高清图、任务列表)
5
+ - 视频客户端: VideoClient (视频生成、状态轮询、任务列表)
6
+ """
7
+
8
+ import os
9
+ import time
10
+ from typing import Dict, Any, List, Optional, Union
11
+ from pathlib import Path
12
+ from ixspy_ai_api import AIClient, APIError
13
+
14
+ class ImageClient(AIClient):
15
+ """AI 图像生成客户端"""
16
+
17
+ # 自由构图-多图
18
+ TYPE_CUSTOM_COMPOSITION_MULTI = 'custom_composition_multi'
19
+
20
+ # 自由构图
21
+ TYPE_CUSTOM_COMPOSITION = 'custom_composition'
22
+
23
+ # 场景替换
24
+ TYPE_SCENE_REPLACEMENT = 'scene_replacement'
25
+
26
+ # 商品替换
27
+ TYPE_PRODUCT_REPLACEMENT = 'product_replacement'
28
+
29
+ # 商品换色
30
+ TYPE_PRODUCT_RECOLORING = 'product_recoloring'
31
+
32
+ # 局部重绘
33
+ TYPE_PARTIAL_REDRAW = 'partial_redraw'
34
+
35
+ # 智能延展
36
+ TYPE_SMART_EXPAND = 'smart_expand'
37
+
38
+ # 图片翻译
39
+ TYPE_TRANSLATION = 'translation'
40
+
41
+ # AI超清-2K
42
+ TYPE_AI_UPSCALE_2K = 'ai_upscale_2k'
43
+
44
+ # ---------- 发起作图任务(通用 + 便捷方法) ----------
45
+ def create_task(self, task_type: str, **kwargs) -> int:
46
+ """
47
+ 通用作图方法
48
+
49
+ Args:
50
+ task_type: 作图类型,可选值见文档
51
+ **kwargs: 特定参数,需包含 original_image 及其他类型所需参数
52
+
53
+ Returns:
54
+ task_id
55
+ """
56
+ # 预处理 original_image
57
+ if 'original_image' in kwargs:
58
+ kwargs['original_image'] = self._prepare_images(kwargs['original_image'])
59
+ # 预处理 reference_image(某些类型需要)
60
+ if 'reference_image' in kwargs:
61
+ kwargs['reference_image'] = self._prepare_single_image(kwargs['reference_image'])
62
+
63
+ endpoint = f"/v1/images/generations/{task_type}"
64
+ data = self._request('POST', endpoint, json=kwargs)
65
+ return int(data['task_id'])
66
+
67
+ # ----- 自由构图-多图 -----
68
+ def create_custom_composition_multi(self,
69
+ original_images: List[Union[str, Path]],
70
+ prompt: str,
71
+ ratios: str = "auto") -> int:
72
+ """
73
+ 自由构图-多图(支持最多5张图片)
74
+
75
+ :param original_images: 原图列表(文件路径、URL或Base64),最多5张
76
+ :param prompt: 画面描述
77
+ :param ratios: 图片比例,默认 "auto"
78
+ :return: 任务ID
79
+ """
80
+ return self.create_task(
81
+ ImageClient.TYPE_CUSTOM_COMPOSITION_MULTI,
82
+ original_image=original_images,
83
+ prompt=prompt,
84
+ ratios=ratios
85
+ )
86
+
87
+ # ----- 自由构图 -----
88
+ def create_custom_composition(self,
89
+ original_image: Union[str, Path],
90
+ prompt: str,
91
+ ratios: str = "auto") -> int:
92
+ """
93
+ 自由构图
94
+
95
+ :param original_image: 原图(文件路径、URL或Base64)
96
+ :param prompt: 画面描述
97
+ :param ratios: 图片比例,默认 "auto"
98
+ :return: 任务ID
99
+ """
100
+ return self.create_task(
101
+ ImageClient.TYPE_CUSTOM_COMPOSITION,
102
+ original_image=original_image,
103
+ prompt=prompt,
104
+ ratios=ratios
105
+ )
106
+
107
+ # ----- 场景替换 -----
108
+ def create_scene_replacement(self,
109
+ original_image: Union[str, Path],
110
+ ratios: str = "auto",
111
+ prompt: Optional[str] = None,
112
+ reference_image: Optional[Union[str, Path]] = None) -> int:
113
+ """
114
+ 场景替换(prompt 和 reference_image 至少需要有一個有值)
115
+
116
+ :param original_image: 原图(文件路径、URL或Base64)
117
+ :param prompt: 场景描述文本
118
+ :param reference_image: 场景参考图(文件路径、URL或Base64)
119
+ :param ratios: 图片比例,默认 "auto"
120
+ :return: 任务ID
121
+ """
122
+ if (prompt is None) and (reference_image is None):
123
+ raise ValueError("prompt 和 reference_image 不能同時爲空")
124
+
125
+ payload = {"original_image": original_image, "ratios": ratios}
126
+ if prompt:
127
+ payload["prompt"] = prompt
128
+ if reference_image:
129
+ payload["reference_image"] = reference_image
130
+ return self.create_task(ImageClient.TYPE_SCENE_REPLACEMENT, **payload)
131
+
132
+ # ----- 商品替换 -----
133
+ def create_product_replacement(self,
134
+ original_image: Union[str, Path],
135
+ reference_image: Union[str, Path],
136
+ prompt: Optional[str] = None) -> int:
137
+ """
138
+ 商品替换
139
+
140
+ :param original_image: 原图(文件路径、URL或Base64)
141
+ :param reference_image: 参考图,以此为背景(文件路径、URL或Base64)
142
+ :param prompt: 商品描述(可选)
143
+ :return: 任务ID
144
+ """
145
+ payload = {"original_image": original_image, "reference_image": reference_image}
146
+ if prompt:
147
+ payload["prompt"] = prompt
148
+ return self.create_task(ImageClient.TYPE_PRODUCT_REPLACEMENT, **payload)
149
+
150
+ # ----- 商品换色 -----
151
+ def create_product_recoloring(self,
152
+ original_image: Union[str, Path],
153
+ color: str) -> int:
154
+ """
155
+ 商品换色
156
+
157
+ :param original_image: 原图(文件路径、URL或Base64)
158
+ :param color: 目标颜色,十六进制格式(含透明度),如 "#ff4500ff"
159
+ :return: 任务ID
160
+ """
161
+ return self.create_task(
162
+ "product_recoloring",
163
+ original_image=original_image,
164
+ color=color
165
+ )
166
+
167
+ # ----- 局部重绘 -----
168
+ def create_partial_redraw(self,
169
+ original_image: Union[str, Path],
170
+ prompt: str,
171
+ reference_image: Optional[Union[str, Path]] = None) -> int:
172
+ """
173
+ 局部重绘
174
+
175
+ :param original_image: 原图(文件路径、URL或Base64)
176
+ :param prompt: 描述如何重绘
177
+ :param reference_image: 参考图(可选,文件路径、URL或Base64)
178
+ :return: 任务ID
179
+ """
180
+ payload = {"original_image": original_image, "prompt": prompt}
181
+ if reference_image:
182
+ payload["reference_image"] = reference_image
183
+ return self.create_task(ImageClient.TYPE_PRODUCT_RECOLORING, **payload)
184
+
185
+ # ----- 智能延展 -----
186
+ def create_smart_expand(self,
187
+ original_image: Union[str, Path],
188
+ direction: str,
189
+ ratios: str) -> int:
190
+ """
191
+ 智能延展
192
+
193
+ :param original_image: 原图(文件路径、URL或Base64)
194
+ :param direction: 延展方向,如 "top_left", "auto" 等
195
+ :param ratios: 目标比例,如 "1:1", "16:9"
196
+ :return: 任务ID
197
+ """
198
+ return self.create_task(
199
+ ImageClient.TYPE_SMART_EXPAND,
200
+ original_image=original_image,
201
+ direction=direction,
202
+ ratios=ratios
203
+ )
204
+
205
+ # ----- 图片翻译 -----
206
+ def create_translation(self,
207
+ original_image: Union[str, Path],
208
+ source_language: str,
209
+ target_language: str) -> int:
210
+ """
211
+ 图片翻译
212
+
213
+ :param original_image: 原图(文件路径、URL或Base64)
214
+ :param source_language: 原语言,如 "auto", "Chinese"
215
+ :param target_language: 目标语言,如 "English"
216
+ :return: 任务ID
217
+ """
218
+ return self.create_task(
219
+ ImageClient.TYPE_TRANSLATION,
220
+ original_image=original_image,
221
+ source_language=source_language,
222
+ target_language=target_language
223
+ )
224
+
225
+ # ----- AI 超清-2K -----
226
+ def create_ai_upscale_2k(self, original_image: Union[str, Path]) -> int:
227
+ """
228
+ AI超清-2K(仅需原图)
229
+
230
+ :param original_image: 原图(文件路径、URL或Base64)
231
+ :return: 任务ID
232
+ """
233
+ return self.create_task(ImageClient.TYPE_AI_UPSCALE_2K, original_image=original_image)
234
+
235
+ # ---------- 查询作图结果 ----------
236
+ def get_task_status(self, task_id: int) -> Dict[str, Any]:
237
+ """查询单个作图任务状态"""
238
+ endpoint = f"/v1/images/generations/tasks/{task_id}"
239
+ return self._request('GET', endpoint)
240
+
241
+ # ---------- 获取高清图片 ----------
242
+ def get_hd_image(self, task_id: int) -> str:
243
+ """获取作图任务的高清图片 URL(任务需已完成)"""
244
+ endpoint = f"/v1/images/upscale/{task_id}"
245
+ data = self._request('GET', endpoint)
246
+ return data['hd_image_url']
247
+
248
+ # ---------- 获取作图任务列表 ----------
249
+ def list_tasks(self,
250
+ page: int = 1,
251
+ page_size: int = 20,
252
+ status: Optional[str] = None,
253
+ task_type: Optional[str] = None) -> Dict[str, Any]:
254
+ """获取作图任务列表,支持分页、状态和类型过滤"""
255
+ params = {"page": page, "page_size": page_size}
256
+ if status and status != 'all':
257
+ params["status"] = status
258
+ if task_type:
259
+ params["type"] = task_type
260
+ return self._request('GET', '/v1/images/tasks-list', params=params)
261
+
262
+ # ---------- 高级封装 ----------
263
+
264
+ # ---------- 轮询等待作图任务完成 ----------
265
+ def wait_for_completion(self, task_id: int, poll_interval: int = 3, timeout: int = 180) -> Dict[str, Any]:
266
+ start_time = time.time()
267
+ while True:
268
+ data = self.get_task_status(task_id)
269
+ status = data.get('status')
270
+ if status == 'completed':
271
+ return data
272
+ elif status == 'error':
273
+ raise APIError(1000, f"Task {task_id} failed")
274
+ elif status in ('queued', 'processing'):
275
+ if timeout and (time.time() - start_time) > timeout:
276
+ raise APIError(1001, f"Task {task_id} timeout after {timeout}s")
277
+ time.sleep(poll_interval)
278
+ else:
279
+ raise APIError(1002, f"Unknown status: {status}")
280
+ '''
281
+ # 暫時註釋掉
282
+ start_time = time.time()
283
+ while True:
284
+ if time.time() - start_time > timeout:
285
+ raise APIError(-1, f"任务 {task_id} 轮询超时", 0)
286
+
287
+ data = self.get_task_status(task_id)
288
+ status = data.get('status')
289
+ if status == 'completed':
290
+ return data
291
+ if status == 'error':
292
+ raise APIError(-1, f"任务 {task_id} 执行失败", 0)
293
+ time.sleep(poll_interval)
294
+ '''
295
+
296
+ # ---------- 发起任务并等待完成 ----------
297
+ def generate(self, task_type: str, wait: bool = True,
298
+ poll_interval: int = 3, timeout: Optional[int] = None,
299
+ **params) -> Union[str, Dict[str, Any]]:
300
+ """
301
+ 一键生成:发起任务并等待完成
302
+ 注意:推荐使用专用方法 + wait_for_completion,此方法为通用便捷接口
303
+ """
304
+ task_id = self.create_task(task_type, **params)
305
+ if not wait:
306
+ return task_id
307
+ result = self.wait_for_completion(task_id, poll_interval, timeout)
308
+ result['task_id'] = task_id
309
+ return result
@@ -0,0 +1,4 @@
1
+ import os
2
+
3
+ __version__ = os.getenv("TAG", "0.0.0")
4
+ VERSION = tuple(map(int, __version__.split('.')))
@@ -0,0 +1,69 @@
1
+ """
2
+ AI 图像/视频生成 Python SDK
3
+ - 基类: AIClient (通用请求、认证、图片上传)
4
+ - 图片客户端: ImageClient (9种作图、状态轮询、高清图、任务列表)
5
+ - 视频客户端: VideoClient (视频生成、状态轮询、任务列表)
6
+ """
7
+
8
+ import os
9
+ import time
10
+ from typing import Dict, Any, List, Optional, Union
11
+ from pathlib import Path
12
+ from ixspy_ai_api import AIClient, APIError
13
+
14
+ class VideoClient(AIClient):
15
+ """AI 视频生成客户端"""
16
+
17
+ # ---------- 发起视频任务 ----------
18
+ def create_video(self,
19
+ original_images: List[Union[str, Path]],
20
+ prompt: str) -> int:
21
+ """
22
+ 发起视频生成任务(最多5张图)
23
+
24
+ Args:
25
+ original_images: 原始图片列表(本地路径/URL/Base64)
26
+ prompt: 视频画面描述
27
+
28
+ Returns:
29
+ task_id
30
+ """
31
+ prepared_images = self._prepare_images(original_images)
32
+ payload = {
33
+ "original_image": prepared_images,
34
+ "prompt": prompt
35
+ }
36
+ data = self._request('POST', '/v1/video/generations', json=payload)
37
+ return int(data['task_id'])
38
+
39
+ # ---------- 查询视频结果 ----------
40
+ def get_video_status(self, task_id: int) -> Dict[str, Any]:
41
+ """查询单个视频任务状态"""
42
+ endpoint = f"/v1/video/generations/tasks/{task_id}"
43
+ return self._request('GET', endpoint)
44
+
45
+ def wait_for_video_completion(self, task_id: int, poll_interval: int = 15, timeout: int = 600) -> Dict[str, Any]:
46
+ """轮询等待视频任务完成(建议间隔15-20秒)"""
47
+ start_time = time.time()
48
+ while True:
49
+ if time.time() - start_time > timeout:
50
+ raise APIError(-1, f"视频任务 {task_id} 轮询超时", 0)
51
+
52
+ data = self.get_video_status(task_id)
53
+ status = data.get('status')
54
+ if status == 'completed':
55
+ return data
56
+ if status == 'error':
57
+ raise APIError(-1, f"视频任务 {task_id} 执行失败", 0)
58
+ time.sleep(poll_interval)
59
+
60
+ # ---------- 获取视频任务列表 ----------
61
+ def list_video_tasks(self,
62
+ page: int = 1,
63
+ page_size: int = 20,
64
+ status: Optional[str] = None) -> Dict[str, Any]:
65
+ """获取视频任务列表,支持分页和状态过滤"""
66
+ params = {"page": page, "page_size": page_size}
67
+ if status and status != 'all':
68
+ params["status"] = status
69
+ return self._request('GET', '/v1/video/tasks-list', params=params)
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: ixspy-ai-api
3
+ Version: 1.0.1
4
+ Summary: A client of IXSPY AI Api
5
+ Home-page: https://github.com/ixspyinc/ixspy-ai-api-python
6
+ Author: IXSPY Team
7
+ Author-email: tech@ixspy.com
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3.5
10
+ Classifier: Programming Language :: Python :: 3.6
11
+ Classifier: Programming Language :: Python :: 3.7
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: requests>=2
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: keywords
28
+ Dynamic: license
29
+ Dynamic: license-file
30
+ Dynamic: requires-dist
31
+ Dynamic: summary
32
+
33
+ # IXSPY AI API
34
+
35
+ IXSPY AI API V1.0 official python version
36
+
37
+ ## README.md
38
+
39
+ ## Installation
40
+
41
+ 1. pypi install
42
+ ```BASH
43
+ pip install ixspy-ai-api
44
+ ```
45
+
46
+ 2. Source code install
47
+ ```BASH
48
+ git clone https://github.com/ixspyinc/ixspy-ai-api-python.git
49
+ cd ixspy-ai-api-python
50
+ python setup.py install
51
+ ```
52
+
53
+ ## Usage
54
+
55
+ Basic usage
56
+ ```python
57
+ import os
58
+ import sys
59
+ from ixspy_ai_api import ImageClient
60
+
61
+ # 分步骤调用, 任务方法和参数都已约定好
62
+
63
+ API_KEY = 'YOUR_KEY'
64
+ FOLDER_PATH = os.path.dirname(os.path.abspath(sys.argv[0])) + os.sep
65
+ original_image_path = FOLDER_PATH + 'images/speaker.jpg'
66
+
67
+ client = ImageClient(api_key=API_KEY)
68
+
69
+ task_id = client.create_custom_composition(
70
+ original_image=original_image_path,
71
+ prompt="移除产品背景,只保留白色背景产品图",
72
+ )
73
+ print(f"任务ID: {task_id}")
74
+
75
+ # 轮询等待完成
76
+ result = client.wait_for_completion(task_id, poll_interval=3, timeout=180)
77
+
78
+ # 可和预生成的图片 examples/images/demo_result_create_custom_composition.png 对比
79
+ print("标清图URL:", result['sd_image_url'])
80
+
81
+ # 高清圖需要額外時間,這裏選擇多等待半分鐘
82
+ print('等待半分钟后获取高清图')
83
+ time.sleep(30)
84
+
85
+ # 获取高清图
86
+ hd_url = client.get_hd_image(task_id)
87
+ print("高清图URL:", hd_url)
88
+
89
+ ```
90
+
91
+ Advance use
92
+
93
+ For detailed usage, please refer to the files in the /examples directory.
94
+
95
+
96
+
97
+ ## API document
98
+ https://img.ixspy.com/api-doc.html
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ ixspy_ai_api/__init__.py
5
+ ixspy_ai_api/ai_client.py
6
+ ixspy_ai_api/image_client.py
7
+ ixspy_ai_api/version.py
8
+ ixspy_ai_api/video_client.py
9
+ ixspy_ai_api.egg-info/PKG-INFO
10
+ ixspy_ai_api.egg-info/SOURCES.txt
11
+ ixspy_ai_api.egg-info/dependency_links.txt
12
+ ixspy_ai_api.egg-info/requires.txt
13
+ ixspy_ai_api.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2
@@ -0,0 +1 @@
1
+ ixspy_ai_api
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,39 @@
1
+ import os
2
+ import pathlib
3
+
4
+ from setuptools import setup, find_packages
5
+
6
+ HERE = pathlib.Path(__file__).parent.resolve()
7
+ LONG_DESCRIPTION = (HERE / "README.md").read_text(encoding="utf8")
8
+ LONG_DESC_TYPE = "text/markdown"
9
+
10
+ try:
11
+ __version__ = os.environ.get('GITHUB_REF_NAME', '0.0.0')
12
+ except:
13
+ __version__ = "0.0.0"
14
+
15
+ VERSION = tuple(map(int, __version__.split('.')))
16
+ CURR_VERSION = '.'.join(str(x) for x in VERSION)
17
+
18
+ setup(name='ixspy-ai-api',
19
+ version=CURR_VERSION,
20
+ description='A client of IXSPY AI Api',
21
+ long_description=LONG_DESCRIPTION,
22
+ long_description_content_type=LONG_DESC_TYPE,
23
+ author='IXSPY Team',
24
+ author_email='tech@ixspy.com',
25
+ url='https://github.com/ixspyinc/ixspy-ai-api-python',
26
+ license='MIT',
27
+ keywords='',
28
+ packages=find_packages(),
29
+ install_requires=['requests >= 2'],
30
+ classifiers=["Programming Language :: Python :: 3.5",
31
+ "Programming Language :: Python :: 3.6",
32
+ "Programming Language :: Python :: 3.7",
33
+ "Programming Language :: Python :: 3.8",
34
+ "Programming Language :: Python :: 3.9",
35
+ "Programming Language :: Python :: 3.10",
36
+ "Programming Language :: Python :: 3.11",
37
+ "Programming Language :: Python :: 3.12",
38
+ "Programming Language :: Python :: 3.13",]
39
+ )