ai-world-sdk 1.1.1 → 1.1.2

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.
package/README.md CHANGED
@@ -9,7 +9,7 @@ TypeScript SDK for AI World Platform - 一个功能完整的 AI 应用开发 SDK
9
9
 
10
10
  - 🤖 **聊天模型**: 兼容 LangChain.js 接口(OpenAI、Gemini、Claude、Doubao)
11
11
  - 🎨 **图像生成**: 支持豆包 Seedream 和 Google Gemini
12
- - 🎬 **视频生成**: 支持豆包 Seedance
12
+ - 🎬 **视频生成**: 支持豆包 Seedance 和 OpenAI Sora
13
13
  - 📥 **下载代理**: 支持流式下载和普通下载任意 URL 的二进制文件
14
14
  - 🔐 **用户认证**: 支持获取当前登录用户信息
15
15
  - ⚙️ **全局配置**: 自动从浏览器环境获取配置,简化初始化
@@ -113,6 +113,8 @@ console.log('图像 URL:', geminiResult.data[0]?.url);
113
113
 
114
114
  ### 4. 视频生成
115
115
 
116
+ #### 豆包视频生成(Seedance)
117
+
116
118
  ```typescript
117
119
  import { VideoGenerationClient } from 'ai-world-sdk';
118
120
 
@@ -136,6 +138,90 @@ if (result.status === 'succeeded') {
136
138
  }
137
139
  ```
138
140
 
141
+ #### OpenAI 视频生成(Sora)
142
+
143
+ ```typescript
144
+ import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
145
+
146
+ const openaiVideoClient = new OpenAIVideoGenerationClient({});
147
+
148
+ // 方式1: 文本生成视频
149
+ const task = await openaiVideoClient.generate({
150
+ prompt: 'A beautiful sunset over the ocean with waves crashing on the shore',
151
+ model: 'sora-2', // 或 'sora-2-pro'
152
+ provider: 'aihubmix', // 或 'api2img'
153
+ seconds: '4', // 4, 8, 或 12 秒
154
+ size: '1280x720' // '720x1280', '1280x720', '1024x1792', '1792x1024'
155
+ });
156
+
157
+ console.log('任务 ID:', task.id);
158
+ console.log('任务状态:', task.status);
159
+
160
+ // 方式2: 图像生成视频(图生视频)
161
+ const taskWithImage = await openaiVideoClient.generate({
162
+ prompt: 'Animate this scene with gentle movements',
163
+ input_reference: 'data:image/png;base64,iVBORw0KGgo...', // Base64 图像或 URL
164
+ model: 'sora-2',
165
+ provider: 'aihubmix',
166
+ seconds: '4'
167
+ });
168
+
169
+ // 查询任务状态
170
+ const status = await openaiVideoClient.getTask(task.id, 'aihubmix');
171
+ console.log('当前状态:', status.status);
172
+
173
+ // 轮询等待完成
174
+ const result = await openaiVideoClient.waitForCompletion(task.id, 'aihubmix', {
175
+ maxAttempts: 60,
176
+ interval: 5000,
177
+ onProgress: (status) => {
178
+ console.log('当前状态:', status.status);
179
+ }
180
+ });
181
+
182
+ if (result.status === 'completed') {
183
+ console.log('视频生成成功!');
184
+
185
+ // 流式下载视频
186
+ const videoBlob = await openaiVideoClient.downloadVideo(
187
+ result.id,
188
+ 'aihubmix', // provider
189
+ 'video' // 'video' 或 'thumbnail'
190
+ );
191
+
192
+ console.log('视频大小:', (videoBlob.size / 1024 / 1024).toFixed(2), 'MB');
193
+
194
+ // 在浏览器中下载
195
+ const url = URL.createObjectURL(videoBlob);
196
+ const a = document.createElement('a');
197
+ a.href = url;
198
+ a.download = 'sora_video.mp4';
199
+ a.click();
200
+ URL.revokeObjectURL(url);
201
+ }
202
+
203
+ // 一键生成并等待(简化版)
204
+ const completeResult = await openaiVideoClient.generateAndWait({
205
+ prompt: 'A futuristic city skyline',
206
+ model: 'sora-2',
207
+ provider: 'aihubmix',
208
+ seconds: '4'
209
+ }, {
210
+ maxAttempts: 60,
211
+ interval: 5000,
212
+ onProgress: (status) => console.log('状态:', status.status)
213
+ });
214
+
215
+ if (completeResult.status === 'completed') {
216
+ const videoBlob = await openaiVideoClient.downloadVideo(
217
+ completeResult.id,
218
+ 'aihubmix',
219
+ 'video'
220
+ );
221
+ console.log('一键生成完成,视频大小:', videoBlob.size);
222
+ }
223
+ ```
224
+
139
225
  ### 5. 用户认证
140
226
 
141
227
  ```typescript
@@ -378,7 +464,7 @@ const secondResponse = await client.chat({
378
464
 
379
465
  ### 视频生成
380
466
 
381
- #### VideoGenerationClient
467
+ #### VideoGenerationClient(豆包 Seedance)
382
468
 
383
469
  ```typescript
384
470
  const client = new VideoGenerationClient({});
@@ -403,6 +489,53 @@ const result = await client.poll(task.id, {
403
489
  });
404
490
  ```
405
491
 
492
+ #### OpenAIVideoGenerationClient(OpenAI Sora)
493
+
494
+ ```typescript
495
+ const client = new OpenAIVideoGenerationClient({});
496
+
497
+ // 文本生成视频
498
+ const task = await client.generate({
499
+ prompt: 'A beautiful sunset',
500
+ model: 'sora-2', // 可选: sora-2, sora-2-pro
501
+ provider: 'openai', // 可选: openai, aihubmix, api2img
502
+ seconds: '4', // 可选: 4, 8, 12
503
+ size: '1280x720', // 可选: 720x1280, 1280x720, 1024x1792, 1792x1024
504
+ });
505
+
506
+ // 图像生成视频
507
+ const taskFromImage = await client.generate({
508
+ prompt: 'Animate this scene',
509
+ input_reference: 'data:image/png;base64,iVBORw0KGgo...', // Base64 或 URL
510
+ model: 'sora-2',
511
+ seconds: '8',
512
+ });
513
+
514
+ // 查询状态
515
+ const status = await client.getTask(task.id);
516
+
517
+ // 轮询直到完成
518
+ const result = await client.waitForCompletion(task.id, {
519
+ maxAttempts: 60,
520
+ interval: 5000,
521
+ onProgress: (status) => {
522
+ console.log('状态:', status.status);
523
+ }
524
+ });
525
+
526
+ // 下载视频
527
+ const videoBlob = await client.downloadVideo(task.id, {
528
+ variant: 'video' // 或 'thumbnail'
529
+ });
530
+
531
+ // 一键生成并等待
532
+ const finalResult = await client.generateAndWait({
533
+ prompt: 'A futuristic city',
534
+ model: 'sora-2',
535
+ seconds: '4'
536
+ });
537
+ ```
538
+
406
539
  ### 下载代理
407
540
 
408
541
  #### DownloadClient
@@ -1064,6 +1197,8 @@ if (userInfo.avatar_url) {
1064
1197
 
1065
1198
  ### 视频生成工作流
1066
1199
 
1200
+ #### 豆包视频生成(Doubao Seedance)
1201
+
1067
1202
  ```typescript
1068
1203
  import { VideoGenerationClient } from 'ai-world-sdk';
1069
1204
 
