@runpod/ai-sdk-provider 1.1.0 → 1.3.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/CHANGELOG.md +16 -0
- package/README.md +236 -16
- package/dist/index.d.mts +113 -3
- package/dist/index.d.ts +113 -3
- package/dist/index.js +649 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +658 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
27
27
|
|
|
28
28
|
// src/runpod-provider.ts
|
|
29
29
|
var import_openai_compatible = require("@ai-sdk/openai-compatible");
|
|
30
|
-
var
|
|
30
|
+
var import_provider_utils6 = require("@ai-sdk/provider-utils");
|
|
31
31
|
|
|
32
32
|
// src/runpod-image-model.ts
|
|
33
33
|
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
@@ -41,28 +41,37 @@ var runpodImageErrorSchema = import_zod.z.object({
|
|
|
41
41
|
error: import_zod.z.string().optional(),
|
|
42
42
|
message: import_zod.z.string().optional()
|
|
43
43
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (nestedError.message && typeof nestedError.message === "string") {
|
|
57
|
-
return nestedError.message;
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
44
|
+
function extractErrorMessage(data) {
|
|
45
|
+
if (data.message) {
|
|
46
|
+
return data.message;
|
|
47
|
+
}
|
|
48
|
+
if (data.error) {
|
|
49
|
+
const lastBraceIndex = data.error.lastIndexOf("{");
|
|
50
|
+
if (lastBraceIndex !== -1) {
|
|
51
|
+
try {
|
|
52
|
+
const jsonStr = data.error.substring(lastBraceIndex);
|
|
53
|
+
const nestedError = JSON.parse(jsonStr);
|
|
54
|
+
if (nestedError.message && typeof nestedError.message === "string") {
|
|
55
|
+
return nestedError.message;
|
|
60
56
|
}
|
|
57
|
+
} catch {
|
|
61
58
|
}
|
|
62
|
-
return data.error;
|
|
63
59
|
}
|
|
64
|
-
return
|
|
60
|
+
return data.error;
|
|
65
61
|
}
|
|
62
|
+
return "Unknown Runpod error";
|
|
63
|
+
}
|
|
64
|
+
var runpodImageFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
|
|
65
|
+
errorSchema: runpodImageErrorSchema,
|
|
66
|
+
errorToMessage: extractErrorMessage
|
|
67
|
+
});
|
|
68
|
+
var runpodTranscriptionFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
|
|
69
|
+
errorSchema: runpodImageErrorSchema,
|
|
70
|
+
errorToMessage: extractErrorMessage
|
|
71
|
+
});
|
|
72
|
+
var runpodVideoFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
|
|
73
|
+
errorSchema: runpodImageErrorSchema,
|
|
74
|
+
errorToMessage: extractErrorMessage
|
|
66
75
|
});
|
|
67
76
|
|
|
68
77
|
// src/runpod-image-model.ts
|
|
@@ -86,6 +95,8 @@ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
|
|
|
86
95
|
"512*512",
|
|
87
96
|
"768*768",
|
|
88
97
|
"1024*1024",
|
|
98
|
+
"1280*1280",
|
|
99
|
+
// wan-2.6 max
|
|
89
100
|
"1536*1536",
|
|
90
101
|
"2048*2048",
|
|
91
102
|
"4096*4096",
|
|
@@ -94,6 +105,100 @@ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
|
|
|
94
105
|
"1024*768",
|
|
95
106
|
"768*1024"
|
|
96
107
|
]);
|
|
108
|
+
var Z_IMAGE_TURBO_SUPPORTED_SIZES = /* @__PURE__ */ new Set([
|
|
109
|
+
"1328*1328",
|
|
110
|
+
// 1:1
|
|
111
|
+
"1472*1140",
|
|
112
|
+
// 4:3
|
|
113
|
+
"1140*1472",
|
|
114
|
+
// 3:4
|
|
115
|
+
"512*512",
|
|
116
|
+
"768*768",
|
|
117
|
+
"1024*1024",
|
|
118
|
+
"1280*1280",
|
|
119
|
+
"1536*1536",
|
|
120
|
+
"512*768",
|
|
121
|
+
"768*512",
|
|
122
|
+
"1024*768",
|
|
123
|
+
"768*1024",
|
|
124
|
+
"768*432",
|
|
125
|
+
"1024*576",
|
|
126
|
+
"1280*720",
|
|
127
|
+
"1536*864",
|
|
128
|
+
"432*768",
|
|
129
|
+
"576*1024",
|
|
130
|
+
"720*1280",
|
|
131
|
+
"864*1536"
|
|
132
|
+
]);
|
|
133
|
+
var Z_IMAGE_TURBO_ASPECT_RATIOS = {
|
|
134
|
+
"1:1": "1328*1328",
|
|
135
|
+
"4:3": "1472*1140",
|
|
136
|
+
"3:4": "1140*1472",
|
|
137
|
+
"3:2": "768*512",
|
|
138
|
+
"2:3": "512*768",
|
|
139
|
+
"16:9": "1280*720",
|
|
140
|
+
"9:16": "720*1280"
|
|
141
|
+
};
|
|
142
|
+
var MODEL_SUPPORTED_SIZES = {
|
|
143
|
+
"tongyi-mai/z-image-turbo": Z_IMAGE_TURBO_SUPPORTED_SIZES,
|
|
144
|
+
"z-image-turbo": Z_IMAGE_TURBO_SUPPORTED_SIZES
|
|
145
|
+
// alias, not advertised
|
|
146
|
+
};
|
|
147
|
+
var MODEL_SUPPORTED_ASPECT_RATIOS = {
|
|
148
|
+
"tongyi-mai/z-image-turbo": Z_IMAGE_TURBO_ASPECT_RATIOS,
|
|
149
|
+
"z-image-turbo": Z_IMAGE_TURBO_ASPECT_RATIOS
|
|
150
|
+
// alias, not advertised
|
|
151
|
+
};
|
|
152
|
+
var WAN_ASPECT_RATIOS = {
|
|
153
|
+
"1:1": "1280*1280",
|
|
154
|
+
// 1,638,400 pixels
|
|
155
|
+
"2:3": "800*1200",
|
|
156
|
+
// 960,000 pixels
|
|
157
|
+
"3:2": "1200*800",
|
|
158
|
+
// 960,000 pixels
|
|
159
|
+
"3:4": "960*1280",
|
|
160
|
+
// 1,228,800 pixels
|
|
161
|
+
"4:3": "1280*960",
|
|
162
|
+
// 1,228,800 pixels
|
|
163
|
+
"9:16": "720*1280",
|
|
164
|
+
// 921,600 pixels
|
|
165
|
+
"16:9": "1280*720",
|
|
166
|
+
// 921,600 pixels
|
|
167
|
+
"21:9": "1344*576",
|
|
168
|
+
// 774,144 pixels
|
|
169
|
+
"9:21": "576*1344"
|
|
170
|
+
// 774,144 pixels
|
|
171
|
+
};
|
|
172
|
+
var WAN_MIN_PIXELS = 768 * 768;
|
|
173
|
+
var WAN_MAX_PIXELS = 1280 * 1280;
|
|
174
|
+
var WAN_MIN_ASPECT_RATIO = 1 / 4;
|
|
175
|
+
var WAN_MAX_ASPECT_RATIO = 4 / 1;
|
|
176
|
+
function validateWanSize(size) {
|
|
177
|
+
const [widthStr, heightStr] = size.split("*");
|
|
178
|
+
const width = parseInt(widthStr, 10);
|
|
179
|
+
const height = parseInt(heightStr, 10);
|
|
180
|
+
if (isNaN(width) || isNaN(height)) {
|
|
181
|
+
throw new import_provider.InvalidArgumentError({
|
|
182
|
+
argument: "size",
|
|
183
|
+
message: `Invalid size format: ${size}. Expected format: WIDTHxHEIGHT or WIDTH*HEIGHT`
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
const totalPixels = width * height;
|
|
187
|
+
const aspectRatio = width / height;
|
|
188
|
+
if (totalPixels < WAN_MIN_PIXELS || totalPixels > WAN_MAX_PIXELS) {
|
|
189
|
+
throw new import_provider.InvalidArgumentError({
|
|
190
|
+
argument: "size",
|
|
191
|
+
message: `Size ${size} has ${totalPixels} pixels, which is outside the valid range for WAN 2.6 (${WAN_MIN_PIXELS} to ${WAN_MAX_PIXELS} pixels). Try 1280x1280 or 1024x1024.`
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
if (aspectRatio < WAN_MIN_ASPECT_RATIO || aspectRatio > WAN_MAX_ASPECT_RATIO) {
|
|
195
|
+
throw new import_provider.InvalidArgumentError({
|
|
196
|
+
argument: "size",
|
|
197
|
+
message: `Size ${size} has aspect ratio ${aspectRatio.toFixed(2)}, which is outside the valid range for WAN 2.6 (1:4 to 4:1).`
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
97
202
|
var RunpodImageModel = class {
|
|
98
203
|
constructor(modelId, config) {
|
|
99
204
|
this.modelId = modelId;
|
|
@@ -127,28 +232,49 @@ var RunpodImageModel = class {
|
|
|
127
232
|
}
|
|
128
233
|
const isPrunaModel = this.modelId.includes("pruna") || this.modelId.includes("p-image");
|
|
129
234
|
const isNanoBananaProModel = this.modelId.includes("nano-banana-pro");
|
|
235
|
+
const isWanModel = this.modelId.includes("wan-2");
|
|
130
236
|
let runpodSize;
|
|
131
237
|
if (isPrunaModel || isNanoBananaProModel) {
|
|
132
238
|
runpodSize = aspectRatio || "1:1";
|
|
239
|
+
} else if (isWanModel) {
|
|
240
|
+
if (size) {
|
|
241
|
+
const runpodSizeCandidate = size.replace("x", "*");
|
|
242
|
+
validateWanSize(runpodSizeCandidate);
|
|
243
|
+
runpodSize = runpodSizeCandidate;
|
|
244
|
+
} else if (aspectRatio) {
|
|
245
|
+
if (!WAN_ASPECT_RATIOS[aspectRatio]) {
|
|
246
|
+
throw new import_provider.InvalidArgumentError({
|
|
247
|
+
argument: "aspectRatio",
|
|
248
|
+
message: `Aspect ratio ${aspectRatio} is not supported by WAN 2.6. Supported aspect ratios: ${Object.keys(WAN_ASPECT_RATIOS).join(", ")}`
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
runpodSize = WAN_ASPECT_RATIOS[aspectRatio];
|
|
252
|
+
} else {
|
|
253
|
+
runpodSize = "1280*1280";
|
|
254
|
+
}
|
|
133
255
|
} else if (size) {
|
|
134
256
|
const runpodSizeCandidate = size.replace("x", "*");
|
|
135
|
-
|
|
257
|
+
const supportedSizes = MODEL_SUPPORTED_SIZES[this.modelId] ?? SUPPORTED_SIZES;
|
|
258
|
+
if (!supportedSizes.has(runpodSizeCandidate)) {
|
|
136
259
|
throw new import_provider.InvalidArgumentError({
|
|
137
260
|
argument: "size",
|
|
138
261
|
message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(
|
|
139
|
-
|
|
262
|
+
supportedSizes
|
|
140
263
|
).map((s) => s.replace("*", "x")).join(", ")}`
|
|
141
264
|
});
|
|
142
265
|
}
|
|
143
266
|
runpodSize = runpodSizeCandidate;
|
|
144
267
|
} else if (aspectRatio) {
|
|
145
|
-
|
|
268
|
+
const supportedAspectRatios = MODEL_SUPPORTED_ASPECT_RATIOS[this.modelId] ?? SUPPORTED_ASPECT_RATIOS;
|
|
269
|
+
if (!supportedAspectRatios[aspectRatio]) {
|
|
146
270
|
throw new import_provider.InvalidArgumentError({
|
|
147
271
|
argument: "aspectRatio",
|
|
148
|
-
message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(
|
|
272
|
+
message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(
|
|
273
|
+
supportedAspectRatios
|
|
274
|
+
).join(", ")}`
|
|
149
275
|
});
|
|
150
276
|
}
|
|
151
|
-
runpodSize =
|
|
277
|
+
runpodSize = supportedAspectRatios[aspectRatio];
|
|
152
278
|
} else {
|
|
153
279
|
runpodSize = "1328*1328";
|
|
154
280
|
}
|
|
@@ -243,6 +369,10 @@ var RunpodImageModel = class {
|
|
|
243
369
|
}
|
|
244
370
|
}
|
|
245
371
|
};
|
|
372
|
+
} else if (typedResponse.status === "FAILED") {
|
|
373
|
+
throw new Error(
|
|
374
|
+
`Image generation failed: ${typedResponse.error || "Unknown error"}`
|
|
375
|
+
);
|
|
246
376
|
} else {
|
|
247
377
|
throw new Error(`Unexpected response status: ${typedResponse.status}`);
|
|
248
378
|
}
|
|
@@ -447,6 +577,25 @@ var RunpodImageModel = class {
|
|
|
447
577
|
}
|
|
448
578
|
return qwenEdit2511Payload;
|
|
449
579
|
}
|
|
580
|
+
const isZImageTurbo = this.modelId === "tongyi-mai/z-image-turbo" || this.modelId === "z-image-turbo";
|
|
581
|
+
if (isZImageTurbo) {
|
|
582
|
+
const zImageTurboPayload = {
|
|
583
|
+
prompt,
|
|
584
|
+
size: runpodSize,
|
|
585
|
+
seed: seed ?? -1,
|
|
586
|
+
output_format: runpodOptions?.output_format ?? "png",
|
|
587
|
+
enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
|
|
588
|
+
...runpodOptions
|
|
589
|
+
};
|
|
590
|
+
if (standardizedImages && standardizedImages.length > 0) {
|
|
591
|
+
if (standardizedImages.length === 1) {
|
|
592
|
+
zImageTurboPayload.image = standardizedImages[0];
|
|
593
|
+
} else {
|
|
594
|
+
zImageTurboPayload.images = standardizedImages;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return zImageTurboPayload;
|
|
598
|
+
}
|
|
450
599
|
const isWanModel = this.modelId.includes("wan-2");
|
|
451
600
|
if (isWanModel) {
|
|
452
601
|
return {
|
|
@@ -486,8 +635,10 @@ var runpodImageResponseSchema = import_zod2.z.object({
|
|
|
486
635
|
// URL to the generated image (Qwen format)
|
|
487
636
|
image_url: import_zod2.z.string().optional()
|
|
488
637
|
// URL to the generated image (Flux format)
|
|
489
|
-
}).optional()
|
|
638
|
+
}).optional(),
|
|
490
639
|
// Optional for IN_QUEUE/IN_PROGRESS responses
|
|
640
|
+
error: import_zod2.z.string().optional()
|
|
641
|
+
// Error message if FAILED
|
|
491
642
|
});
|
|
492
643
|
var runpodImageStatusSchema = import_zod2.z.object({
|
|
493
644
|
id: import_zod2.z.string(),
|
|
@@ -608,6 +759,11 @@ var RunpodSpeechModel = class {
|
|
|
608
759
|
const message = parsed && typeof parsed.error === "string" && parsed.error || rawBodyText || `HTTP ${response.status}`;
|
|
609
760
|
throw new Error(`Runpod speech request failed: ${message}`);
|
|
610
761
|
}
|
|
762
|
+
if (parsed?.status === "FAILED") {
|
|
763
|
+
throw new Error(
|
|
764
|
+
`Speech generation failed: ${parsed.error || "Unknown error"}`
|
|
765
|
+
);
|
|
766
|
+
}
|
|
611
767
|
const output = parsed?.output ?? parsed;
|
|
612
768
|
const audioUrl = output?.audio_url;
|
|
613
769
|
if (typeof audioUrl !== "string" || audioUrl.length === 0) {
|
|
@@ -643,6 +799,420 @@ var RunpodSpeechModel = class {
|
|
|
643
799
|
}
|
|
644
800
|
};
|
|
645
801
|
|
|
802
|
+
// src/runpod-transcription-model.ts
|
|
803
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
804
|
+
var import_zod3 = require("zod");
|
|
805
|
+
function isRecord2(value) {
|
|
806
|
+
return typeof value === "object" && value !== null;
|
|
807
|
+
}
|
|
808
|
+
var runpodJobResponseSchema = import_zod3.z.object({
|
|
809
|
+
id: import_zod3.z.string(),
|
|
810
|
+
status: import_zod3.z.string().optional()
|
|
811
|
+
});
|
|
812
|
+
var runpodStatusResponseSchema = import_zod3.z.object({
|
|
813
|
+
id: import_zod3.z.string().optional(),
|
|
814
|
+
status: import_zod3.z.string(),
|
|
815
|
+
output: import_zod3.z.object({
|
|
816
|
+
text: import_zod3.z.string().optional(),
|
|
817
|
+
result: import_zod3.z.string().optional(),
|
|
818
|
+
// Some workers use 'result' instead of 'text'
|
|
819
|
+
segments: import_zod3.z.array(
|
|
820
|
+
import_zod3.z.object({
|
|
821
|
+
text: import_zod3.z.string().optional(),
|
|
822
|
+
start: import_zod3.z.number().optional(),
|
|
823
|
+
end: import_zod3.z.number().optional()
|
|
824
|
+
})
|
|
825
|
+
).optional(),
|
|
826
|
+
language: import_zod3.z.string().optional(),
|
|
827
|
+
duration: import_zod3.z.number().optional(),
|
|
828
|
+
cost: import_zod3.z.number().optional()
|
|
829
|
+
}).optional(),
|
|
830
|
+
error: import_zod3.z.string().optional()
|
|
831
|
+
});
|
|
832
|
+
var RunpodTranscriptionModel = class {
|
|
833
|
+
constructor(modelId, config) {
|
|
834
|
+
this.modelId = modelId;
|
|
835
|
+
this.config = config;
|
|
836
|
+
this.specificationVersion = "v3";
|
|
837
|
+
}
|
|
838
|
+
get provider() {
|
|
839
|
+
return this.config.provider;
|
|
840
|
+
}
|
|
841
|
+
getRunpodRunUrl() {
|
|
842
|
+
const baseURL = (0, import_provider_utils4.withoutTrailingSlash)(this.config.baseURL) ?? this.config.baseURL;
|
|
843
|
+
if (baseURL.endsWith("/run") || baseURL.endsWith("/runsync")) {
|
|
844
|
+
return baseURL;
|
|
845
|
+
}
|
|
846
|
+
return `${baseURL}/run`;
|
|
847
|
+
}
|
|
848
|
+
async doGenerate(options) {
|
|
849
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
850
|
+
const warnings = [];
|
|
851
|
+
const { audio, providerOptions, abortSignal, headers } = options;
|
|
852
|
+
const runpodOptions = this.extractRunpodOptions(providerOptions);
|
|
853
|
+
const input = {};
|
|
854
|
+
if (runpodOptions.audio && typeof runpodOptions.audio === "string") {
|
|
855
|
+
input.audio = runpodOptions.audio;
|
|
856
|
+
} else {
|
|
857
|
+
const base64Audio = this.convertAudioToBase64(audio);
|
|
858
|
+
input.audio_base64 = base64Audio;
|
|
859
|
+
}
|
|
860
|
+
if (runpodOptions.prompt || runpodOptions.initial_prompt) {
|
|
861
|
+
input.initial_prompt = runpodOptions.prompt ?? runpodOptions.initial_prompt;
|
|
862
|
+
}
|
|
863
|
+
if (runpodOptions.language) {
|
|
864
|
+
input.language = runpodOptions.language;
|
|
865
|
+
}
|
|
866
|
+
if (runpodOptions.word_timestamps !== void 0) {
|
|
867
|
+
input.word_timestamps = runpodOptions.word_timestamps;
|
|
868
|
+
}
|
|
869
|
+
if (runpodOptions.model) {
|
|
870
|
+
input.model = runpodOptions.model;
|
|
871
|
+
}
|
|
872
|
+
if (runpodOptions.transcription) {
|
|
873
|
+
input.transcription = runpodOptions.transcription;
|
|
874
|
+
}
|
|
875
|
+
if (runpodOptions.translate !== void 0) {
|
|
876
|
+
input.translate = runpodOptions.translate;
|
|
877
|
+
}
|
|
878
|
+
if (runpodOptions.enable_vad !== void 0) {
|
|
879
|
+
input.enable_vad = runpodOptions.enable_vad;
|
|
880
|
+
}
|
|
881
|
+
const requestBody = { input };
|
|
882
|
+
const url = this.getRunpodRunUrl();
|
|
883
|
+
const effectiveBaseURL = (0, import_provider_utils4.withoutTrailingSlash)(this.config.baseURL) ?? this.config.baseURL;
|
|
884
|
+
const { value: response, responseHeaders } = await (0, import_provider_utils4.postJsonToApi)({
|
|
885
|
+
url,
|
|
886
|
+
headers: {
|
|
887
|
+
...this.config.headers(),
|
|
888
|
+
...headers
|
|
889
|
+
},
|
|
890
|
+
body: requestBody,
|
|
891
|
+
failedResponseHandler: runpodTranscriptionFailedResponseHandler,
|
|
892
|
+
successfulResponseHandler: (0, import_provider_utils4.createJsonResponseHandler)(
|
|
893
|
+
runpodJobResponseSchema
|
|
894
|
+
),
|
|
895
|
+
abortSignal,
|
|
896
|
+
fetch: this.config.fetch
|
|
897
|
+
});
|
|
898
|
+
const typedResponse = response;
|
|
899
|
+
const jobId = typedResponse.id;
|
|
900
|
+
if (!jobId) {
|
|
901
|
+
throw new Error(
|
|
902
|
+
"Runpod transcription response did not include a job id."
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
const pollOptions = {
|
|
906
|
+
maxAttempts: runpodOptions.maxPollAttempts ?? 120,
|
|
907
|
+
pollIntervalMillis: runpodOptions.pollIntervalMillis ?? 2e3
|
|
908
|
+
};
|
|
909
|
+
const result = await this.pollForCompletion(
|
|
910
|
+
jobId,
|
|
911
|
+
abortSignal,
|
|
912
|
+
pollOptions,
|
|
913
|
+
effectiveBaseURL
|
|
914
|
+
);
|
|
915
|
+
const output = result.output;
|
|
916
|
+
const text = output?.text ?? output?.result ?? "";
|
|
917
|
+
const segments = this.parseSegments(output);
|
|
918
|
+
const language = output?.language;
|
|
919
|
+
const durationInSeconds = output?.duration;
|
|
920
|
+
const providerMetadata = {
|
|
921
|
+
runpod: {
|
|
922
|
+
jobId
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
return {
|
|
926
|
+
text,
|
|
927
|
+
segments,
|
|
928
|
+
language,
|
|
929
|
+
durationInSeconds,
|
|
930
|
+
warnings,
|
|
931
|
+
request: {
|
|
932
|
+
body: JSON.stringify(requestBody)
|
|
933
|
+
},
|
|
934
|
+
response: {
|
|
935
|
+
timestamp: currentDate,
|
|
936
|
+
modelId: this.modelId,
|
|
937
|
+
headers: responseHeaders,
|
|
938
|
+
body: JSON.stringify(result)
|
|
939
|
+
},
|
|
940
|
+
providerMetadata
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
convertAudioToBase64(audio) {
|
|
944
|
+
if (typeof audio === "string") {
|
|
945
|
+
return audio;
|
|
946
|
+
}
|
|
947
|
+
return this.uint8ArrayToBase64(audio);
|
|
948
|
+
}
|
|
949
|
+
uint8ArrayToBase64(data) {
|
|
950
|
+
if (typeof Buffer !== "undefined") {
|
|
951
|
+
return Buffer.from(data).toString("base64");
|
|
952
|
+
}
|
|
953
|
+
let binary = "";
|
|
954
|
+
for (let i = 0; i < data.length; i++) {
|
|
955
|
+
binary += String.fromCharCode(data[i]);
|
|
956
|
+
}
|
|
957
|
+
return btoa(binary);
|
|
958
|
+
}
|
|
959
|
+
extractRunpodOptions(providerOptions) {
|
|
960
|
+
if (!providerOptions) return {};
|
|
961
|
+
const runpod2 = providerOptions.runpod;
|
|
962
|
+
if (isRecord2(runpod2)) {
|
|
963
|
+
return runpod2;
|
|
964
|
+
}
|
|
965
|
+
return {};
|
|
966
|
+
}
|
|
967
|
+
async pollForCompletion(jobId, abortSignal, pollOptions, effectiveBaseURL) {
|
|
968
|
+
const maxAttempts = pollOptions?.maxAttempts ?? 120;
|
|
969
|
+
const pollInterval = pollOptions?.pollIntervalMillis ?? 2e3;
|
|
970
|
+
const baseURL = effectiveBaseURL ?? this.config.baseURL;
|
|
971
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
972
|
+
if (abortSignal?.aborted) {
|
|
973
|
+
throw new Error("Transcription was aborted");
|
|
974
|
+
}
|
|
975
|
+
const { value: statusResponse } = await (0, import_provider_utils4.getFromApi)({
|
|
976
|
+
url: `${baseURL}/status/${jobId}`,
|
|
977
|
+
headers: this.config.headers(),
|
|
978
|
+
successfulResponseHandler: (0, import_provider_utils4.createJsonResponseHandler)(
|
|
979
|
+
runpodStatusResponseSchema
|
|
980
|
+
),
|
|
981
|
+
failedResponseHandler: runpodTranscriptionFailedResponseHandler,
|
|
982
|
+
abortSignal,
|
|
983
|
+
fetch: this.config.fetch
|
|
984
|
+
});
|
|
985
|
+
const typedStatusResponse = statusResponse;
|
|
986
|
+
if (typedStatusResponse.status === "COMPLETED") {
|
|
987
|
+
return typedStatusResponse;
|
|
988
|
+
}
|
|
989
|
+
if (typedStatusResponse.status === "FAILED") {
|
|
990
|
+
throw new Error(
|
|
991
|
+
`Transcription failed: ${typedStatusResponse.error || "Unknown error"}`
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
995
|
+
}
|
|
996
|
+
throw new Error(
|
|
997
|
+
`Transcription timed out after ${maxAttempts} attempts (${maxAttempts * pollInterval / 1e3}s)`
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
parseSegments(output) {
|
|
1001
|
+
if (!output?.segments || !Array.isArray(output.segments)) {
|
|
1002
|
+
return [];
|
|
1003
|
+
}
|
|
1004
|
+
return output.segments.map((segment) => ({
|
|
1005
|
+
text: segment.text ?? "",
|
|
1006
|
+
startSecond: segment.start ?? 0,
|
|
1007
|
+
endSecond: segment.end ?? 0
|
|
1008
|
+
}));
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
// src/runpod-video-model.ts
|
|
1013
|
+
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
1014
|
+
var import_zod4 = require("zod");
|
|
1015
|
+
function isRecord3(value) {
|
|
1016
|
+
return typeof value === "object" && value !== null;
|
|
1017
|
+
}
|
|
1018
|
+
var runpodVideoJobResponseSchema = import_zod4.z.object({
|
|
1019
|
+
id: import_zod4.z.string(),
|
|
1020
|
+
status: import_zod4.z.string().optional()
|
|
1021
|
+
});
|
|
1022
|
+
var runpodVideoStatusSchema = import_zod4.z.object({
|
|
1023
|
+
id: import_zod4.z.string().optional(),
|
|
1024
|
+
status: import_zod4.z.string(),
|
|
1025
|
+
output: import_zod4.z.unknown().optional(),
|
|
1026
|
+
error: import_zod4.z.string().optional()
|
|
1027
|
+
});
|
|
1028
|
+
var RunpodVideoModel = class {
|
|
1029
|
+
constructor(modelId, config) {
|
|
1030
|
+
this.modelId = modelId;
|
|
1031
|
+
this.config = config;
|
|
1032
|
+
this.specificationVersion = "v3";
|
|
1033
|
+
this.maxVideosPerCall = 1;
|
|
1034
|
+
}
|
|
1035
|
+
get provider() {
|
|
1036
|
+
return this.config.provider;
|
|
1037
|
+
}
|
|
1038
|
+
getRunpodRunUrl() {
|
|
1039
|
+
const baseURL = (0, import_provider_utils5.withoutTrailingSlash)(this.config.baseURL) ?? this.config.baseURL;
|
|
1040
|
+
if (baseURL.endsWith("/run") || baseURL.endsWith("/runsync")) {
|
|
1041
|
+
return baseURL;
|
|
1042
|
+
}
|
|
1043
|
+
return `${baseURL}/run`;
|
|
1044
|
+
}
|
|
1045
|
+
async doGenerate(options) {
|
|
1046
|
+
const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
|
|
1047
|
+
const warnings = [];
|
|
1048
|
+
if (options.n > 1) {
|
|
1049
|
+
warnings.push({
|
|
1050
|
+
type: "unsupported",
|
|
1051
|
+
feature: "n > 1",
|
|
1052
|
+
details: "Runpod video models only support generating 1 video per call. Only 1 video will be generated."
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
const { providerOptions, abortSignal, headers } = options;
|
|
1056
|
+
const runpodOptions = this.extractRunpodOptions(providerOptions);
|
|
1057
|
+
const input = this.buildInputPayload(options, runpodOptions);
|
|
1058
|
+
const requestBody = { input };
|
|
1059
|
+
const url = this.getRunpodRunUrl();
|
|
1060
|
+
const effectiveBaseURL = (0, import_provider_utils5.withoutTrailingSlash)(this.config.baseURL) ?? this.config.baseURL;
|
|
1061
|
+
const { value: response, responseHeaders } = await (0, import_provider_utils5.postJsonToApi)({
|
|
1062
|
+
url,
|
|
1063
|
+
headers: {
|
|
1064
|
+
...this.config.headers(),
|
|
1065
|
+
...headers
|
|
1066
|
+
},
|
|
1067
|
+
body: requestBody,
|
|
1068
|
+
failedResponseHandler: runpodVideoFailedResponseHandler,
|
|
1069
|
+
successfulResponseHandler: (0, import_provider_utils5.createJsonResponseHandler)(
|
|
1070
|
+
runpodVideoJobResponseSchema
|
|
1071
|
+
),
|
|
1072
|
+
abortSignal,
|
|
1073
|
+
fetch: this.config.fetch
|
|
1074
|
+
});
|
|
1075
|
+
const typedResponse = response;
|
|
1076
|
+
const jobId = typedResponse.id;
|
|
1077
|
+
if (!jobId) {
|
|
1078
|
+
throw new Error("Runpod video response did not include a job id.");
|
|
1079
|
+
}
|
|
1080
|
+
const pollOptions = {
|
|
1081
|
+
maxAttempts: runpodOptions.maxPollAttempts ?? 120,
|
|
1082
|
+
pollIntervalMillis: runpodOptions.pollIntervalMillis ?? 5e3
|
|
1083
|
+
};
|
|
1084
|
+
const result = await this.pollForCompletion(
|
|
1085
|
+
jobId,
|
|
1086
|
+
abortSignal,
|
|
1087
|
+
pollOptions,
|
|
1088
|
+
effectiveBaseURL
|
|
1089
|
+
);
|
|
1090
|
+
const videoUrl = this.extractVideoUrl(result.output);
|
|
1091
|
+
const providerMetadata = {
|
|
1092
|
+
runpod: {
|
|
1093
|
+
jobId
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
return {
|
|
1097
|
+
videos: [{ type: "url", url: videoUrl, mediaType: "video/mp4" }],
|
|
1098
|
+
warnings,
|
|
1099
|
+
response: {
|
|
1100
|
+
timestamp: currentDate,
|
|
1101
|
+
modelId: this.modelId,
|
|
1102
|
+
headers: responseHeaders
|
|
1103
|
+
},
|
|
1104
|
+
providerMetadata
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
buildInputPayload(options, runpodOptions) {
|
|
1108
|
+
const apiOptions = Object.fromEntries(
|
|
1109
|
+
Object.entries(runpodOptions).filter(
|
|
1110
|
+
([key]) => key !== "maxPollAttempts" && key !== "pollIntervalMillis"
|
|
1111
|
+
)
|
|
1112
|
+
);
|
|
1113
|
+
const input = {
|
|
1114
|
+
...apiOptions
|
|
1115
|
+
};
|
|
1116
|
+
if (options.prompt) {
|
|
1117
|
+
input.prompt = options.prompt;
|
|
1118
|
+
}
|
|
1119
|
+
if (options.duration !== void 0) {
|
|
1120
|
+
input.duration = options.duration;
|
|
1121
|
+
}
|
|
1122
|
+
if (options.fps !== void 0) {
|
|
1123
|
+
input.fps = options.fps;
|
|
1124
|
+
}
|
|
1125
|
+
if (options.seed !== void 0) {
|
|
1126
|
+
input.seed = options.seed;
|
|
1127
|
+
}
|
|
1128
|
+
if (options.resolution) {
|
|
1129
|
+
input.size = options.resolution.replace("x", "*");
|
|
1130
|
+
} else if (options.aspectRatio) {
|
|
1131
|
+
input.aspect_ratio = options.aspectRatio;
|
|
1132
|
+
}
|
|
1133
|
+
if (options.image) {
|
|
1134
|
+
input.image = this.convertFileToRunpodFormat(options.image);
|
|
1135
|
+
}
|
|
1136
|
+
return input;
|
|
1137
|
+
}
|
|
1138
|
+
convertFileToRunpodFormat(file) {
|
|
1139
|
+
if (file.type === "url") {
|
|
1140
|
+
return file.url;
|
|
1141
|
+
}
|
|
1142
|
+
const mediaType = file.mediaType;
|
|
1143
|
+
const data = file.data;
|
|
1144
|
+
if (typeof data === "string") {
|
|
1145
|
+
return `data:${mediaType};base64,${data}`;
|
|
1146
|
+
}
|
|
1147
|
+
const base64 = this.uint8ArrayToBase64(data);
|
|
1148
|
+
return `data:${mediaType};base64,${base64}`;
|
|
1149
|
+
}
|
|
1150
|
+
uint8ArrayToBase64(data) {
|
|
1151
|
+
if (typeof Buffer !== "undefined") {
|
|
1152
|
+
return Buffer.from(data).toString("base64");
|
|
1153
|
+
}
|
|
1154
|
+
let binary = "";
|
|
1155
|
+
for (let i = 0; i < data.length; i++) {
|
|
1156
|
+
binary += String.fromCharCode(data[i]);
|
|
1157
|
+
}
|
|
1158
|
+
return btoa(binary);
|
|
1159
|
+
}
|
|
1160
|
+
extractRunpodOptions(providerOptions) {
|
|
1161
|
+
if (!providerOptions) return {};
|
|
1162
|
+
const runpod2 = providerOptions.runpod;
|
|
1163
|
+
if (isRecord3(runpod2)) {
|
|
1164
|
+
return runpod2;
|
|
1165
|
+
}
|
|
1166
|
+
return {};
|
|
1167
|
+
}
|
|
1168
|
+
extractVideoUrl(output) {
|
|
1169
|
+
if (isRecord3(output)) {
|
|
1170
|
+
if (typeof output.video_url === "string") return output.video_url;
|
|
1171
|
+
if (typeof output.result === "string") return output.result;
|
|
1172
|
+
if (typeof output.url === "string") return output.url;
|
|
1173
|
+
}
|
|
1174
|
+
if (typeof output === "string") {
|
|
1175
|
+
return output;
|
|
1176
|
+
}
|
|
1177
|
+
throw new Error(
|
|
1178
|
+
`Runpod video generation completed but no video URL was found in the output: ${JSON.stringify(output)}`
|
|
1179
|
+
);
|
|
1180
|
+
}
|
|
1181
|
+
async pollForCompletion(jobId, abortSignal, pollOptions, effectiveBaseURL) {
|
|
1182
|
+
const maxAttempts = pollOptions?.maxAttempts ?? 120;
|
|
1183
|
+
const pollInterval = pollOptions?.pollIntervalMillis ?? 5e3;
|
|
1184
|
+
const baseURL = effectiveBaseURL ?? this.config.baseURL;
|
|
1185
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1186
|
+
if (abortSignal?.aborted) {
|
|
1187
|
+
throw new Error("Video generation was aborted");
|
|
1188
|
+
}
|
|
1189
|
+
const { value: statusResponse } = await (0, import_provider_utils5.getFromApi)({
|
|
1190
|
+
url: `${baseURL}/status/${jobId}`,
|
|
1191
|
+
headers: this.config.headers(),
|
|
1192
|
+
successfulResponseHandler: (0, import_provider_utils5.createJsonResponseHandler)(
|
|
1193
|
+
runpodVideoStatusSchema
|
|
1194
|
+
),
|
|
1195
|
+
failedResponseHandler: runpodVideoFailedResponseHandler,
|
|
1196
|
+
abortSignal,
|
|
1197
|
+
fetch: this.config.fetch
|
|
1198
|
+
});
|
|
1199
|
+
const typedStatusResponse = statusResponse;
|
|
1200
|
+
if (typedStatusResponse.status === "COMPLETED") {
|
|
1201
|
+
return typedStatusResponse;
|
|
1202
|
+
}
|
|
1203
|
+
if (typedStatusResponse.status === "FAILED") {
|
|
1204
|
+
throw new Error(
|
|
1205
|
+
`Video generation failed: ${typedStatusResponse.error || "Unknown error"}`
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
1209
|
+
}
|
|
1210
|
+
throw new Error(
|
|
1211
|
+
`Video generation timed out after ${maxAttempts} attempts (${maxAttempts * pollInterval / 1e3}s)`
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
|
|
646
1216
|
// src/runpod-provider.ts
|
|
647
1217
|
var MODEL_ID_TO_ENDPOINT_URL = {
|
|
648
1218
|
"qwen/qwen3-32b-awq": "https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1",
|
|
@@ -666,6 +1236,10 @@ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
|
|
|
666
1236
|
"black-forest-labs/flux-1-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-dev",
|
|
667
1237
|
// Alibaba Wan 2.6 (t2i)
|
|
668
1238
|
"alibaba/wan-2.6": "https://api.runpod.ai/v2/wan-2-6-t2i",
|
|
1239
|
+
// Tongyi Z-Image Turbo (t2i)
|
|
1240
|
+
"tongyi-mai/z-image-turbo": "https://api.runpod.ai/v2/z-image-turbo",
|
|
1241
|
+
"z-image-turbo": "https://api.runpod.ai/v2/z-image-turbo",
|
|
1242
|
+
// alias, not advertised
|
|
669
1243
|
// Nano Banana (edit only)
|
|
670
1244
|
"google/nano-banana-edit": "https://api.runpod.ai/v2/nano-banana-edit",
|
|
671
1245
|
"nano-banana-edit": "https://api.runpod.ai/v2/nano-banana-edit",
|
|
@@ -679,6 +1253,26 @@ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
|
|
|
679
1253
|
var SPEECH_MODEL_ID_TO_ENDPOINT_URL = {
|
|
680
1254
|
"resembleai/chatterbox-turbo": "https://api.runpod.ai/v2/chatterbox-turbo/"
|
|
681
1255
|
};
|
|
1256
|
+
var TRANSCRIPTION_MODEL_ID_TO_ENDPOINT_URL = {
|
|
1257
|
+
"pruna/whisper-v3-large": "https://api.runpod.ai/v2/whisper-v3-large"
|
|
1258
|
+
};
|
|
1259
|
+
var VIDEO_MODEL_ID_TO_ENDPOINT_URL = {
|
|
1260
|
+
"pruna/p-video": "https://api.runpod.ai/v2/p-video",
|
|
1261
|
+
"vidu/q3-t2v": "https://api.runpod.ai/v2/vidu-q3-t2v",
|
|
1262
|
+
"vidu/q3-i2v": "https://api.runpod.ai/v2/vidu-q3-i2v",
|
|
1263
|
+
"kwaivgi/kling-v2.6-std-motion-control": "https://api.runpod.ai/v2/kling-v2-6-std-motion-control",
|
|
1264
|
+
"kwaivgi/kling-video-o1-r2v": "https://api.runpod.ai/v2/kling-video-o1-r2v",
|
|
1265
|
+
"kwaivgi/kling-v2.1-i2v-pro": "https://api.runpod.ai/v2/kling-v2-1-i2v-pro",
|
|
1266
|
+
"alibaba/wan-2.6-t2v": "https://api.runpod.ai/v2/wan-2-6-t2v",
|
|
1267
|
+
"alibaba/wan-2.6-i2v": "https://api.runpod.ai/v2/wan-2-6-i2v",
|
|
1268
|
+
"alibaba/wan-2.5": "https://api.runpod.ai/v2/wan-2-5",
|
|
1269
|
+
"alibaba/wan-2.2-t2v-720-lora": "https://api.runpod.ai/v2/wan-2-2-t2v-720-lora",
|
|
1270
|
+
"alibaba/wan-2.2-i2v-720": "https://api.runpod.ai/v2/wan-2-2-i2v-720",
|
|
1271
|
+
"alibaba/wan-2.1-i2v-720": "https://api.runpod.ai/v2/wan-2-1-i2v-720",
|
|
1272
|
+
"bytedance/seedance-v1.5-pro-i2v": "https://api.runpod.ai/v2/seedance-v1-5-pro-i2v",
|
|
1273
|
+
"openai/sora-2-pro-i2v": "https://api.runpod.ai/v2/sora-2-pro-i2v",
|
|
1274
|
+
"openai/sora-2-i2v": "https://api.runpod.ai/v2/sora-2-i2v"
|
|
1275
|
+
};
|
|
682
1276
|
var MODEL_ID_TO_OPENAI_NAME = {
|
|
683
1277
|
"qwen/qwen3-32b-awq": "Qwen/Qwen3-32B-AWQ",
|
|
684
1278
|
"deepcogito/cogito-671b-v2.1-fp8": "deepcogito/cogito-671b-v2.1-FP8",
|
|
@@ -707,7 +1301,7 @@ function parseRunpodConsoleEndpointId(modelIdOrUrl) {
|
|
|
707
1301
|
}
|
|
708
1302
|
function createRunpod(options = {}) {
|
|
709
1303
|
const getHeaders = () => ({
|
|
710
|
-
Authorization: `Bearer ${(0,
|
|
1304
|
+
Authorization: `Bearer ${(0, import_provider_utils6.loadApiKey)({
|
|
711
1305
|
apiKey: options.apiKey,
|
|
712
1306
|
environmentVariableName: "RUNPOD_API_KEY",
|
|
713
1307
|
description: "Runpod"
|
|
@@ -737,7 +1331,7 @@ function createRunpod(options = {}) {
|
|
|
737
1331
|
}
|
|
738
1332
|
return {
|
|
739
1333
|
provider: `runpod.${modelType}`,
|
|
740
|
-
url: ({ path }) => `${(0,
|
|
1334
|
+
url: ({ path }) => `${(0, import_provider_utils6.withoutTrailingSlash)(baseURL)}${path}`,
|
|
741
1335
|
headers: getHeaders,
|
|
742
1336
|
fetch: runpodFetch
|
|
743
1337
|
};
|
|
@@ -782,6 +1376,30 @@ function createRunpod(options = {}) {
|
|
|
782
1376
|
fetch: runpodFetch
|
|
783
1377
|
});
|
|
784
1378
|
};
|
|
1379
|
+
const createTranscriptionModel = (modelId) => {
|
|
1380
|
+
const endpointIdFromConsole = parseRunpodConsoleEndpointId(modelId);
|
|
1381
|
+
const normalizedModelId = endpointIdFromConsole ?? modelId;
|
|
1382
|
+
const mappedBaseURL = TRANSCRIPTION_MODEL_ID_TO_ENDPOINT_URL[normalizedModelId];
|
|
1383
|
+
const baseURL = mappedBaseURL ?? (normalizedModelId.startsWith("http") ? normalizedModelId : `https://api.runpod.ai/v2/${normalizedModelId}`);
|
|
1384
|
+
return new RunpodTranscriptionModel(normalizedModelId, {
|
|
1385
|
+
provider: "runpod.transcription",
|
|
1386
|
+
baseURL,
|
|
1387
|
+
headers: getHeaders,
|
|
1388
|
+
fetch: runpodFetch
|
|
1389
|
+
});
|
|
1390
|
+
};
|
|
1391
|
+
const createVideoModel = (modelId) => {
|
|
1392
|
+
const endpointIdFromConsole = parseRunpodConsoleEndpointId(modelId);
|
|
1393
|
+
const normalizedModelId = endpointIdFromConsole ?? modelId;
|
|
1394
|
+
const mappedBaseURL = VIDEO_MODEL_ID_TO_ENDPOINT_URL[normalizedModelId];
|
|
1395
|
+
const baseURL = mappedBaseURL ?? (normalizedModelId.startsWith("http") ? normalizedModelId : `https://api.runpod.ai/v2/${normalizedModelId}`);
|
|
1396
|
+
return new RunpodVideoModel(normalizedModelId, {
|
|
1397
|
+
provider: "runpod.video",
|
|
1398
|
+
baseURL,
|
|
1399
|
+
headers: getHeaders,
|
|
1400
|
+
fetch: options.fetch
|
|
1401
|
+
});
|
|
1402
|
+
};
|
|
785
1403
|
const provider = (modelId) => createChatModel(modelId);
|
|
786
1404
|
provider.completionModel = createCompletionModel;
|
|
787
1405
|
provider.languageModel = createChatModel;
|
|
@@ -790,6 +1408,10 @@ function createRunpod(options = {}) {
|
|
|
790
1408
|
provider.image = createImageModel;
|
|
791
1409
|
provider.speechModel = createSpeechModel;
|
|
792
1410
|
provider.speech = createSpeechModel;
|
|
1411
|
+
provider.transcriptionModel = createTranscriptionModel;
|
|
1412
|
+
provider.transcription = createTranscriptionModel;
|
|
1413
|
+
provider.videoModel = createVideoModel;
|
|
1414
|
+
provider.video = createVideoModel;
|
|
793
1415
|
return provider;
|
|
794
1416
|
}
|
|
795
1417
|
var runpod = createRunpod();
|