@golpoai/sdk 0.1.9 → 1.0.0
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/dist/index.cjs +409 -66
- package/dist/index.d.cts +81 -34
- package/dist/index.d.ts +81 -34
- package/dist/index.js +410 -67
- package/package.json +10 -2
package/dist/index.cjs
CHANGED
|
@@ -57,33 +57,55 @@ var Golpo = class {
|
|
|
57
57
|
async createPodcastJob(prompt, opts = {}) {
|
|
58
58
|
const {
|
|
59
59
|
uploads,
|
|
60
|
-
concurrency = 8,
|
|
61
|
-
addMusic = false,
|
|
62
60
|
voiceInstructions,
|
|
63
|
-
personality1,
|
|
64
|
-
personality2,
|
|
65
|
-
doResearch = false,
|
|
66
|
-
ttsModel = "accurate",
|
|
67
61
|
language,
|
|
68
|
-
style = "
|
|
62
|
+
style = "solo-female-3",
|
|
69
63
|
bgMusic,
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
// Extended params
|
|
65
|
+
newScript,
|
|
66
|
+
timing = 1
|
|
67
|
+
// timing in minutes – default 1 if not provided
|
|
72
68
|
} = opts;
|
|
69
|
+
const concurrency = 8;
|
|
73
70
|
const fields = [
|
|
74
71
|
["prompt", prompt],
|
|
75
|
-
["
|
|
76
|
-
["do_research", String(doResearch)],
|
|
77
|
-
["tts_model", ttsModel],
|
|
78
|
-
["style", style],
|
|
79
|
-
["output_volume", String(outputVolume)]
|
|
72
|
+
["style", style]
|
|
80
73
|
];
|
|
81
74
|
if (voiceInstructions) fields.push(["voice_instructions", voiceInstructions]);
|
|
82
|
-
if (personality1) fields.push(["personality_1", personality1]);
|
|
83
|
-
if (personality2) fields.push(["personality_2", personality2]);
|
|
84
75
|
if (language) fields.push(["language", language]);
|
|
85
76
|
if (bgMusic) fields.push(["bg_music", bgMusic]);
|
|
86
|
-
if (
|
|
77
|
+
if (newScript != null) fields.push(["new_script", newScript]);
|
|
78
|
+
fields.push(["timing", String(timing)]);
|
|
79
|
+
fields.push(["video_type", "null"]);
|
|
80
|
+
const hasUploads = (() => {
|
|
81
|
+
if (!uploads) return false;
|
|
82
|
+
if (typeof uploads === "string") return uploads.trim().length > 0;
|
|
83
|
+
const iterator = uploads[Symbol.iterator]();
|
|
84
|
+
const first = iterator.next();
|
|
85
|
+
return !first.done;
|
|
86
|
+
})();
|
|
87
|
+
const request_payload = {
|
|
88
|
+
prompt,
|
|
89
|
+
video_voice: style,
|
|
90
|
+
video_duration: String(timing),
|
|
91
|
+
video_type: "null",
|
|
92
|
+
language,
|
|
93
|
+
voice_instructions: voiceInstructions,
|
|
94
|
+
new_script: newScript,
|
|
95
|
+
bg_music: bgMusic,
|
|
96
|
+
attached_documents: uploads,
|
|
97
|
+
source: "node-sdk"
|
|
98
|
+
};
|
|
99
|
+
try {
|
|
100
|
+
const result = await this.createVideoRecord({
|
|
101
|
+
topic: prompt,
|
|
102
|
+
requestPayload: request_payload
|
|
103
|
+
});
|
|
104
|
+
if (result && result.videoId) {
|
|
105
|
+
fields.push(["video_id", result.videoId]);
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
}
|
|
87
109
|
const formData = await this.createFormData(fields, uploads, concurrency);
|
|
88
110
|
const { data } = await this.http.post("/generate", formData, {
|
|
89
111
|
timeout: 24e4,
|
|
@@ -110,63 +132,210 @@ var Golpo = class {
|
|
|
110
132
|
async createPodcast(prompt, opts = {}) {
|
|
111
133
|
const { pollIntervalMs = 2e3, ...jobOpts } = opts;
|
|
112
134
|
const jobId = await this.createPodcastJob(prompt, jobOpts);
|
|
113
|
-
|
|
135
|
+
const r = await this.pollUntilComplete(
|
|
114
136
|
jobId,
|
|
115
137
|
pollIntervalMs
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
podcastScript: r.podcast_script
|
|
119
|
-
}));
|
|
138
|
+
);
|
|
139
|
+
return { url: r.podcast_url, script: r.podcast_script, videoId: jobId };
|
|
120
140
|
}
|
|
121
141
|
async createVideo(prompt, opts = {}) {
|
|
122
142
|
const {
|
|
123
143
|
uploads,
|
|
124
144
|
pollIntervalMs = 2e3,
|
|
125
|
-
concurrency = 8,
|
|
126
145
|
voiceInstructions,
|
|
127
|
-
personality1,
|
|
128
|
-
doResearch = false,
|
|
129
|
-
ttsModel = "accurate",
|
|
130
146
|
language,
|
|
131
|
-
style = "solo-female",
|
|
147
|
+
style = "solo-female-3",
|
|
132
148
|
bgMusic = "engaging",
|
|
133
|
-
bgVolume = 1.4,
|
|
134
|
-
outputVolume = 1,
|
|
135
149
|
videoType = "long",
|
|
136
|
-
includeWatermark =
|
|
150
|
+
includeWatermark = false,
|
|
137
151
|
logo,
|
|
138
|
-
timing =
|
|
152
|
+
timing = 1,
|
|
153
|
+
useColor = true,
|
|
154
|
+
// newly added backend parameters
|
|
155
|
+
newScript,
|
|
156
|
+
logoPlacement,
|
|
157
|
+
videoInstructions,
|
|
158
|
+
useLineart2Style,
|
|
159
|
+
audioClip,
|
|
160
|
+
isPublic,
|
|
161
|
+
useAsIs,
|
|
162
|
+
skipAnimation,
|
|
163
|
+
userImages,
|
|
164
|
+
userImagesDescriptions,
|
|
165
|
+
userVideos,
|
|
166
|
+
userVideosDescription,
|
|
167
|
+
userAudioInVideo,
|
|
168
|
+
use2Style,
|
|
169
|
+
// specificAnimation, // not yet supported by the Golpo 2.0 pipeline
|
|
170
|
+
imageStyle,
|
|
171
|
+
inputImages,
|
|
172
|
+
penStyle,
|
|
173
|
+
showPencilCursor,
|
|
174
|
+
pacing,
|
|
175
|
+
justReturnScript
|
|
139
176
|
} = opts;
|
|
177
|
+
const concurrency = 8;
|
|
178
|
+
const request_payload = {
|
|
179
|
+
prompt,
|
|
180
|
+
video_voice: style,
|
|
181
|
+
video_duration: String(timing),
|
|
182
|
+
video_type: videoType,
|
|
183
|
+
language,
|
|
184
|
+
voice_instructions: voiceInstructions,
|
|
185
|
+
bg_music: bgMusic,
|
|
186
|
+
use_color: useColor,
|
|
187
|
+
direct_script: newScript,
|
|
188
|
+
script_mode: newScript ? true : false,
|
|
189
|
+
logo_placement: logoPlacement,
|
|
190
|
+
video_instructions: videoInstructions,
|
|
191
|
+
use_lineart_2_style: useLineart2Style,
|
|
192
|
+
audio_clip: audioClip,
|
|
193
|
+
is_public: isPublic,
|
|
194
|
+
use_as_is: useAsIs,
|
|
195
|
+
skip_animation: skipAnimation,
|
|
196
|
+
user_images: userImages,
|
|
197
|
+
user_images_descriptions: userImagesDescriptions,
|
|
198
|
+
user_videos: userVideos,
|
|
199
|
+
user_videos_description: userVideosDescription,
|
|
200
|
+
user_audio_in_video: userAudioInVideo,
|
|
201
|
+
use_2_0_style: use2Style,
|
|
202
|
+
// specific_animation: specificAnimation, // not yet supported by the pipeline
|
|
203
|
+
image_style: imageStyle,
|
|
204
|
+
input_images: inputImages,
|
|
205
|
+
pen_style: penStyle,
|
|
206
|
+
show_pencil_cursor: penStyle ? true : showPencilCursor ?? false,
|
|
207
|
+
pacing,
|
|
208
|
+
own_narration_video_mode: null,
|
|
209
|
+
own_narration_pip_position: null,
|
|
210
|
+
just_return_script: justReturnScript,
|
|
211
|
+
attached_documents: uploads,
|
|
212
|
+
source: "node-sdk"
|
|
213
|
+
};
|
|
140
214
|
const fields = [
|
|
141
215
|
["prompt", prompt],
|
|
142
|
-
["do_research", String(doResearch)],
|
|
143
|
-
["tts_model", ttsModel],
|
|
144
|
-
["bg_volume", String(bgVolume)],
|
|
145
|
-
["output_volume", String(outputVolume)],
|
|
146
216
|
["style", style],
|
|
147
217
|
["video_type", videoType],
|
|
148
218
|
["include_watermark", String(includeWatermark)],
|
|
149
|
-
["timing", timing]
|
|
219
|
+
["timing", String(timing)],
|
|
220
|
+
["use_color", String(useColor)]
|
|
150
221
|
];
|
|
151
222
|
if (language) fields.push(["language", language]);
|
|
152
223
|
if (voiceInstructions) fields.push(["voice_instructions", voiceInstructions]);
|
|
153
|
-
if (personality1) fields.push(["personality_1", personality1]);
|
|
154
224
|
if (bgMusic) fields.push(["bg_music", bgMusic]);
|
|
225
|
+
try {
|
|
226
|
+
const result = await this.createVideoRecord({
|
|
227
|
+
topic: prompt,
|
|
228
|
+
requestPayload: request_payload
|
|
229
|
+
});
|
|
230
|
+
if (result && result.videoId) {
|
|
231
|
+
fields.push(["video_id", result.videoId]);
|
|
232
|
+
}
|
|
233
|
+
} catch (error) {
|
|
234
|
+
}
|
|
235
|
+
if (newScript) fields.push(["new_script", newScript]);
|
|
236
|
+
if (logoPlacement) fields.push(["logo_placement", logoPlacement]);
|
|
237
|
+
if (videoInstructions) fields.push(["video_instructions", videoInstructions]);
|
|
238
|
+
if (useLineart2Style) fields.push(["use_lineart_2_style", useLineart2Style]);
|
|
239
|
+
if (isPublic != null) fields.push(["is_public", String(isPublic)]);
|
|
240
|
+
if (useAsIs) {
|
|
241
|
+
const value = Array.isArray(useAsIs) ? JSON.stringify(useAsIs) : useAsIs;
|
|
242
|
+
fields.push(["use_as_is", value]);
|
|
243
|
+
}
|
|
244
|
+
if (skipAnimation) {
|
|
245
|
+
const value = Array.isArray(skipAnimation) ? JSON.stringify(skipAnimation) : skipAnimation;
|
|
246
|
+
fields.push(["skip_animation", value]);
|
|
247
|
+
}
|
|
248
|
+
if (userImagesDescriptions) {
|
|
249
|
+
const value = Array.isArray(userImagesDescriptions) ? JSON.stringify(userImagesDescriptions) : userImagesDescriptions;
|
|
250
|
+
fields.push(["user_images_descriptions", value]);
|
|
251
|
+
}
|
|
252
|
+
if (userVideosDescription) {
|
|
253
|
+
const value = Array.isArray(userVideosDescription) ? JSON.stringify(userVideosDescription) : userVideosDescription;
|
|
254
|
+
fields.push(["user_videos_description", value]);
|
|
255
|
+
}
|
|
256
|
+
if (userAudioInVideo) {
|
|
257
|
+
fields.push(["user_audio_in_video", userAudioInVideo]);
|
|
258
|
+
} else if (userVideos) {
|
|
259
|
+
fields.push(["user_audio_in_video", "[]"]);
|
|
260
|
+
}
|
|
261
|
+
if (use2Style != null) fields.push(["use_2_0_style", String(use2Style)]);
|
|
262
|
+
if (imageStyle) fields.push(["image_style", imageStyle]);
|
|
263
|
+
if (penStyle) fields.push(["pen_style", penStyle]);
|
|
264
|
+
const effectiveShowPencilCursor = penStyle ? true : showPencilCursor ?? false;
|
|
265
|
+
fields.push(["show_pencil_cursor", String(effectiveShowPencilCursor)]);
|
|
266
|
+
if (pacing) fields.push(["pacing", pacing]);
|
|
267
|
+
if (justReturnScript != null) fields.push(["just_return_script", String(justReturnScript)]);
|
|
155
268
|
if (logo) {
|
|
156
269
|
fields.push(["logo_path", logo]);
|
|
157
270
|
}
|
|
158
|
-
const formData = await this.createFormData(
|
|
271
|
+
const formData = await this.createFormData(
|
|
272
|
+
fields,
|
|
273
|
+
uploads,
|
|
274
|
+
concurrency,
|
|
275
|
+
logo,
|
|
276
|
+
audioClip,
|
|
277
|
+
userImages,
|
|
278
|
+
userVideos,
|
|
279
|
+
inputImages
|
|
280
|
+
);
|
|
159
281
|
const { data } = await this.http.post("/generate", formData, {
|
|
160
282
|
timeout: 24e4,
|
|
161
283
|
headers: formData.getHeaders()
|
|
162
284
|
});
|
|
163
|
-
|
|
285
|
+
if (justReturnScript) {
|
|
286
|
+
const r2 = await this.pollUntilComplete(
|
|
287
|
+
data.job_id,
|
|
288
|
+
pollIntervalMs,
|
|
289
|
+
"/script-status"
|
|
290
|
+
);
|
|
291
|
+
return { url: "", script: r2.podcast_script, videoId: data.job_id };
|
|
292
|
+
}
|
|
293
|
+
const r = await this.pollUntilComplete(
|
|
164
294
|
data.job_id,
|
|
165
295
|
pollIntervalMs
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
296
|
+
);
|
|
297
|
+
return { url: r.podcast_url, script: r.podcast_script, videoId: data.job_id };
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Private helper: Get user email from API key
|
|
301
|
+
* Backend resolves: api_key -> user_id -> user_credits.email
|
|
302
|
+
*/
|
|
303
|
+
async getUserEmailFromApiKey() {
|
|
304
|
+
try {
|
|
305
|
+
const { data } = await this.http.get("/api/resolve-email-from-api-key");
|
|
306
|
+
return data.email || null;
|
|
307
|
+
} catch (error) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async createVideoRecord(opts) {
|
|
312
|
+
const {
|
|
313
|
+
topic,
|
|
314
|
+
context = "",
|
|
315
|
+
scenes = 6,
|
|
316
|
+
pipeline = "color",
|
|
317
|
+
shareDocuments = false,
|
|
318
|
+
logoPlacement = null,
|
|
319
|
+
audioClipUrl = null,
|
|
320
|
+
requestPayload
|
|
321
|
+
} = opts;
|
|
322
|
+
const emailFromApiKey = await this.getUserEmailFromApiKey();
|
|
323
|
+
if (!emailFromApiKey) {
|
|
324
|
+
throw new Error("Email not found");
|
|
325
|
+
}
|
|
326
|
+
const body = {
|
|
327
|
+
topic,
|
|
328
|
+
context,
|
|
329
|
+
scenes,
|
|
330
|
+
pipeline,
|
|
331
|
+
user_email: emailFromApiKey,
|
|
332
|
+
share_documents: shareDocuments,
|
|
333
|
+
logo_placement: logoPlacement,
|
|
334
|
+
audio_clip_url: audioClipUrl,
|
|
335
|
+
request_payload: requestPayload ? JSON.stringify(requestPayload) : null
|
|
336
|
+
};
|
|
337
|
+
const { data } = await this.http.post("/api/create-video-record", body);
|
|
338
|
+
return { videoId: data.video_id };
|
|
170
339
|
}
|
|
171
340
|
/**
|
|
172
341
|
* Edit specific frames of a video and regenerate the video.
|
|
@@ -213,11 +382,11 @@ var Golpo = class {
|
|
|
213
382
|
try {
|
|
214
383
|
const frameVersions = await this.getFrameVersions(videoId);
|
|
215
384
|
let frameAnimations = frameVersions.frame_animations ? { ...frameVersions.frame_animations } : {};
|
|
216
|
-
|
|
385
|
+
for (const frameId of frameIds) {
|
|
217
386
|
await this.setFrameVersion(videoId, frameId, editResult);
|
|
218
387
|
const updatedVersions = await this.getFrameVersions(videoId);
|
|
219
388
|
frameAnimations = updatedVersions.frame_animations || {};
|
|
220
|
-
}
|
|
389
|
+
}
|
|
221
390
|
const mp4Urls = Object.entries(frameAnimations).sort(([a], [b]) => parseInt(a) - parseInt(b)).map(([_, url]) => url);
|
|
222
391
|
if (mp4Urls.length === 0) {
|
|
223
392
|
throw new Error("No frame animations found to combine");
|
|
@@ -227,17 +396,11 @@ var Golpo = class {
|
|
|
227
396
|
pollIntervalMs,
|
|
228
397
|
videoUrl
|
|
229
398
|
};
|
|
230
|
-
const
|
|
231
|
-
return {
|
|
232
|
-
videoUrl: combinedUrl,
|
|
233
|
-
jobId
|
|
234
|
-
};
|
|
399
|
+
const combined = await this.combineVideos(combineOptions);
|
|
400
|
+
return { videoUrl: combined.url, jobId };
|
|
235
401
|
} catch (error) {
|
|
236
402
|
console.warn("Failed to auto-combine videos, returning edit result:", error);
|
|
237
|
-
return {
|
|
238
|
-
videoUrl: editResult,
|
|
239
|
-
jobId
|
|
240
|
-
};
|
|
403
|
+
return { videoUrl: editResult, jobId };
|
|
241
404
|
}
|
|
242
405
|
}
|
|
243
406
|
/**
|
|
@@ -391,19 +554,25 @@ var Golpo = class {
|
|
|
391
554
|
if (!combineJobId) {
|
|
392
555
|
throw new Error("No job ID received from combine-videos API");
|
|
393
556
|
}
|
|
394
|
-
|
|
557
|
+
const url = await this.pollEditStatus(combineJobId, pollIntervalMs);
|
|
558
|
+
return { url };
|
|
395
559
|
}
|
|
396
560
|
/* ------------------------------------------------------------ *
|
|
397
561
|
* INTERNAL HELPERS
|
|
398
562
|
* ------------------------------------------------------------ */
|
|
399
|
-
async pollUntilComplete(jobId, interval) {
|
|
563
|
+
async pollUntilComplete(jobId, interval, statusPath = "/status") {
|
|
400
564
|
while (true) {
|
|
565
|
+
let data;
|
|
401
566
|
try {
|
|
402
|
-
const
|
|
403
|
-
|
|
567
|
+
const res = await this.http.get(`${statusPath}/${jobId}`);
|
|
568
|
+
data = res.data;
|
|
404
569
|
} catch (error) {
|
|
405
570
|
console.warn(`Status check failed for job ${jobId}, retrying in ${interval}ms:`, error instanceof Error ? error.message : error);
|
|
406
571
|
}
|
|
572
|
+
if (data?.status === "completed") return data;
|
|
573
|
+
if (data?.status === "failed") {
|
|
574
|
+
throw new Error(`Job ${jobId} failed: ${data.error || data.message || "unknown error"}`);
|
|
575
|
+
}
|
|
407
576
|
await new Promise((r) => setTimeout(r, interval));
|
|
408
577
|
}
|
|
409
578
|
}
|
|
@@ -453,7 +622,50 @@ var Golpo = class {
|
|
|
453
622
|
attempts++;
|
|
454
623
|
}
|
|
455
624
|
}
|
|
456
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Upload a file using /upload-url endpoint and return the final URL.
|
|
627
|
+
* Replicates the _presign_and_upload_one logic from the backend.
|
|
628
|
+
*/
|
|
629
|
+
async uploadFileAndGetUrl(filePath) {
|
|
630
|
+
const absPath = (0, import_path.resolve)(filePath.trim().replace(/^<|>$/g, ""));
|
|
631
|
+
try {
|
|
632
|
+
await import_fs.promises.access(absPath);
|
|
633
|
+
} catch (error) {
|
|
634
|
+
throw new Error(`File not found: ${absPath}. Original path: ${filePath}`);
|
|
635
|
+
}
|
|
636
|
+
const fileName = (0, import_path.basename)(absPath);
|
|
637
|
+
const fileData = await import_fs.promises.readFile(absPath);
|
|
638
|
+
const mimeType = (0, import_mime_types.lookup)(absPath) || "application/octet-stream";
|
|
639
|
+
const { data: presignInfo } = await this.http.post(
|
|
640
|
+
"/upload-url",
|
|
641
|
+
{ filename: fileName },
|
|
642
|
+
{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }
|
|
643
|
+
);
|
|
644
|
+
let finalUrl;
|
|
645
|
+
if (presignInfo.url && presignInfo.fields) {
|
|
646
|
+
const uploadFormData = new import_form_data.default();
|
|
647
|
+
Object.entries(presignInfo.fields).forEach(([key, value]) => {
|
|
648
|
+
uploadFormData.append(key, value);
|
|
649
|
+
});
|
|
650
|
+
uploadFormData.append("file", fileData, { filename: fileName });
|
|
651
|
+
await import_axios.default.post(presignInfo.url, uploadFormData, {
|
|
652
|
+
headers: uploadFormData.getHeaders(),
|
|
653
|
+
timeout: 3e4
|
|
654
|
+
});
|
|
655
|
+
finalUrl = presignInfo.final_url || presignInfo.url.split("?")[0];
|
|
656
|
+
} else if (presignInfo.upload_url || presignInfo.url) {
|
|
657
|
+
const uploadUrl = presignInfo.upload_url || presignInfo.url;
|
|
658
|
+
await import_axios.default.put(uploadUrl, fileData, {
|
|
659
|
+
headers: { "Content-Type": mimeType },
|
|
660
|
+
timeout: 3e4
|
|
661
|
+
});
|
|
662
|
+
finalUrl = presignInfo.final_url || uploadUrl.split("?")[0];
|
|
663
|
+
} else {
|
|
664
|
+
throw new Error(`Unrecognized presign response: ${JSON.stringify(presignInfo)}`);
|
|
665
|
+
}
|
|
666
|
+
return finalUrl;
|
|
667
|
+
}
|
|
668
|
+
async createFormData(fields, uploads, concurrency, logo, audioClip, userImages, userVideos, inputImages) {
|
|
457
669
|
const formData = new import_form_data.default();
|
|
458
670
|
fields.forEach(([key, value]) => {
|
|
459
671
|
if (key !== "logo_path") {
|
|
@@ -462,16 +674,147 @@ var Golpo = class {
|
|
|
462
674
|
});
|
|
463
675
|
if (logo) {
|
|
464
676
|
const logoPath = logo.trim().replace(/^<|>$/g, "");
|
|
677
|
+
let logoUrl;
|
|
465
678
|
if (URL_RE.test(logoPath)) {
|
|
466
|
-
|
|
679
|
+
logoUrl = logoPath;
|
|
680
|
+
} else {
|
|
681
|
+
logoUrl = await this.uploadFileAndGetUrl(logoPath);
|
|
682
|
+
}
|
|
683
|
+
formData.append("logo", logoUrl);
|
|
684
|
+
}
|
|
685
|
+
if (audioClip) {
|
|
686
|
+
const audioList = Array.isArray(audioClip) ? audioClip : [audioClip];
|
|
687
|
+
const audioLocalFiles = [];
|
|
688
|
+
const audioUrls = [];
|
|
689
|
+
audioList.forEach((item) => {
|
|
690
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
691
|
+
if (URL_RE.test(path)) {
|
|
692
|
+
audioUrls.push(path);
|
|
693
|
+
} else {
|
|
694
|
+
audioLocalFiles.push(path);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
if (audioLocalFiles.length > 0) {
|
|
698
|
+
const limit = (0, import_p_limit.default)(concurrency);
|
|
699
|
+
const uploadedUrls = await Promise.all(
|
|
700
|
+
audioLocalFiles.map(
|
|
701
|
+
(filePath) => limit(() => this.uploadFileAndGetUrl(filePath))
|
|
702
|
+
)
|
|
703
|
+
);
|
|
704
|
+
audioUrls.push(...uploadedUrls);
|
|
705
|
+
}
|
|
706
|
+
if (audioUrls.length > 0) {
|
|
707
|
+
formData.append("audio_clip", audioUrls[0]);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (userImages) {
|
|
711
|
+
const imagesList = Array.isArray(userImages) ? userImages : [userImages];
|
|
712
|
+
const imageLocalFiles = [];
|
|
713
|
+
const imageUrls = [];
|
|
714
|
+
console.log("[SDK] Processing userImages:", imagesList);
|
|
715
|
+
imagesList.forEach((item) => {
|
|
716
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
717
|
+
if (URL_RE.test(path)) {
|
|
718
|
+
console.log("[SDK] userImages item is URL:", path);
|
|
719
|
+
imageUrls.push(path);
|
|
720
|
+
} else {
|
|
721
|
+
console.log("[SDK] userImages item is local file:", path);
|
|
722
|
+
imageLocalFiles.push(path);
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
if (imageLocalFiles.length > 0) {
|
|
726
|
+
console.log("[SDK] Uploading", imageLocalFiles.length, "image file(s)");
|
|
727
|
+
const limit = (0, import_p_limit.default)(concurrency);
|
|
728
|
+
try {
|
|
729
|
+
const uploadedUrls = await Promise.all(
|
|
730
|
+
imageLocalFiles.map(
|
|
731
|
+
(filePath) => limit(async () => {
|
|
732
|
+
try {
|
|
733
|
+
console.log("[SDK] Uploading image file:", filePath);
|
|
734
|
+
const url = await this.uploadFileAndGetUrl(filePath);
|
|
735
|
+
console.log("[SDK] Image uploaded, got URL:", url);
|
|
736
|
+
return url;
|
|
737
|
+
} catch (error) {
|
|
738
|
+
console.error(`[SDK] Failed to upload image file ${filePath}:`, error);
|
|
739
|
+
throw error;
|
|
740
|
+
}
|
|
741
|
+
})
|
|
742
|
+
)
|
|
743
|
+
);
|
|
744
|
+
imageUrls.push(...uploadedUrls);
|
|
745
|
+
console.log("[SDK] All images uploaded, total URLs:", imageUrls.length);
|
|
746
|
+
} catch (error) {
|
|
747
|
+
console.error("[SDK] Error uploading image files:", error);
|
|
748
|
+
throw error;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (imageUrls.length > 0) {
|
|
752
|
+
const jsonArray = JSON.stringify(imageUrls);
|
|
753
|
+
console.log("[SDK] Sending user_images as JSON:", jsonArray);
|
|
754
|
+
formData.append("user_images", jsonArray);
|
|
755
|
+
} else {
|
|
756
|
+
console.log("[SDK] No image URLs to send");
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (userVideos) {
|
|
760
|
+
const videosList = Array.isArray(userVideos) ? userVideos : [userVideos];
|
|
761
|
+
const videoLocalFiles = [];
|
|
762
|
+
const videoUrls = [];
|
|
763
|
+
videosList.forEach((item) => {
|
|
764
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
765
|
+
if (URL_RE.test(path)) {
|
|
766
|
+
videoUrls.push(path);
|
|
767
|
+
} else {
|
|
768
|
+
videoLocalFiles.push(path);
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
if (videoLocalFiles.length > 0) {
|
|
772
|
+
const limit = (0, import_p_limit.default)(concurrency);
|
|
773
|
+
try {
|
|
774
|
+
const uploadedUrls = await Promise.all(
|
|
775
|
+
videoLocalFiles.map(
|
|
776
|
+
(filePath) => limit(async () => {
|
|
777
|
+
try {
|
|
778
|
+
return await this.uploadFileAndGetUrl(filePath);
|
|
779
|
+
} catch (error) {
|
|
780
|
+
console.error(`Failed to upload video file ${filePath}:`, error);
|
|
781
|
+
throw error;
|
|
782
|
+
}
|
|
783
|
+
})
|
|
784
|
+
)
|
|
785
|
+
);
|
|
786
|
+
videoUrls.push(...uploadedUrls);
|
|
787
|
+
} catch (error) {
|
|
788
|
+
console.error("Error uploading video files:", error);
|
|
789
|
+
throw error;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (videoUrls.length > 0) {
|
|
793
|
+
formData.append("user_videos", JSON.stringify(videoUrls));
|
|
467
794
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
795
|
+
}
|
|
796
|
+
if (inputImages) {
|
|
797
|
+
const imagesList = Array.isArray(inputImages) ? inputImages : [inputImages];
|
|
798
|
+
const localFiles = [];
|
|
799
|
+
const imageUrls = [];
|
|
800
|
+
imagesList.forEach((item) => {
|
|
801
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
802
|
+
if (URL_RE.test(path)) {
|
|
803
|
+
imageUrls.push(path);
|
|
804
|
+
} else {
|
|
805
|
+
localFiles.push(path);
|
|
806
|
+
}
|
|
474
807
|
});
|
|
808
|
+
if (localFiles.length > 0) {
|
|
809
|
+
const limit = (0, import_p_limit.default)(concurrency);
|
|
810
|
+
const uploadedUrls = await Promise.all(
|
|
811
|
+
localFiles.map((filePath) => limit(() => this.uploadFileAndGetUrl(filePath)))
|
|
812
|
+
);
|
|
813
|
+
imageUrls.push(...uploadedUrls);
|
|
814
|
+
}
|
|
815
|
+
if (imageUrls.length > 0) {
|
|
816
|
+
formData.append("input_images", JSON.stringify(imageUrls));
|
|
817
|
+
}
|
|
475
818
|
}
|
|
476
819
|
if (uploads) {
|
|
477
820
|
const list = typeof uploads === "string" ? [uploads] : [...uploads];
|