@@ -1093,6 +1228,131 @@ if (result.status === 'succeeded') {
1093
1228
  }
1094
1229
  ```
1095
1230
 
1231
+ #### OpenAI 视频生成(Sora)
1232
+
1233
+ ```typescript
1234
+ import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
1235
+
1236
+ const client = new OpenAIVideoGenerationClient({});
1237
+
1238
+ // 1. 文本生成视频
1239
+ const task = await client.generate({
1240
+ prompt: 'A serene mountain landscape with a flowing river',
1241
+ model: 'sora-2', // 'sora-2' 或 'sora-2-pro'
1242
+ provider: 'aihubmix', // 'aihubmix' 或 'api2img'
1243
+ seconds: '4', // '4', '8', 或 '12'
1244
+ size: '1280x720' // '720x1280', '1280x720', '1024x1792', '1792x1024'
1245
+ });
1246
+
1247
+ console.log('任务已创建:', task.id);
1248
+ console.log('任务状态:', task.status);
1249
+
1250
+ // 2. 查询任务状态
1251
+ const status = await client.getTask(task.id, 'aihubmix');
1252
+ console.log('当前状态:', status.status);
1253
+
1254
+ // 3. 轮询等待完成
1255
+ const result = await client.waitForCompletion(
1256
+ task.id,
1257
+ 'aihubmix', // provider 参数
1258
+ {
1259
+ maxAttempts: 60,
1260
+ interval: 5000,
1261
+ onProgress: (status) => {
1262
+ console.log(`状态: ${status.status}`);
1263
+ if (status.status === 'in_progress') {
1264
+ console.log('正在生成...');
1265
+ }
1266
+ }
1267
+ }
1268
+ );
1269
+
1270
+ if (result.status === 'completed') {
1271
+ console.log('✅ 视频生成成功!');
1272
+
1273
+ // 4. 流式下载视频
1274
+ const videoBlob = await client.downloadVideo(
1275
+ result.id,
1276
+ 'aihubmix', // provider
1277
+ 'video' // 'video' 或 'thumbnail'
1278
+ );
1279
+
1280
+ console.log('视频大小:', (videoBlob.size / 1024 / 1024).toFixed(2), 'MB');
1281
+ console.log('视频类型:', videoBlob.type);
1282
+
1283
+ // 在浏览器中创建下载链接
1284
+ const url = URL.createObjectURL(videoBlob);
1285
+ const a = document.createElement('a');
1286
+ a.href = url;
1287
+ a.download = `sora_video_${result.id}.mp4`;
1288
+ a.click();
1289
+ URL.revokeObjectURL(url);
1290
+
1291
+ // 也可以下载缩略图
1292
+ const thumbnail = await client.downloadVideo(
1293
+ result.id,
1294
+ 'aihubmix',
1295
+ 'thumbnail'
1296
+ );
1297
+ console.log('缩略图大小:', (thumbnail.size / 1024).toFixed(2), 'KB');
1298
+ } else if (result.status === 'failed') {
1299
+ console.error('❌ 生成失败:', result.error);
1300
+ }
1301
+
1302
+ // 一键生成并等待(简化版)
1303
+ try {
1304
+ const result2 = await client.generateAndWait({
1305
+ prompt: 'A futuristic city with flying cars at night',
1306
+ model: 'sora-2',
1307
+ provider: 'aihubmix',
1308
+ seconds: '8',
1309
+ size: '1280x720'
1310
+ }, {
1311
+ maxAttempts: 60,
1312
+ interval: 5000,
1313
+ onProgress: (status) => console.log('进度:', status.status)
1314
+ });
1315
+
1316
+ console.log('视频生成完成:', result2.id);
1317
+
1318
+ // 流式下载
1319
+ const video = await client.downloadVideo(
1320
+ result2.id,
1321
+ 'aihubmix',
1322
+ 'video'
1323
+ );
1324
+ console.log('视频大小:', (video.size / 1024 / 1024).toFixed(2), 'MB');
1325
+ } catch (error) {
1326
+ console.error('视频生成失败:', error);
1327
+ }
1328
+
1329
+ // 图像生成视频示例
1330
+ const imageToVideoTask = await client.generate({
1331
+ prompt: 'Make this scene come alive with gentle movements',
1332
+ input_reference: 'data:image/png;base64,iVBORw0KGgo...', // 图像 base64 或 URL
1333
+ model: 'sora-2',
1334
+ provider: 'aihubmix',
1335
+ seconds: '4'
1336
+ });
1337
+
1338
+ const imageToVideoResult = await client.waitForCompletion(
1339
+ imageToVideoTask.id,
1340
+ 'aihubmix'
1341
+ );
1342
+
1343
+ if (imageToVideoResult.status === 'completed') {
1344
+ console.log('图生视频完成:', imageToVideoResult.id);
1345
+
1346
+ // 下载视频
1347
+ const videoBlob = await client.downloadVideo(
1348
+ imageToVideoResult.id,
1349
+ 'aihubmix',
1350
+ 'video'
1351
+ );
1352
+ console.log('视频已下载,大小:', videoBlob.size);
1353
+ }
1354
+ ```
1355
+
1096
1356
  ### 用户认证工作流
1097
1357
 
1098
1358
  ```typescript
