@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.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/Golpo.ts
|
|
2
2
|
import axios from "axios";
|
|
3
|
-
import { createReadStream } from "fs";
|
|
3
|
+
import { createReadStream, promises as fs } from "fs";
|
|
4
4
|
import { basename, resolve } from "path";
|
|
5
5
|
import { lookup as mimeLookup } from "mime-types";
|
|
6
6
|
import pLimit from "p-limit";
|
|
@@ -20,33 +20,55 @@ var Golpo = class {
|
|
|
20
20
|
async createPodcastJob(prompt, opts = {}) {
|
|
21
21
|
const {
|
|
22
22
|
uploads,
|
|
23
|
-
concurrency = 8,
|
|
24
|
-
addMusic = false,
|
|
25
23
|
voiceInstructions,
|
|
26
|
-
personality1,
|
|
27
|
-
personality2,
|
|
28
|
-
doResearch = false,
|
|
29
|
-
ttsModel = "accurate",
|
|
30
24
|
language,
|
|
31
|
-
style = "
|
|
25
|
+
style = "solo-female-3",
|
|
32
26
|
bgMusic,
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
// Extended params
|
|
28
|
+
newScript,
|
|
29
|
+
timing = 1
|
|
30
|
+
// timing in minutes – default 1 if not provided
|
|
35
31
|
} = opts;
|
|
32
|
+
const concurrency = 8;
|
|
36
33
|
const fields = [
|
|
37
34
|
["prompt", prompt],
|
|
38
|
-
["
|
|
39
|
-
["do_research", String(doResearch)],
|
|
40
|
-
["tts_model", ttsModel],
|
|
41
|
-
["style", style],
|
|
42
|
-
["output_volume", String(outputVolume)]
|
|
35
|
+
["style", style]
|
|
43
36
|
];
|
|
44
37
|
if (voiceInstructions) fields.push(["voice_instructions", voiceInstructions]);
|
|
45
|
-
if (personality1) fields.push(["personality_1", personality1]);
|
|
46
|
-
if (personality2) fields.push(["personality_2", personality2]);
|
|
47
38
|
if (language) fields.push(["language", language]);
|
|
48
39
|
if (bgMusic) fields.push(["bg_music", bgMusic]);
|
|
49
|
-
if (
|
|
40
|
+
if (newScript != null) fields.push(["new_script", newScript]);
|
|
41
|
+
fields.push(["timing", String(timing)]);
|
|
42
|
+
fields.push(["video_type", "null"]);
|
|
43
|
+
const hasUploads = (() => {
|
|
44
|
+
if (!uploads) return false;
|
|
45
|
+
if (typeof uploads === "string") return uploads.trim().length > 0;
|
|
46
|
+
const iterator = uploads[Symbol.iterator]();
|
|
47
|
+
const first = iterator.next();
|
|
48
|
+
return !first.done;
|
|
49
|
+
})();
|
|
50
|
+
const request_payload = {
|
|
51
|
+
prompt,
|
|
52
|
+
video_voice: style,
|
|
53
|
+
video_duration: String(timing),
|
|
54
|
+
video_type: "null",
|
|
55
|
+
language,
|
|
56
|
+
voice_instructions: voiceInstructions,
|
|
57
|
+
new_script: newScript,
|
|
58
|
+
bg_music: bgMusic,
|
|
59
|
+
attached_documents: uploads,
|
|
60
|
+
source: "node-sdk"
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
const result = await this.createVideoRecord({
|
|
64
|
+
topic: prompt,
|
|
65
|
+
requestPayload: request_payload
|
|
66
|
+
});
|
|
67
|
+
if (result && result.videoId) {
|
|
68
|
+
fields.push(["video_id", result.videoId]);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
}
|
|
50
72
|
const formData = await this.createFormData(fields, uploads, concurrency);
|
|
51
73
|
const { data } = await this.http.post("/generate", formData, {
|
|
52
74
|
timeout: 24e4,
|
|
@@ -73,63 +95,210 @@ var Golpo = class {
|
|
|
73
95
|
async createPodcast(prompt, opts = {}) {
|
|
74
96
|
const { pollIntervalMs = 2e3, ...jobOpts } = opts;
|
|
75
97
|
const jobId = await this.createPodcastJob(prompt, jobOpts);
|
|
76
|
-
|
|
98
|
+
const r = await this.pollUntilComplete(
|
|
77
99
|
jobId,
|
|
78
100
|
pollIntervalMs
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
podcastScript: r.podcast_script
|
|
82
|
-
}));
|
|
101
|
+
);
|
|
102
|
+
return { url: r.podcast_url, script: r.podcast_script, videoId: jobId };
|
|
83
103
|
}
|
|
84
104
|
async createVideo(prompt, opts = {}) {
|
|
85
105
|
const {
|
|
86
106
|
uploads,
|
|
87
107
|
pollIntervalMs = 2e3,
|
|
88
|
-
concurrency = 8,
|
|
89
108
|
voiceInstructions,
|
|
90
|
-
personality1,
|
|
91
|
-
doResearch = false,
|
|
92
|
-
ttsModel = "accurate",
|
|
93
109
|
language,
|
|
94
|
-
style = "solo-female",
|
|
110
|
+
style = "solo-female-3",
|
|
95
111
|
bgMusic = "engaging",
|
|
96
|
-
bgVolume = 1.4,
|
|
97
|
-
outputVolume = 1,
|
|
98
112
|
videoType = "long",
|
|
99
|
-
includeWatermark =
|
|
113
|
+
includeWatermark = false,
|
|
100
114
|
logo,
|
|
101
|
-
timing =
|
|
115
|
+
timing = 1,
|
|
116
|
+
useColor = true,
|
|
117
|
+
// newly added backend parameters
|
|
118
|
+
newScript,
|
|
119
|
+
logoPlacement,
|
|
120
|
+
videoInstructions,
|
|
121
|
+
useLineart2Style,
|
|
122
|
+
audioClip,
|
|
123
|
+
isPublic,
|
|
124
|
+
useAsIs,
|
|
125
|
+
skipAnimation,
|
|
126
|
+
userImages,
|
|
127
|
+
userImagesDescriptions,
|
|
128
|
+
userVideos,
|
|
129
|
+
userVideosDescription,
|
|
130
|
+
userAudioInVideo,
|
|
131
|
+
use2Style,
|
|
132
|
+
// specificAnimation, // not yet supported by the Golpo 2.0 pipeline
|
|
133
|
+
imageStyle,
|
|
134
|
+
inputImages,
|
|
135
|
+
penStyle,
|
|
136
|
+
showPencilCursor,
|
|
137
|
+
pacing,
|
|
138
|
+
justReturnScript
|
|
102
139
|
} = opts;
|
|
140
|
+
const concurrency = 8;
|
|
141
|
+
const request_payload = {
|
|
142
|
+
prompt,
|
|
143
|
+
video_voice: style,
|
|
144
|
+
video_duration: String(timing),
|
|
145
|
+
video_type: videoType,
|
|
146
|
+
language,
|
|
147
|
+
voice_instructions: voiceInstructions,
|
|
148
|
+
bg_music: bgMusic,
|
|
149
|
+
use_color: useColor,
|
|
150
|
+
direct_script: newScript,
|
|
151
|
+
script_mode: newScript ? true : false,
|
|
152
|
+
logo_placement: logoPlacement,
|
|
153
|
+
video_instructions: videoInstructions,
|
|
154
|
+
use_lineart_2_style: useLineart2Style,
|
|
155
|
+
audio_clip: audioClip,
|
|
156
|
+
is_public: isPublic,
|
|
157
|
+
use_as_is: useAsIs,
|
|
158
|
+
skip_animation: skipAnimation,
|
|
159
|
+
user_images: userImages,
|
|
160
|
+
user_images_descriptions: userImagesDescriptions,
|
|
161
|
+
user_videos: userVideos,
|
|
162
|
+
user_videos_description: userVideosDescription,
|
|
163
|
+
user_audio_in_video: userAudioInVideo,
|
|
164
|
+
use_2_0_style: use2Style,
|
|
165
|
+
// specific_animation: specificAnimation, // not yet supported by the pipeline
|
|
166
|
+
image_style: imageStyle,
|
|
167
|
+
input_images: inputImages,
|
|
168
|
+
pen_style: penStyle,
|
|
169
|
+
show_pencil_cursor: penStyle ? true : showPencilCursor ?? false,
|
|
170
|
+
pacing,
|
|
171
|
+
own_narration_video_mode: null,
|
|
172
|
+
own_narration_pip_position: null,
|
|
173
|
+
just_return_script: justReturnScript,
|
|
174
|
+
attached_documents: uploads,
|
|
175
|
+
source: "node-sdk"
|
|
176
|
+
};
|
|
103
177
|
const fields = [
|
|
104
178
|
["prompt", prompt],
|
|
105
|
-
["do_research", String(doResearch)],
|
|
106
|
-
["tts_model", ttsModel],
|
|
107
|
-
["bg_volume", String(bgVolume)],
|
|
108
|
-
["output_volume", String(outputVolume)],
|
|
109
179
|
["style", style],
|
|
110
180
|
["video_type", videoType],
|
|
111
181
|
["include_watermark", String(includeWatermark)],
|
|
112
|
-
["timing", timing]
|
|
182
|
+
["timing", String(timing)],
|
|
183
|
+
["use_color", String(useColor)]
|
|
113
184
|
];
|
|
114
185
|
if (language) fields.push(["language", language]);
|
|
115
186
|
if (voiceInstructions) fields.push(["voice_instructions", voiceInstructions]);
|
|
116
|
-
if (personality1) fields.push(["personality_1", personality1]);
|
|
117
187
|
if (bgMusic) fields.push(["bg_music", bgMusic]);
|
|
188
|
+
try {
|
|
189
|
+
const result = await this.createVideoRecord({
|
|
190
|
+
topic: prompt,
|
|
191
|
+
requestPayload: request_payload
|
|
192
|
+
});
|
|
193
|
+
if (result && result.videoId) {
|
|
194
|
+
fields.push(["video_id", result.videoId]);
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
}
|
|
198
|
+
if (newScript) fields.push(["new_script", newScript]);
|
|
199
|
+
if (logoPlacement) fields.push(["logo_placement", logoPlacement]);
|
|
200
|
+
if (videoInstructions) fields.push(["video_instructions", videoInstructions]);
|
|
201
|
+
if (useLineart2Style) fields.push(["use_lineart_2_style", useLineart2Style]);
|
|
202
|
+
if (isPublic != null) fields.push(["is_public", String(isPublic)]);
|
|
203
|
+
if (useAsIs) {
|
|
204
|
+
const value = Array.isArray(useAsIs) ? JSON.stringify(useAsIs) : useAsIs;
|
|
205
|
+
fields.push(["use_as_is", value]);
|
|
206
|
+
}
|
|
207
|
+
if (skipAnimation) {
|
|
208
|
+
const value = Array.isArray(skipAnimation) ? JSON.stringify(skipAnimation) : skipAnimation;
|
|
209
|
+
fields.push(["skip_animation", value]);
|
|
210
|
+
}
|
|
211
|
+
if (userImagesDescriptions) {
|
|
212
|
+
const value = Array.isArray(userImagesDescriptions) ? JSON.stringify(userImagesDescriptions) : userImagesDescriptions;
|
|
213
|
+
fields.push(["user_images_descriptions", value]);
|
|
214
|
+
}
|
|
215
|
+
if (userVideosDescription) {
|
|
216
|
+
const value = Array.isArray(userVideosDescription) ? JSON.stringify(userVideosDescription) : userVideosDescription;
|
|
217
|
+
fields.push(["user_videos_description", value]);
|
|
218
|
+
}
|
|
219
|
+
if (userAudioInVideo) {
|
|
220
|
+
fields.push(["user_audio_in_video", userAudioInVideo]);
|
|
221
|
+
} else if (userVideos) {
|
|
222
|
+
fields.push(["user_audio_in_video", "[]"]);
|
|
223
|
+
}
|
|
224
|
+
if (use2Style != null) fields.push(["use_2_0_style", String(use2Style)]);
|
|
225
|
+
if (imageStyle) fields.push(["image_style", imageStyle]);
|
|
226
|
+
if (penStyle) fields.push(["pen_style", penStyle]);
|
|
227
|
+
const effectiveShowPencilCursor = penStyle ? true : showPencilCursor ?? false;
|
|
228
|
+
fields.push(["show_pencil_cursor", String(effectiveShowPencilCursor)]);
|
|
229
|
+
if (pacing) fields.push(["pacing", pacing]);
|
|
230
|
+
if (justReturnScript != null) fields.push(["just_return_script", String(justReturnScript)]);
|
|
118
231
|
if (logo) {
|
|
119
232
|
fields.push(["logo_path", logo]);
|
|
120
233
|
}
|
|
121
|
-
const formData = await this.createFormData(
|
|
234
|
+
const formData = await this.createFormData(
|
|
235
|
+
fields,
|
|
236
|
+
uploads,
|
|
237
|
+
concurrency,
|
|
238
|
+
logo,
|
|
239
|
+
audioClip,
|
|
240
|
+
userImages,
|
|
241
|
+
userVideos,
|
|
242
|
+
inputImages
|
|
243
|
+
);
|
|
122
244
|
const { data } = await this.http.post("/generate", formData, {
|
|
123
245
|
timeout: 24e4,
|
|
124
246
|
headers: formData.getHeaders()
|
|
125
247
|
});
|
|
126
|
-
|
|
248
|
+
if (justReturnScript) {
|
|
249
|
+
const r2 = await this.pollUntilComplete(
|
|
250
|
+
data.job_id,
|
|
251
|
+
pollIntervalMs,
|
|
252
|
+
"/script-status"
|
|
253
|
+
);
|
|
254
|
+
return { url: "", script: r2.podcast_script, videoId: data.job_id };
|
|
255
|
+
}
|
|
256
|
+
const r = await this.pollUntilComplete(
|
|
127
257
|
data.job_id,
|
|
128
258
|
pollIntervalMs
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
259
|
+
);
|
|
260
|
+
return { url: r.podcast_url, script: r.podcast_script, videoId: data.job_id };
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Private helper: Get user email from API key
|
|
264
|
+
* Backend resolves: api_key -> user_id -> user_credits.email
|
|
265
|
+
*/
|
|
266
|
+
async getUserEmailFromApiKey() {
|
|
267
|
+
try {
|
|
268
|
+
const { data } = await this.http.get("/api/resolve-email-from-api-key");
|
|
269
|
+
return data.email || null;
|
|
270
|
+
} catch (error) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async createVideoRecord(opts) {
|
|
275
|
+
const {
|
|
276
|
+
topic,
|
|
277
|
+
context = "",
|
|
278
|
+
scenes = 6,
|
|
279
|
+
pipeline = "color",
|
|
280
|
+
shareDocuments = false,
|
|
281
|
+
logoPlacement = null,
|
|
282
|
+
audioClipUrl = null,
|
|
283
|
+
requestPayload
|
|
284
|
+
} = opts;
|
|
285
|
+
const emailFromApiKey = await this.getUserEmailFromApiKey();
|
|
286
|
+
if (!emailFromApiKey) {
|
|
287
|
+
throw new Error("Email not found");
|
|
288
|
+
}
|
|
289
|
+
const body = {
|
|
290
|
+
topic,
|
|
291
|
+
context,
|
|
292
|
+
scenes,
|
|
293
|
+
pipeline,
|
|
294
|
+
user_email: emailFromApiKey,
|
|
295
|
+
share_documents: shareDocuments,
|
|
296
|
+
logo_placement: logoPlacement,
|
|
297
|
+
audio_clip_url: audioClipUrl,
|
|
298
|
+
request_payload: requestPayload ? JSON.stringify(requestPayload) : null
|
|
299
|
+
};
|
|
300
|
+
const { data } = await this.http.post("/api/create-video-record", body);
|
|
301
|
+
return { videoId: data.video_id };
|
|
133
302
|
}
|
|
134
303
|
/**
|
|
135
304
|
* Edit specific frames of a video and regenerate the video.
|
|
@@ -176,11 +345,11 @@ var Golpo = class {
|
|
|
176
345
|
try {
|
|
177
346
|
const frameVersions = await this.getFrameVersions(videoId);
|
|
178
347
|
let frameAnimations = frameVersions.frame_animations ? { ...frameVersions.frame_animations } : {};
|
|
179
|
-
|
|
348
|
+
for (const frameId of frameIds) {
|
|
180
349
|
await this.setFrameVersion(videoId, frameId, editResult);
|
|
181
350
|
const updatedVersions = await this.getFrameVersions(videoId);
|
|
182
351
|
frameAnimations = updatedVersions.frame_animations || {};
|
|
183
|
-
}
|
|
352
|
+
}
|
|
184
353
|
const mp4Urls = Object.entries(frameAnimations).sort(([a], [b]) => parseInt(a) - parseInt(b)).map(([_, url]) => url);
|
|
185
354
|
if (mp4Urls.length === 0) {
|
|
186
355
|
throw new Error("No frame animations found to combine");
|
|
@@ -190,17 +359,11 @@ var Golpo = class {
|
|
|
190
359
|
pollIntervalMs,
|
|
191
360
|
videoUrl
|
|
192
361
|
};
|
|
193
|
-
const
|
|
194
|
-
return {
|
|
195
|
-
videoUrl: combinedUrl,
|
|
196
|
-
jobId
|
|
197
|
-
};
|
|
362
|
+
const combined = await this.combineVideos(combineOptions);
|
|
363
|
+
return { videoUrl: combined.url, jobId };
|
|
198
364
|
} catch (error) {
|
|
199
365
|
console.warn("Failed to auto-combine videos, returning edit result:", error);
|
|
200
|
-
return {
|
|
201
|
-
videoUrl: editResult,
|
|
202
|
-
jobId
|
|
203
|
-
};
|
|
366
|
+
return { videoUrl: editResult, jobId };
|
|
204
367
|
}
|
|
205
368
|
}
|
|
206
369
|
/**
|
|
@@ -354,19 +517,25 @@ var Golpo = class {
|
|
|
354
517
|
if (!combineJobId) {
|
|
355
518
|
throw new Error("No job ID received from combine-videos API");
|
|
356
519
|
}
|
|
357
|
-
|
|
520
|
+
const url = await this.pollEditStatus(combineJobId, pollIntervalMs);
|
|
521
|
+
return { url };
|
|
358
522
|
}
|
|
359
523
|
/* ------------------------------------------------------------ *
|
|
360
524
|
* INTERNAL HELPERS
|
|
361
525
|
* ------------------------------------------------------------ */
|
|
362
|
-
async pollUntilComplete(jobId, interval) {
|
|
526
|
+
async pollUntilComplete(jobId, interval, statusPath = "/status") {
|
|
363
527
|
while (true) {
|
|
528
|
+
let data;
|
|
364
529
|
try {
|
|
365
|
-
const
|
|
366
|
-
|
|
530
|
+
const res = await this.http.get(`${statusPath}/${jobId}`);
|
|
531
|
+
data = res.data;
|
|
367
532
|
} catch (error) {
|
|
368
533
|
console.warn(`Status check failed for job ${jobId}, retrying in ${interval}ms:`, error instanceof Error ? error.message : error);
|
|
369
534
|
}
|
|
535
|
+
if (data?.status === "completed") return data;
|
|
536
|
+
if (data?.status === "failed") {
|
|
537
|
+
throw new Error(`Job ${jobId} failed: ${data.error || data.message || "unknown error"}`);
|
|
538
|
+
}
|
|
370
539
|
await new Promise((r) => setTimeout(r, interval));
|
|
371
540
|
}
|
|
372
541
|
}
|
|
@@ -416,7 +585,50 @@ var Golpo = class {
|
|
|
416
585
|
attempts++;
|
|
417
586
|
}
|
|
418
587
|
}
|
|
419
|
-
|
|
588
|
+
/**
|
|
589
|
+
* Upload a file using /upload-url endpoint and return the final URL.
|
|
590
|
+
* Replicates the _presign_and_upload_one logic from the backend.
|
|
591
|
+
*/
|
|
592
|
+
async uploadFileAndGetUrl(filePath) {
|
|
593
|
+
const absPath = resolve(filePath.trim().replace(/^<|>$/g, ""));
|
|
594
|
+
try {
|
|
595
|
+
await fs.access(absPath);
|
|
596
|
+
} catch (error) {
|
|
597
|
+
throw new Error(`File not found: ${absPath}. Original path: ${filePath}`);
|
|
598
|
+
}
|
|
599
|
+
const fileName = basename(absPath);
|
|
600
|
+
const fileData = await fs.readFile(absPath);
|
|
601
|
+
const mimeType = mimeLookup(absPath) || "application/octet-stream";
|
|
602
|
+
const { data: presignInfo } = await this.http.post(
|
|
603
|
+
"/upload-url",
|
|
604
|
+
{ filename: fileName },
|
|
605
|
+
{ headers: { "Content-Type": "application/x-www-form-urlencoded" } }
|
|
606
|
+
);
|
|
607
|
+
let finalUrl;
|
|
608
|
+
if (presignInfo.url && presignInfo.fields) {
|
|
609
|
+
const uploadFormData = new FormData();
|
|
610
|
+
Object.entries(presignInfo.fields).forEach(([key, value]) => {
|
|
611
|
+
uploadFormData.append(key, value);
|
|
612
|
+
});
|
|
613
|
+
uploadFormData.append("file", fileData, { filename: fileName });
|
|
614
|
+
await axios.post(presignInfo.url, uploadFormData, {
|
|
615
|
+
headers: uploadFormData.getHeaders(),
|
|
616
|
+
timeout: 3e4
|
|
617
|
+
});
|
|
618
|
+
finalUrl = presignInfo.final_url || presignInfo.url.split("?")[0];
|
|
619
|
+
} else if (presignInfo.upload_url || presignInfo.url) {
|
|
620
|
+
const uploadUrl = presignInfo.upload_url || presignInfo.url;
|
|
621
|
+
await axios.put(uploadUrl, fileData, {
|
|
622
|
+
headers: { "Content-Type": mimeType },
|
|
623
|
+
timeout: 3e4
|
|
624
|
+
});
|
|
625
|
+
finalUrl = presignInfo.final_url || uploadUrl.split("?")[0];
|
|
626
|
+
} else {
|
|
627
|
+
throw new Error(`Unrecognized presign response: ${JSON.stringify(presignInfo)}`);
|
|
628
|
+
}
|
|
629
|
+
return finalUrl;
|
|
630
|
+
}
|
|
631
|
+
async createFormData(fields, uploads, concurrency, logo, audioClip, userImages, userVideos, inputImages) {
|
|
420
632
|
const formData = new FormData();
|
|
421
633
|
fields.forEach(([key, value]) => {
|
|
422
634
|
if (key !== "logo_path") {
|
|
@@ -425,16 +637,147 @@ var Golpo = class {
|
|
|
425
637
|
});
|
|
426
638
|
if (logo) {
|
|
427
639
|
const logoPath = logo.trim().replace(/^<|>$/g, "");
|
|
640
|
+
let logoUrl;
|
|
428
641
|
if (URL_RE.test(logoPath)) {
|
|
429
|
-
|
|
642
|
+
logoUrl = logoPath;
|
|
643
|
+
} else {
|
|
644
|
+
logoUrl = await this.uploadFileAndGetUrl(logoPath);
|
|
645
|
+
}
|
|
646
|
+
formData.append("logo", logoUrl);
|
|
647
|
+
}
|
|
648
|
+
if (audioClip) {
|
|
649
|
+
const audioList = Array.isArray(audioClip) ? audioClip : [audioClip];
|
|
650
|
+
const audioLocalFiles = [];
|
|
651
|
+
const audioUrls = [];
|
|
652
|
+
audioList.forEach((item) => {
|
|
653
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
654
|
+
if (URL_RE.test(path)) {
|
|
655
|
+
audioUrls.push(path);
|
|
656
|
+
} else {
|
|
657
|
+
audioLocalFiles.push(path);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
if (audioLocalFiles.length > 0) {
|
|
661
|
+
const limit = pLimit(concurrency);
|
|
662
|
+
const uploadedUrls = await Promise.all(
|
|
663
|
+
audioLocalFiles.map(
|
|
664
|
+
(filePath) => limit(() => this.uploadFileAndGetUrl(filePath))
|
|
665
|
+
)
|
|
666
|
+
);
|
|
667
|
+
audioUrls.push(...uploadedUrls);
|
|
668
|
+
}
|
|
669
|
+
if (audioUrls.length > 0) {
|
|
670
|
+
formData.append("audio_clip", audioUrls[0]);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (userImages) {
|
|
674
|
+
const imagesList = Array.isArray(userImages) ? userImages : [userImages];
|
|
675
|
+
const imageLocalFiles = [];
|
|
676
|
+
const imageUrls = [];
|
|
677
|
+
console.log("[SDK] Processing userImages:", imagesList);
|
|
678
|
+
imagesList.forEach((item) => {
|
|
679
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
680
|
+
if (URL_RE.test(path)) {
|
|
681
|
+
console.log("[SDK] userImages item is URL:", path);
|
|
682
|
+
imageUrls.push(path);
|
|
683
|
+
} else {
|
|
684
|
+
console.log("[SDK] userImages item is local file:", path);
|
|
685
|
+
imageLocalFiles.push(path);
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
if (imageLocalFiles.length > 0) {
|
|
689
|
+
console.log("[SDK] Uploading", imageLocalFiles.length, "image file(s)");
|
|
690
|
+
const limit = pLimit(concurrency);
|
|
691
|
+
try {
|
|
692
|
+
const uploadedUrls = await Promise.all(
|
|
693
|
+
imageLocalFiles.map(
|
|
694
|
+
(filePath) => limit(async () => {
|
|
695
|
+
try {
|
|
696
|
+
console.log("[SDK] Uploading image file:", filePath);
|
|
697
|
+
const url = await this.uploadFileAndGetUrl(filePath);
|
|
698
|
+
console.log("[SDK] Image uploaded, got URL:", url);
|
|
699
|
+
return url;
|
|
700
|
+
} catch (error) {
|
|
701
|
+
console.error(`[SDK] Failed to upload image file ${filePath}:`, error);
|
|
702
|
+
throw error;
|
|
703
|
+
}
|
|
704
|
+
})
|
|
705
|
+
)
|
|
706
|
+
);
|
|
707
|
+
imageUrls.push(...uploadedUrls);
|
|
708
|
+
console.log("[SDK] All images uploaded, total URLs:", imageUrls.length);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
console.error("[SDK] Error uploading image files:", error);
|
|
711
|
+
throw error;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
if (imageUrls.length > 0) {
|
|
715
|
+
const jsonArray = JSON.stringify(imageUrls);
|
|
716
|
+
console.log("[SDK] Sending user_images as JSON:", jsonArray);
|
|
717
|
+
formData.append("user_images", jsonArray);
|
|
718
|
+
} else {
|
|
719
|
+
console.log("[SDK] No image URLs to send");
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
if (userVideos) {
|
|
723
|
+
const videosList = Array.isArray(userVideos) ? userVideos : [userVideos];
|
|
724
|
+
const videoLocalFiles = [];
|
|
725
|
+
const videoUrls = [];
|
|
726
|
+
videosList.forEach((item) => {
|
|
727
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
728
|
+
if (URL_RE.test(path)) {
|
|
729
|
+
videoUrls.push(path);
|
|
730
|
+
} else {
|
|
731
|
+
videoLocalFiles.push(path);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
if (videoLocalFiles.length > 0) {
|
|
735
|
+
const limit = pLimit(concurrency);
|
|
736
|
+
try {
|
|
737
|
+
const uploadedUrls = await Promise.all(
|
|
738
|
+
videoLocalFiles.map(
|
|
739
|
+
(filePath) => limit(async () => {
|
|
740
|
+
try {
|
|
741
|
+
return await this.uploadFileAndGetUrl(filePath);
|
|
742
|
+
} catch (error) {
|
|
743
|
+
console.error(`Failed to upload video file ${filePath}:`, error);
|
|
744
|
+
throw error;
|
|
745
|
+
}
|
|
746
|
+
})
|
|
747
|
+
)
|
|
748
|
+
);
|
|
749
|
+
videoUrls.push(...uploadedUrls);
|
|
750
|
+
} catch (error) {
|
|
751
|
+
console.error("Error uploading video files:", error);
|
|
752
|
+
throw error;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
if (videoUrls.length > 0) {
|
|
756
|
+
formData.append("user_videos", JSON.stringify(videoUrls));
|
|
430
757
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
758
|
+
}
|
|
759
|
+
if (inputImages) {
|
|
760
|
+
const imagesList = Array.isArray(inputImages) ? inputImages : [inputImages];
|
|
761
|
+
const localFiles = [];
|
|
762
|
+
const imageUrls = [];
|
|
763
|
+
imagesList.forEach((item) => {
|
|
764
|
+
const path = String(item).trim().replace(/^<|>$/g, "");
|
|
765
|
+
if (URL_RE.test(path)) {
|
|
766
|
+
imageUrls.push(path);
|
|
767
|
+
} else {
|
|
768
|
+
localFiles.push(path);
|
|
769
|
+
}
|
|
437
770
|
});
|
|
771
|
+
if (localFiles.length > 0) {
|
|
772
|
+
const limit = pLimit(concurrency);
|
|
773
|
+
const uploadedUrls = await Promise.all(
|
|
774
|
+
localFiles.map((filePath) => limit(() => this.uploadFileAndGetUrl(filePath)))
|
|
775
|
+
);
|
|
776
|
+
imageUrls.push(...uploadedUrls);
|
|
777
|
+
}
|
|
778
|
+
if (imageUrls.length > 0) {
|
|
779
|
+
formData.append("input_images", JSON.stringify(imageUrls));
|
|
780
|
+
}
|
|
438
781
|
}
|
|
439
782
|
if (uploads) {
|
|
440
783
|
const list = typeof uploads === "string" ? [uploads] : [...uploads];
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golpoai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"exports":
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"require": "./dist/index.cjs"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"module": "./dist/index.js",
|
|
6
14
|
"types": "./dist/index.d.ts",
|
|
7
15
|
"files": [
|
|
8
16
|
"dist/**/*"
|