@@ -1253,7 +1513,28 @@ for await (const chunk of client.streamDownload({
1253
1513
 
1254
1514
  ### 视频生成模型
1255
1515
 
1256
- - **豆包 Seedance**: `doubao-seedance-1-0-pro-fast-251015` (默认,推荐)
1516
+ #### 豆包 Seedance
1517
+
1518
+ | 模型 | Provider | 说明 | 参数 |
1519
+ |------|----------|------|------|
1520
+ | `doubao-seedance-1-0-pro-fast-251015` | `doubao` | 快速版(推荐) | 时长: 1-10秒,宽高比: 16:9/9:16/1:1 |
1521
+ | `doubao-seedance-1-0-pro-250528` | `doubao` | 专业版 | 时长: 1-10秒,宽高比: 16:9/9:16/1:1 |
1522
+ | `doubao-seedance-1-0-lite-t2v-250428` | `doubao` | 轻量版(文生视频) | 时长: 1-10秒 |
1523
+ | `doubao-seedance-1-0-lite-i2v-250428` | `doubao` | 轻量版(图生视频) | 时长: 1-10秒 |
1524
+
1525
+ #### OpenAI Sora
1526
+
1527
+ | 模型 | Provider | 说明 | 参数 |
1528
+ |------|----------|------|------|
1529
+ | `sora-2` | `aihubmix` / `api2img` | 标准模型(默认) | 时长: 4/8/12秒,分辨率: 720x1280, 1280x720, 1024x1792, 1792x1024 |
1530
+ | `sora-2-pro` | `aihubmix` / `api2img` | 专业版模型 | 时长: 4/8/12秒,分辨率: 720x1280, 1280x720, 1024x1792, 1792x1024 |
1531
+
1532
+ **特性说明:**
1533
+ - **豆包 Seedance**: 支持文本生成视频和图像生成视频,URL 直接返回
1534
+ - **OpenAI Sora**: 支持文本生成视频和图像生成视频(Base64/URL),需要流式下载
1535
+ - **Provider 选择**:
1536
+ - 豆包: 仅支持 `doubao` provider
1537
+ - OpenAI: 支持 `aihubmix` 和 `api2img` provider(推荐使用 `aihubmix`)
1257
1538
 
1258
1539
  ## 错误处理
1259
1540
 
@@ -44,7 +44,7 @@ const fs_1 = require("fs");
44
44
  dotenv.config();
45
45
  index_1.sdkConfig.setBaseUrl("http://localhost:8000");
46
46
  index_1.sdkConfig.setToken(process.env.AUTH_TOKEN || process.env.TOKEN || "");
47
- // sdkConfig.setDebug(true);
47
+ index_1.sdkConfig.setDebug(true);
48
48
  function extractTextFromChunk(chunk) {
49
49
  if (typeof chunk.content === "string") {
50
50
  return chunk.content;
@@ -1148,4 +1148,397 @@ describe("Langchain SDK Tests", () => {
1148
1148
  console.log("响应内容:", content);
1149
1149
  }
1150
1150
  }, 30000);
1151
+ // ========== OpenAI 视频生成测试 ==========
1152
+ test("OpenAIVideoGenerationClient - 创建视频生成任务(文本)", async () => {
1153
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1154
+ const task = await openaiVideoClient.generate({
1155
+ prompt: "A beautiful sunset over the ocean with waves crashing on the shore",
1156
+ model: "sora-2",
1157
+ provider: "aihubmix",
1158
+ seconds: "4",
1159
+ size: "1280x720",
1160
+ });
1161
+ expect(task).toBeDefined();
1162
+ expect(task.id).toBeDefined();
1163
+ expect(typeof task.id).toBe("string");
1164
+ expect(task.status).toBeDefined();
1165
+ expect(["queued", "in_progress", "completed", "failed"]).toContain(task.status);
1166
+ console.log("✅ OpenAI 视频生成任务创建成功(文本)");
1167
+ console.log("任务 ID:", task.id);
1168
+ console.log("任务状态:", task.status);
1169
+ }, 60000);
1170
+ test("OpenAIVideoGenerationClient - 创建视频生成任务(图像)", async () => {
1171
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1172
+ // 使用一个小的 base64 图像
1173
+ const base64Image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAJCAIAAACAMfp5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFgmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4xLWMwMDIgNzkuZGJhM2RhM2I1LCAyMDIzLzEyLzE1LTEwOjQyOjM3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB0aWZmOk9yaWVudGF0aW9uPSIxIiBleGlmOkNvbG9yU3BhY2U9IjEiIGV4aWY6UGl4ZWxYRGltZW5zaW9uPSI4IiBleGlmOlBpeGVsWURpbWVuc2lvbj0iOSIgeG1wOkNyZWF0ZURhdGU9IjIwMjUtMTItMTlUMTI6MDY6MDMrMDg6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI1LTEyLTE5VDEyOjA2OjM1KzA4OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTEyLTE5VDEyOjA2OjM1KzA4OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5Y2IwNmRjYi04MmI0LTQ3ODctYmQ1Ny1lYWI5MzE5MzkyYzUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OWNiMDZkY2ItODJiNC00Nzg3LWJkNTctZWFiOTMxOTM5MmM1IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6OWNiMDZkY2ItODJiNC00Nzg3LWJkNTctZWFiOTMxOTM5MmM1Ij4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OWNiMDZkY2ItODJiNC00Nzg3LWJkNTctZWFiOTMxOTM5MmM1IiBzdEV2dDp3aGVuPSIyMDI1LTEyLTE5VDEyOjA2OjM1KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjUuNiAoTWFjaW50b3NoKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6KNh+8AAAAEElEQVQIHWNgYPiPAw0PCQA/Vke5jW7wRQAAAABJRU5ErkJggg==";
1174
+ const task = await openaiVideoClient.generate({
1175
+ prompt: "Animate this scene with gentle movements",
1176
+ input_reference: base64Image,
1177
+ model: "sora-2",
1178
+ provider: "aihubmix",
1179
+ seconds: "4",
1180
+ });
1181
+ console.log("task:", task);
1182
+ expect(task).toBeDefined();
1183
+ expect(task.id).toBeDefined();
1184
+ expect(typeof task.id).toBe("string");
1185
+ console.log("✅ OpenAI 视频生成任务创建成功(图像)");
1186
+ console.log("任务 ID:", task.id);
1187
+ }, 60000);
1188
+ test("OpenAIVideoGenerationClient - 查询任务状态", async () => {
1189
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1190
+ // // 先创建一个任务
1191
+ // const createTask = await openaiVideoClient.generate({
1192
+ // prompt: "A serene mountain landscape",
1193
+ // model: "sora-2",
1194
+ // provider: "aihubmix",
1195
+ // seconds: "4",
1196
+ // });
1197
+ // console.log("createTask:", createTask);
1198
+ // expect(createTask.id).toBeDefined();
1199
+ // 查询任务状态
1200
+ let taskId = "eyJtb2RlbCI6InNvcmEtMiIsImlkIjoidmlkZW9fNjk0YmYxYzZjNTEwODE5MDliZjBlNDc5ZDI3OGU5ODYifQchannel2361";
1201
+ // 轮询任务(使用较短的超时时间用于测试)
1202
+ try {
1203
+ const result = await openaiVideoClient.waitForCompletion(taskId, "aihubmix", {
1204
+ maxAttempts: 30, // 最多轮询 30 次
1205
+ interval: 5000, // 每 5 秒轮询一次
1206
+ onProgress: (status) => {
1207
+ console.log(`进度更新: ${status.status}`);
1208
+ }
1209
+ });
1210
+ console.log("--------------------------------");
1211
+ console.log("result:", JSON.stringify(result, null, 2));
1212
+ console.log("--------------------------------");
1213
+ expect(result).toBeDefined();
1214
+ expect(["completed", "failed"]).toContain(result.status);
1215
+ console.log("✅ OpenAI 视频任务轮询完成");
1216
+ console.log("最终状态:", result.status);
1217
+ if (result.status === "completed") {
1218
+ console.log("视频 ID:", result.id);
1219
+ }
1220
+ else if (result.error) {
1221
+ console.log("错误信息:", result.error);
1222
+ }
1223
+ }
1224
+ catch (error) {
1225
+ // 如果超时,这是正常的(视频生成需要时间)
1226
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1227
+ console.log("⏭️ 轮询超时(正常,视频生成需要较长时间)");
1228
+ }
1229
+ else {
1230
+ throw error;
1231
+ }
1232
+ }
1233
+ }, 60000);
1234
+ test("OpenAIVideoGenerationClient - 轮询等待完成", async () => {
1235
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1236
+ // 创建任务
1237
+ const createTask = await openaiVideoClient.generate({
1238
+ prompt: "A short video of clouds moving across the sky",
1239
+ model: "sora-2",
1240
+ provider: "aihubmix",
1241
+ seconds: "4",
1242
+ });
1243
+ expect(createTask.id).toBeDefined();
1244
+ console.log("任务创建:", createTask.id);
1245
+ // 轮询任务(使用较短的超时时间用于测试)
1246
+ try {
1247
+ const result = await openaiVideoClient.waitForCompletion(createTask.id, "aihubmix", {
1248
+ maxAttempts: 30, // 最多轮询 30 次
1249
+ interval: 5000, // 每 5 秒轮询一次
1250
+ onProgress: (status) => {
1251
+ console.log(`进度更新: ${status.status}`);
1252
+ }
1253
+ });
1254
+ expect(result).toBeDefined();
1255
+ expect(["completed", "failed"]).toContain(result.status);
1256
+ console.log("✅ OpenAI 视频任务轮询完成");
1257
+ console.log("最终状态:", result.status);
1258
+ if (result.status === "completed") {
1259
+ console.log("视频 ID:", result.id);
1260
+ }
1261
+ else if (result.error) {
1262
+ console.log("错误信息:", result.error);
1263
+ }
1264
+ }
1265
+ catch (error) {
1266
+ // 如果超时,这是正常的(视频生成需要时间)
1267
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1268
+ console.log("⏭️ 轮询超时(正常,视频生成需要较长时间)");
1269
+ }
1270
+ else {
1271
+ throw error;
1272
+ }
1273
+ }
1274
+ }, 180000);
1275
+ test("OpenAIVideoGenerationClient - 一键生成并等待", async () => {
1276
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1277
+ try {
1278
+ const result = await openaiVideoClient.generateAndWait({
1279
+ prompt: "A futuristic city skyline",
1280
+ model: "sora-2",
1281
+ provider: "aihubmix",
1282
+ seconds: "4",
1283
+ size: "1280x720"
1284
+ }, {
1285
+ maxAttempts: 30,
1286
+ interval: 5000,
1287
+ onProgress: (status) => {
1288
+ console.log("状态:", status.status);
1289
+ }
1290
+ });
1291
+ expect(result).toBeDefined();
1292
+ expect(result.id).toBeDefined();
1293
+ expect(["completed", "failed"]).toContain(result.status);
1294
+ console.log("✅ OpenAI 一键生成并等待测试完成");
1295
+ console.log("最终状态:", result.status);
1296
+ }
1297
+ catch (error) {
1298
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1299
+ console.log("⏭️ 轮询超时(正常)");
1300
+ }
1301
+ else {
1302
+ throw error;
1303
+ }
1304
+ }
1305
+ }, 180000);
1306
+ test("OpenAIVideoGenerationClient - 不同 provider 测试", async () => {
1307
+ const providers = ["api2img"];
1308
+ for (const provider of providers) {
1309
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1310
+ const task = await openaiVideoClient.generate({
1311
+ prompt: "A simple animation",
1312
+ model: "sora-2",
1313
+ provider: provider,
1314
+ seconds: "4",
1315
+ });
1316
+ expect(task).toBeDefined();
1317
+ expect(task.id).toBeDefined();
1318
+ console.log(`✅ provider ${provider} 测试成功,任务 ID: ${task.id}`);
1319
+ }
1320
+ }, 120000);
1321
+ test("OpenAIVideoGenerationClient - 不同 seconds 参数测试", async () => {
1322
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1323
+ const secondsOptions = ["4", "8"];
1324
+ for (const seconds of secondsOptions) {
1325
+ const task = await openaiVideoClient.generate({
1326
+ prompt: "A video clip",
1327
+ model: "sora-2",
1328
+ provider: "aihubmix",
1329
+ seconds: seconds,
1330
+ });
1331
+ expect(task).toBeDefined();
1332
+ expect(task.id).toBeDefined();
1333
+ console.log(`✅ seconds ${seconds} 测试成功,任务 ID: ${task.id}`);
1334
+ }
1335
+ }, 120000);
1336
+ test("OpenAIVideoGenerationClient - 不同 size 参数测试", async () => {
1337
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1338
+ const sizeOptions = [
1339
+ "1280x720",
1340
+ "720x1280",
1341
+ ];
1342
+ for (const size of sizeOptions) {
1343
+ const task = await openaiVideoClient.generate({
1344
+ prompt: "A landscape video",
1345
+ model: "sora-2",
1346
+ provider: "aihubmix",
1347
+ seconds: "4",
1348
+ size: size,
1349
+ });
1350
+ expect(task).toBeDefined();
1351
+ expect(task.id).toBeDefined();
1352
+ console.log(`✅ size ${size} 测试成功,任务 ID: ${task.id}`);
1353
+ }
1354
+ }, 120000);
1355
+ test("OpenAIVideoGenerationClient - 下载视频测试", async () => {
1356
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1357
+ let taskId = "eyJtb2RlbCI6InNvcmEtMiIsImlkIjoidmlkZW9fNjk0YmYxYzZjNTEwODE5MDliZjBlNDc5ZDI3OGU5ODYifQchannel2361";
1358
+ // 等待任务完成
1359
+ try {
1360
+ const result = await openaiVideoClient.waitForCompletion(taskId, "aihubmix", {
1361
+ maxAttempts: 30,
1362
+ interval: 5000,
1363
+ });
1364
+ console.log("result:", result);
1365
+ if (result.status === "completed") {
1366
+ // 下载视频
1367
+ const videoBlob = await openaiVideoClient.downloadVideo(result.id, "aihubmix", "video");
1368
+ expect(videoBlob).toBeDefined();
1369
+ expect(videoBlob instanceof Blob).toBe(true);
1370
+ expect(videoBlob.size).toBeGreaterThan(0);
1371
+ console.log("✅ OpenAI 视频下载测试成功");
1372
+ console.log(`视频大小: ${(videoBlob.size / 1024 / 1024).toFixed(2)} MB`);
1373
+ }
1374
+ else {
1375
+ console.log("⏭️ 任务未完成,跳过下载测试");
1376
+ }
1377
+ }
1378
+ catch (error) {
1379
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1380
+ console.log("⏭️ 轮询超时,跳过下载测试");
1381
+ }
1382
+ else {
1383
+ throw error;
1384
+ }
1385
+ }
1386
+ }, 180000);
1387
+ test("OpenAIVideoGenerationClient - 下载缩略图测试", async () => {
1388
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1389
+ // 创建任务
1390
+ const createTask = await openaiVideoClient.generate({
1391
+ prompt: "A simple scene for thumbnail test",
1392
+ model: "sora-2",
1393
+ provider: "aihubmix",
1394
+ seconds: "4",
1395
+ });
1396
+ expect(createTask.id).toBeDefined();
1397
+ console.log("创建任务:", createTask.id);
1398
+ // 等待任务完成
1399
+ try {
1400
+ const result = await openaiVideoClient.waitForCompletion(createTask.id, "aihubmix", {
1401
+ maxAttempts: 30,
1402
+ interval: 5000,
1403
+ });
1404
+ if (result.status === "completed") {
1405
+ // 下载缩略图
1406
+ const thumbnailBlob = await openaiVideoClient.downloadVideo(result.id, "aihubmix", "thumbnail");
1407
+ expect(thumbnailBlob).toBeDefined();
1408
+ expect(thumbnailBlob instanceof Blob).toBe(true);
1409
+ expect(thumbnailBlob.size).toBeGreaterThan(0);
1410
+ console.log("✅ OpenAI 缩略图下载测试成功");
1411
+ console.log(`缩略图大小: ${(thumbnailBlob.size / 1024).toFixed(2)} KB`);
1412
+ }
1413
+ else {
1414
+ console.log("⏭️ 任务未完成,跳过缩略图下载测试");
1415
+ }
1416
+ }
1417
+ catch (error) {
1418
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1419
+ console.log("⏭️ 轮询超时,跳过缩略图下载测试");
1420
+ }
1421
+ else {
1422
+ throw error;
1423
+ }
1424
+ }
1425
+ }, 180000);
1426
+ test("OpenAIVideoGenerationClient - 不同 provider 下载测试", async () => {
1427
+ const providers = ["api2img"];
1428
+ for (const provider of providers) {
1429
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1430
+ // 创建任务
1431
+ const createTask = await openaiVideoClient.generate({
1432
+ prompt: "A test video for download",
1433
+ model: "sora-2",
1434
+ provider: provider,
1435
+ seconds: "4",
1436
+ });
1437
+ expect(createTask.id).toBeDefined();
1438
+ console.log(`${provider} 创建任务:`, createTask.id);
1439
+ try {
1440
+ const result = await openaiVideoClient.waitForCompletion(createTask.id, provider, {
1441
+ maxAttempts: 30,
1442
+ interval: 5000,
1443
+ });
1444
+ if (result.status === "completed") {
1445
+ // 下载视频
1446
+ const videoBlob = await openaiVideoClient.downloadVideo(result.id, provider, "video");
1447
+ expect(videoBlob).toBeDefined();
1448
+ expect(videoBlob instanceof Blob).toBe(true);
1449
+ expect(videoBlob.size).toBeGreaterThan(0);
1450
+ console.log(`✅ provider ${provider} 下载测试成功`);
1451
+ console.log(`视频大小: ${(videoBlob.size / 1024 / 1024).toFixed(2)} MB`);
1452
+ }
1453
+ else {
1454
+ console.log(`⏭️ ${provider} 任务未完成,跳过下载测试`);
1455
+ }
1456
+ }
1457
+ catch (error) {
1458
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1459
+ console.log(`⏭️ ${provider} 轮询超时,跳过下载测试`);
1460
+ }
1461
+ else {
1462
+ throw error;
1463
+ }
1464
+ }
1465
+ }
1466
+ }, 360000);
1467
+ test("OpenAIVideoGenerationClient - 直接下载已完成的视频", async () => {
1468
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1469
+ // 使用一个已知完成的视频 ID(从前面测试中获取)
1470
+ // 注意:这需要一个真实的已完成视频 ID,此处仅作示例
1471
+ const knownVideoId = "eyJtb2RlbCI6InNvcmEtMiIsImlkIjoidmlkZW9fNjk0YmYxYzZjNTEwODE5MDliZjBlNDc5ZDI3OGU5ODYifQchannel2361";
1472
+ try {
1473
+ // 先查询状态
1474
+ const status = await openaiVideoClient.getTask(knownVideoId, "aihubmix");
1475
+ if (status.status === "completed") {
1476
+ // 下载视频
1477
+ const videoBlob = await openaiVideoClient.downloadVideo(knownVideoId, "aihubmix", "video");
1478
+ expect(videoBlob).toBeDefined();
1479
+ expect(videoBlob instanceof Blob).toBe(true);
1480
+ expect(videoBlob.size).toBeGreaterThan(0);
1481
+ console.log("✅ 直接下载已完成视频测试成功");
1482
+ console.log(`视频大小: ${(videoBlob.size / 1024 / 1024).toFixed(2)} MB`);
1483
+ }
1484
+ else {
1485
+ console.log(`⏭️ 视频状态: ${status.status},跳过下载测试`);
1486
+ }
1487
+ }
1488
+ catch (error) {
1489
+ // 视频可能已过期或不存在
1490
+ console.log("⏭️ 视频不存在或已过期,跳过测试");
1491
+ }
1492
+ }, 60000);
1493
+ test("OpenAIVideoGenerationClient - 完整流程:生成、等待、下载", async () => {
1494
+ const openaiVideoClient = new index_1.OpenAIVideoGenerationClient({});
1495
+ try {
1496
+ console.log("1️⃣ 开始生成视频...");
1497
+ const task = await openaiVideoClient.generate({
1498
+ prompt: "A complete workflow test video",
1499
+ model: "sora-2",
1500
+ provider: "aihubmix",
1501
+ seconds: "4",
1502
+ });
1503
+ expect(task.id).toBeDefined();
1504
+ console.log(`任务创建成功: ${task.id}`);
1505
+ console.log("2️⃣ 等待视频生成完成...");
1506
+ const result = await openaiVideoClient.waitForCompletion(task.id, "aihubmix", {
1507
+ maxAttempts: 30,
1508
+ interval: 5000,
1509
+ onProgress: (status) => {
1510
+ console.log(` 进度: ${status.status}`);
1511
+ },
1512
+ });
1513
+ expect(result.status).toBeDefined();
1514
+ console.log(`视频生成完成: ${result.status}`);
1515
+ if (result.status === "completed") {
1516
+ console.log("3️⃣ 下载视频...");
1517
+ const videoBlob = await openaiVideoClient.downloadVideo(result.id, "aihubmix", "video");
1518
+ expect(videoBlob).toBeDefined();
1519
+ expect(videoBlob instanceof Blob).toBe(true);
1520
+ expect(videoBlob.size).toBeGreaterThan(0);
1521
+ console.log("✅ 完整流程测试成功");
1522
+ console.log(` - 任务 ID: ${result.id}`);
1523
+ console.log(` - 视频大小: ${(videoBlob.size / 1024 / 1024).toFixed(2)} MB`);
1524
+ // 也下载缩略图
1525
+ console.log("4️⃣ 下载缩略图...");
1526
+ const thumbnailBlob = await openaiVideoClient.downloadVideo(result.id, "aihubmix", "thumbnail");
1527
+ expect(thumbnailBlob).toBeDefined();
1528
+ expect(thumbnailBlob instanceof Blob).toBe(true);
1529
+ console.log(` - 缩略图大小: ${(thumbnailBlob.size / 1024).toFixed(2)} KB`);
1530
+ }
1531
+ else {
1532
+ console.log("⏭️ 视频生成失败或未完成");
1533
+ }
1534
+ }
1535
+ catch (error) {
1536
+ if (error.message?.includes("已轮询") || error.message?.includes("仍未完成")) {
1537
+ console.log("⏭️ 轮询超时(正常,视频生成需要较长时间)");
1538
+ }
1539
+ else {
1540
+ throw error;
1541
+ }
1542
+ }
1543
+ }, 240000);
1151
1544
  });
package/dist/config.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * 注意: {VERSION} 占位符会在构建时被替换为实际版本号
11
11
  */
12
- export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.1.1";
12
+ export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.1.2";
13
13
  /**
14
14
  * 版本兼容性错误
15
15
  */
@@ -24,8 +24,8 @@ declare class SDKConfig {
24
24
  private _pluginId;
25
25
  private _versionCompatible;
26
26
  private _versionCheckPromise;
27
- readonly sdkSignature = "AI_WORLD_SDK_V:1.1.1";
28
- readonly sdkVersion = "1.1.1";
27
+ readonly sdkSignature = "AI_WORLD_SDK_V:1.1.2";
28
+ readonly sdkVersion = "1.1.2";
29
29
  constructor();
30
30
  /**
31
31
  * Set global base URL
package/dist/config.js CHANGED
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.sdkConfig = exports.VersionCompatibilityError = exports.SDK_SIGNATURE = void 0;
8
8
  // SDK 版本号(构建时自动从 package.json 更新)
9
9
  // 此版本号会在运行 npm run build 时自动从 package.json 读取并更新
10
- const SDK_VERSION = "1.1.1";
10
+ const SDK_VERSION = "1.1.2";
11
11
  /**
12
12
  * SDK 特征码 - 用于在构建后的 JS 文件中识别 SDK 版本
13
13
  * 格式: AI_WORLD_SDK_V:版本号
@@ -15,7 +15,7 @@ const SDK_VERSION = "1.1.1";
15
15
  *
16
16
  * 注意: {VERSION} 占位符会在构建时被替换为实际版本号
17
17
  */
18
- exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.1.1";
18
+ exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.1.2";
19
19
  /**
20
20
  * 版本兼容性错误
21
21
  */
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ import { BaseChatModel, BaseChatModelParams } from "./base";
8
8
  import { DoubaoImageGenerationClient, DoubaoImageSize, type DoubaoImageGenerationConfig, type DoubaoImageGenerationRequest, type DoubaoImageGenerationResponse } from "./doubao-image-generation";
9
9
  import { GeminiImageGenerationClient, type GeminiImageGenerationConfig, type GeminiImageGenerationRequest, type GeminiImageGenerationResponse } from "./gemini-image-generation";
10
10
  import { VideoGenerationClient, type VideoGenerationConfig, type VideoGenerationRequest, type ContentGenerationTaskID, type ContentGenerationTask } from "./video_generation";
11
+ import { OpenAIVideoGenerationClient, type OpenAIVideoGenerationConfig, type OpenAIVideoGenerationRequest, type OpenAIVideoTaskResponse } from "./openai_video_generation";
11
12
  import { DownloadClient, type DownloadConfig, type DownloadOptions, type StreamDownloadOptions } from "./download";
12
13
  import { AuthClient, getCurrentUserInfo, type AuthConfig, type UserInfo } from "./auth";
13
14
  export { BaseMessage, HumanMessage, AIMessage, SystemMessage, AIMessageChunk, type MessageContent, type AIMessageChunkData, } from "./messages";
@@ -23,6 +24,7 @@ export interface LangchainClientConfig {
23
24
  export { DoubaoImageGenerationClient, type DoubaoImageGenerationConfig, type DoubaoImageGenerationRequest, type DoubaoImageGenerationResponse, type DoubaoImageSize, };
24
25
  export { GeminiImageGenerationClient, type GeminiImageGenerationConfig, type GeminiImageGenerationRequest, type GeminiImageGenerationResponse, };
25
26
  export { VideoGenerationClient, type VideoGenerationConfig, type VideoGenerationRequest, type ContentGenerationTaskID, type ContentGenerationTask, };
27
+ export { OpenAIVideoGenerationClient, type OpenAIVideoGenerationConfig, type OpenAIVideoGenerationRequest, type OpenAIVideoTaskResponse, };
26
28
  export { DownloadClient, type DownloadConfig, type DownloadOptions, type StreamDownloadOptions, };
27
29
  export { AuthClient, getCurrentUserInfo, type AuthConfig, type UserInfo, };
28
30
  export { sdkConfig, VersionCompatibilityError, SDK_SIGNATURE } from "./config";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * @see https://github.com/langchain-ai/langchainjs
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.SDK_SIGNATURE = exports.VersionCompatibilityError = exports.sdkConfig = exports.getCurrentUserInfo = exports.AuthClient = exports.DownloadClient = exports.VideoGenerationClient = exports.GeminiImageGenerationClient = exports.DoubaoImageGenerationClient = exports.ChatAnthropic = exports.ChatGoogleGenerativeAI = exports.ChatOpenAI = exports.BaseChatModel = exports.AIMessageChunk = exports.SystemMessage = exports.AIMessage = exports.HumanMessage = void 0;
9
+ exports.SDK_SIGNATURE = exports.VersionCompatibilityError = exports.sdkConfig = exports.getCurrentUserInfo = exports.AuthClient = exports.DownloadClient = exports.OpenAIVideoGenerationClient = exports.VideoGenerationClient = exports.GeminiImageGenerationClient = exports.DoubaoImageGenerationClient = exports.ChatAnthropic = exports.ChatGoogleGenerativeAI = exports.ChatOpenAI = exports.BaseChatModel = exports.AIMessageChunk = exports.SystemMessage = exports.AIMessage = exports.HumanMessage = void 0;
10
10
  exports.createChatModel = createChatModel;
11
11
  const openai_1 = require("./chat_models/openai");
12
12
  const google_1 = require("./chat_models/google");
@@ -16,6 +16,8 @@ const gemini_image_generation_1 = require("./gemini-image-generation");
16
16
  Object.defineProperty(exports, "GeminiImageGenerationClient", { enumerable: true, get: function () { return gemini_image_generation_1.GeminiImageGenerationClient; } });
17
17
  const video_generation_1 = require("./video_generation");
18
18
  Object.defineProperty(exports, "VideoGenerationClient", { enumerable: true, get: function () { return video_generation_1.VideoGenerationClient; } });
19
+ const openai_video_generation_1 = require("./openai_video_generation");
20
+ Object.defineProperty(exports, "OpenAIVideoGenerationClient", { enumerable: true, get: function () { return openai_video_generation_1.OpenAIVideoGenerationClient; } });
19
21
  const download_1 = require("./download");
20
22
  Object.defineProperty(exports, "DownloadClient", { enumerable: true, get: function () { return download_1.DownloadClient; } });
21
23
  const auth_1 = require("./auth");
package/dist/log.js CHANGED
@@ -27,7 +27,7 @@ function logRequest(method, url, headers, body) {
27
27
  debugLog("📤 HTTP Request");
28
28
  debugLog(" Method:", method);
29
29
  debugLog(" URL:", url);
30
- debugLog(" Headers:", { ...headers, Authorization: headers?.Authorization ? "Bearer ***" : undefined });
30
+ debugLog(" Headers:", { ...headers, Authorization: headers?.Authorization });
31
31
  if (body) {
32
32
  try {
33
33
  const bodyStr = typeof body === "string" ? body : JSON.stringify(body, null, 2);
@@ -0,0 +1,188 @@
1
+ /**
2
+ * OpenAI Video Generation Client
3
+ * OpenAI 视频生成客户端
4
+ */
5
+ export interface OpenAIVideoGenerationConfig {
6
+ baseUrl?: string;
7
+ token?: string;
8
+ headers?: Record<string, string>;
9
+ }
10
+ export interface OpenAIVideoGenerationRequest {
11
+ prompt: string;
12
+ model?: string;
13
+ provider?: "aihubmix" | "api2img";
14
+ seconds?: "4" | "8" | "12";
15
+ size?: "720x1280" | "1280x720" | "1024x1792" | "1792x1024";
16
+ input_reference?: string;
17
+ }
18
+ export interface OpenAIVideoTaskResponse {
19
+ id: string;
20
+ object?: string;
21
+ status: "queued" | "in_progress" | "completed" | "failed";
22
+ created_at: number;
23
+ model?: string;
24
+ prompt?: string;
25
+ seconds?: "4" | "8" | "12";
26
+ size?: string;
27
+ url?: string;
28
+ error?: Record<string, any>;
29
+ }
30
+ /**
31
+ * OpenAI Video Generation Client
32
+ * OpenAI 视频生成客户端
33
+ *
34
+ * 使用示例:
35
+ * ```typescript
36
+ * import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
37
+ *
38
+ * const client = new OpenAIVideoGenerationClient({
39
+ * baseUrl: 'http://localhost:8000',
40
+ * token: 'your-auth-token'
41
+ * });
42
+ *
43
+ * // 生成视频
44
+ * const task = await client.generate({
45
+ * prompt: 'A beautiful sunset over the ocean',
46
+ * model: 'sora-2',
47
+ * provider: 'aihubmix',
48
+ * seconds: '4',
49
+ * size: '1280x720'
50
+ * });
51
+ *
52
+ * console.log('Task ID:', task.id);
53
+ *
54
+ * // 查询任务状态
55
+ * const status = await client.getTask(task.id);
56
+ * console.log('Status:', status.status);
57
+ * if (status.video_url) {
58
+ * console.log('Video URL:', status.video_url);
59
+ * }
60
+ * ```
61
+ */
62
+ export declare class OpenAIVideoGenerationClient {
63
+ private headers;
64
+ constructor(config?: OpenAIVideoGenerationConfig);
65
+ /**
66
+ * 生成视频
67
+ * Generate video
68
+ *
69
+ * @param request - 视频生成请求参数
70
+ * @returns 任务响应,包含任务 ID
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * // 文本生成视频
75
+ * const task = await client.generate({
76
+ * prompt: 'A beautiful sunset over the ocean with waves crashing on the shore',
77
+ * model: 'sora-2',
78
+ * provider: 'aihubmix',
79
+ * seconds: '4',
80
+ * size: '1280x720'
81
+ * });
82
+ *
83
+ * // 图像生成视频(使用 base64)
84
+ * const taskWithImage = await client.generate({
85
+ * prompt: 'Animate this image with gentle waves',
86
+ * input_reference: 'data:image/png;base64,iVBORw0KGgo...',
87
+ * model: 'sora-2',
88
+ * seconds: '4'
89
+ * });
90
+ * console.log('Task ID:', task.id);
91
+ * ```
92
+ */
93
+ generate(request: OpenAIVideoGenerationRequest): Promise<OpenAIVideoTaskResponse>;
94
+ /**
95
+ * 查询视频任务状态
96
+ * Get video task status
97
+ *
98
+ * @param taskId - 任务 ID
99
+ * @returns 任务状态信息
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const status = await client.getTask('vid_abc123');
104
+ * console.log('Status:', status.status);
105
+ * if (status.status === 'completed' && status.url) {
106
+ * console.log('Video URL:', status.url);
107
+ * }
108
+ * ```
109
+ */
110
+ getTask(taskId: string, provider: "aihubmix" | "api2img"): Promise<OpenAIVideoTaskResponse>;
111
+ /**
112
+ * 轮询等待任务完成
113
+ * Poll and wait for task completion
114
+ *
115
+ * @param taskId - 任务 ID
116
+ * @param options - 轮询选项
117
+ * @returns 完成的任务信息
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const result = await client.waitForCompletion('vid_abc123', {
122
+ * maxAttempts: 60,
123
+ * interval: 5000
124
+ * });
125
+ * console.log('Video URL:', result.url);
126
+ * ```
127
+ */
128
+ waitForCompletion(taskId: string, provider?: "aihubmix" | "api2img", options?: {
129
+ maxAttempts?: number;
130
+ interval?: number;
131
+ onProgress?: (status: OpenAIVideoTaskResponse) => void;
132
+ }): Promise<OpenAIVideoTaskResponse>;
133
+ /**
134
+ * 生成视频并等待完成
135
+ * Generate video and wait for completion
136
+ *
137
+ * @param request - 视频生成请求参数
138
+ * @param options - 轮询选项
139
+ * @returns 完成的任务信息,包含视频 URL
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const result = await client.generateAndWait({
144
+ * prompt: 'A beautiful sunset',
145
+ * model: 'sora-2',
146
+ * provider: 'aihubmix',
147
+ * seconds: '4'
148
+ * }, {
149
+ * onProgress: (status) => {
150
+ * console.log('Status:', status.status);
151
+ * }
152
+ * });
153
+ * console.log('Video URL:', result.video_url);
154
+ * ```
155
+ */
156
+ generateAndWait(request: OpenAIVideoGenerationRequest, options?: {
157
+ maxAttempts?: number;
158
+ interval?: number;
159
+ onProgress?: (status: OpenAIVideoTaskResponse) => void;
160
+ }): Promise<OpenAIVideoTaskResponse>;
161
+ /**
162
+ * 下载视频文件
163
+ * Download video file
164
+ *
165
+ * @param taskId - 视频任务 ID
166
+ * @param provider - 提供商类型 (aihubmix, api2img)
167
+ * @param variant - 下载类型 (video, thumbnail),默认: video
168
+ * @returns Blob 对象(可用于下载或显示)
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * // 下载视频
173
+ * const videoBlob = await client.downloadVideo('vid_abc123', 'aihubmix', 'video');
174
+ *
175
+ * // 在浏览器中创建下载链接
176
+ * const url = URL.createObjectURL(videoBlob);
177
+ * const a = document.createElement('a');
178
+ * a.href = url;
179
+ * a.download = 'video.mp4';
180
+ * a.click();
181
+ * URL.revokeObjectURL(url);
182
+ *
183
+ * // 或下载缩略图
184
+ * const thumbnail = await client.downloadVideo('vid_abc123', 'aihubmix', 'thumbnail');
185
+ * ```
186
+ */
187
+ downloadVideo(taskId: string, provider?: "aihubmix" | "api2img", variant?: "video" | "thumbnail"): Promise<Blob>;
188
+ }
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAI Video Generation Client
4
+ * OpenAI 视频生成客户端
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.OpenAIVideoGenerationClient = void 0;
8
+ const config_1 = require("./config");
9
+ const log_1 = require("./log");
10
+ /**
11
+ * OpenAI Video Generation Client
12
+ * OpenAI 视频生成客户端
13
+ *
14
+ * 使用示例:
15
+ * ```typescript
16
+ * import { OpenAIVideoGenerationClient } from 'ai-world-sdk';
17
+ *
18
+ * const client = new OpenAIVideoGenerationClient({
19
+ * baseUrl: 'http://localhost:8000',
20
+ * token: 'your-auth-token'
21
+ * });
22
+ *
23
+ * // 生成视频
24
+ * const task = await client.generate({
25
+ * prompt: 'A beautiful sunset over the ocean',
26
+ * model: 'sora-2',
27
+ * provider: 'aihubmix',
28
+ * seconds: '4',
29
+ * size: '1280x720'
30
+ * });
31
+ *
32
+ * console.log('Task ID:', task.id);
33
+ *
34
+ * // 查询任务状态
35
+ * const status = await client.getTask(task.id);
36
+ * console.log('Status:', status.status);
37
+ * if (status.video_url) {
38
+ * console.log('Video URL:', status.video_url);
39
+ * }
40
+ * ```
41
+ */
42
+ class OpenAIVideoGenerationClient {
43
+ constructor(config = {}) {
44
+ const globalHeaders = config_1.sdkConfig.getHeaders();
45
+ this.headers = {
46
+ "Content-Type": "application/json",
47
+ "Authorization": `Bearer ${config_1.sdkConfig.getToken()}`,
48
+ "X-Base-Url": config?.baseUrl || "",
49
+ ...globalHeaders,
50
+ ...config?.headers,
51
+ };
52
+ }
53
+ /**
54
+ * 生成视频
55
+ * Generate video
56
+ *
57
+ * @param request - 视频生成请求参数
58
+ * @returns 任务响应,包含任务 ID
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * // 文本生成视频
63
+ * const task = await client.generate({
64
+ * prompt: 'A beautiful sunset over the ocean with waves crashing on the shore',
65
+ * model: 'sora-2',
66
+ * provider: 'aihubmix',
67
+ * seconds: '4',
68
+ * size: '1280x720'
69
+ * });
70
+ *
71
+ * // 图像生成视频(使用 base64)
72
+ * const taskWithImage = await client.generate({
73
+ * prompt: 'Animate this image with gentle waves',
74
+ * input_reference: 'data:image/png;base64,iVBORw0KGgo...',
75
+ * model: 'sora-2',
76
+ * seconds: '4'
77
+ * });
78
+ * console.log('Task ID:', task.id);
79
+ * ```
80
+ */
81
+ async generate(request) {
82
+ const url = `${config_1.sdkConfig.getServerUrl()}/api/openai-video-proxy/generate`;
83
+ // 记录请求日志
84
+ (0, log_1.logRequest)("POST", url, this.headers, request);
85
+ try {
86
+ const response = await fetch(url, {
87
+ method: "POST",
88
+ headers: this.headers,
89
+ body: JSON.stringify(request),
90
+ });
91
+ // 记录响应日志
92
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, response.body);
93
+ if (!response.ok) {
94
+ const errorData = await response.json().catch(() => ({
95
+ detail: response.statusText,
96
+ }));
97
+ // 检查版本兼容性错误
98
+ if (response.status === 400 &&
99
+ errorData.detail?.includes("version")) {
100
+ throw new config_1.VersionCompatibilityError(errorData.detail);
101
+ }
102
+ throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
103
+ }
104
+ const data = await response.json();
105
+ return data;
106
+ }
107
+ catch (error) {
108
+ if (error instanceof config_1.VersionCompatibilityError) {
109
+ throw error;
110
+ }
111
+ throw new Error(`OpenAI 视频生成失败: ${error instanceof Error ? error.message : String(error)}`);
112
+ }
113
+ }
114
+ /**
115
+ * 查询视频任务状态
116
+ * Get video task status
117
+ *
118
+ * @param taskId - 任务 ID
119
+ * @returns 任务状态信息
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const status = await client.getTask('vid_abc123');
124
+ * console.log('Status:', status.status);
125
+ * if (status.status === 'completed' && status.url) {
126
+ * console.log('Video URL:', status.url);
127
+ * }
128
+ * ```
129
+ */
130
+ async getTask(taskId, provider) {
131
+ const url = `${config_1.sdkConfig.getServerUrl()}/api/openai-video-proxy/${taskId}?provider=${provider}`;
132
+ // 记录请求日志
133
+ (0, log_1.logRequest)("GET", url, this.headers, {});
134
+ try {
135
+ const response = await fetch(url, {
136
+ method: "GET",
137
+ headers: this.headers,
138
+ });
139
+ // 记录响应日志
140
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, response.body);
141
+ if (!response.ok) {
142
+ const errorData = await response.json().catch(() => ({
143
+ detail: response.statusText,
144
+ }));
145
+ // 检查版本兼容性错误
146
+ if (response.status === 400 &&
147
+ errorData.detail?.includes("version")) {
148
+ throw new config_1.VersionCompatibilityError(errorData.detail);
149
+ }
150
+ throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
151
+ }
152
+ const data = await response.json();
153
+ return data;
154
+ }
155
+ catch (error) {
156
+ if (error instanceof config_1.VersionCompatibilityError) {
157
+ throw error;
158
+ }
159
+ throw new Error(`查询任务失败: ${error instanceof Error ? error.message : String(error)}`);
160
+ }
161
+ }
162
+ /**
163
+ * 轮询等待任务完成
164
+ * Poll and wait for task completion
165
+ *
166
+ * @param taskId - 任务 ID
167
+ * @param options - 轮询选项
168
+ * @returns 完成的任务信息
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * const result = await client.waitForCompletion('vid_abc123', {
173
+ * maxAttempts: 60,
174
+ * interval: 5000
175
+ * });
176
+ * console.log('Video URL:', result.url);
177
+ * ```
178
+ */
179
+ async waitForCompletion(taskId, provider = "aihubmix", options = {}) {
180
+ const { maxAttempts = 60, interval = 5000, onProgress } = options;
181
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
182
+ const task = await this.getTask(taskId, provider || "aihubmix");
183
+ if (onProgress) {
184
+ onProgress(task);
185
+ }
186
+ if (task.status === "completed") {
187
+ return task;
188
+ }
189
+ if (task.status === "failed") {
190
+ throw new Error(`任务失败: ${task.error || "未知错误"}`);
191
+ }
192
+ // 等待指定时间后继续轮询
193
+ await new Promise((resolve) => setTimeout(resolve, interval));
194
+ }
195
+ throw new Error(`任务超时: 已轮询 ${maxAttempts} 次,任务仍未完成`);
196
+ }
197
+ /**
198
+ * 生成视频并等待完成
199
+ * Generate video and wait for completion
200
+ *
201
+ * @param request - 视频生成请求参数
202
+ * @param options - 轮询选项
203
+ * @returns 完成的任务信息,包含视频 URL
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const result = await client.generateAndWait({
208
+ * prompt: 'A beautiful sunset',
209
+ * model: 'sora-2',
210
+ * provider: 'aihubmix',
211
+ * seconds: '4'
212
+ * }, {
213
+ * onProgress: (status) => {
214
+ * console.log('Status:', status.status);
215
+ * }
216
+ * });
217
+ * console.log('Video URL:', result.video_url);
218
+ * ```
219
+ */
220
+ async generateAndWait(request, options) {
221
+ const task = await this.generate(request);
222
+ return this.waitForCompletion(task.id, request.provider || "aihubmix", options);
223
+ }
224
+ /**
225
+ * 下载视频文件
226
+ * Download video file
227
+ *
228
+ * @param taskId - 视频任务 ID
229
+ * @param provider - 提供商类型 (aihubmix, api2img)
230
+ * @param variant - 下载类型 (video, thumbnail),默认: video
231
+ * @returns Blob 对象(可用于下载或显示)
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * // 下载视频
236
+ * const videoBlob = await client.downloadVideo('vid_abc123', 'aihubmix', 'video');
237
+ *
238
+ * // 在浏览器中创建下载链接
239
+ * const url = URL.createObjectURL(videoBlob);
240
+ * const a = document.createElement('a');
241
+ * a.href = url;
242
+ * a.download = 'video.mp4';
243
+ * a.click();
244
+ * URL.revokeObjectURL(url);
245
+ *
246
+ * // 或下载缩略图
247
+ * const thumbnail = await client.downloadVideo('vid_abc123', 'aihubmix', 'thumbnail');
248
+ * ```
249
+ */
250
+ async downloadVideo(taskId, provider = "aihubmix", variant = "video") {
251
+ const url = `${config_1.sdkConfig.getServerUrl()}/api/openai-video-proxy/${taskId}/download?provider=${provider}&variant=${variant}`;
252
+ // 记录请求日志
253
+ (0, log_1.logRequest)("GET", url, this.headers, { taskId, provider, variant });
254
+ try {
255
+ const response = await fetch(url, {
256
+ method: "GET",
257
+ headers: this.headers,
258
+ });
259
+ if (!response.ok) {
260
+ const errorData = await response.json().catch(() => null);
261
+ // 记录错误响应日志
262
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, errorData);
263
+ // 检查版本兼容性错误
264
+ if (response.status === 400 &&
265
+ errorData?.detail?.includes("version")) {
266
+ throw new config_1.VersionCompatibilityError(errorData.detail);
267
+ }
268
+ throw new Error(errorData?.detail || `HTTP error! status: ${response.status}`);
269
+ }
270
+ // 流式下载视频(浏览器会自动处理流式传输)
271
+ const blob = await response.blob();
272
+ // 记录成功日志
273
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, {
274
+ blobSize: blob.size,
275
+ blobType: blob.type,
276
+ });
277
+ return blob;
278
+ }
279
+ catch (error) {
280
+ if (error instanceof config_1.VersionCompatibilityError) {
281
+ throw error;
282
+ }
283
+ throw new Error(`下载视频失败: ${error instanceof Error ? error.message : String(error)}`);
284
+ }
285
+ }
286
+ }
287
+ exports.OpenAIVideoGenerationClient = OpenAIVideoGenerationClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-world-sdk",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "TypeScript SDK for AI World Platform - Chat Models, Image Generation, and Video Generation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",