vidspotai-shared 1.0.92 → 1.0.94
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/lib/schemas/demoSpec.schema.d.ts +689 -0
- package/lib/schemas/demoSpec.schema.d.ts.map +1 -0
- package/lib/schemas/demoSpec.schema.js +276 -0
- package/lib/schemas/index.d.ts +1 -0
- package/lib/schemas/index.d.ts.map +1 -1
- package/lib/schemas/index.js +1 -0
- package/lib/schemas/project.schema.d.ts +78 -0
- package/lib/schemas/project.schema.d.ts.map +1 -1
- package/lib/schemas/project.schema.js +55 -1
- package/lib/schemas/videoPlan.schema.d.ts +69 -0
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
- package/lib/schemas/videoPlan.schema.js +30 -1
- package/lib/services/agent/editClassifier.d.ts +16 -0
- package/lib/services/agent/editClassifier.d.ts.map +1 -1
- package/lib/services/agent/index.d.ts +1 -0
- package/lib/services/agent/index.d.ts.map +1 -1
- package/lib/services/agent/index.js +1 -0
- package/lib/services/agent/overlayRenderer.d.ts.map +1 -1
- package/lib/services/agent/overlayRenderer.js +8 -0
- package/lib/services/agent/planner/Planner.d.ts.map +1 -1
- package/lib/services/agent/planner/Planner.js +13 -2
- package/lib/services/agent/planner/structuralRules.d.ts.map +1 -1
- package/lib/services/agent/planner/structuralRules.js +6 -1
- package/lib/services/agent/textStylePacks.d.ts +35 -0
- package/lib/services/agent/textStylePacks.d.ts.map +1 -0
- package/lib/services/agent/textStylePacks.js +70 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts +46 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/estimateCost.tool.d.ts +16 -0
- package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/planVideo.tool.d.ts +27 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/render.tool.d.ts +16 -0
- package/lib/services/agent/tools/render.tool.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.js +8 -8
- package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/google.service.js +92 -8
- package/lib/services/asr/index.d.ts +1 -0
- package/lib/services/asr/index.d.ts.map +1 -1
- package/lib/services/asr/index.js +1 -0
- package/lib/services/asr/transcribeWithFallback.d.ts +54 -0
- package/lib/services/asr/transcribeWithFallback.d.ts.map +1 -0
- package/lib/services/asr/transcribeWithFallback.js +87 -0
- package/lib/services/editor/designToProject.d.ts +2 -0
- package/lib/services/editor/designToProject.d.ts.map +1 -1
- package/lib/services/editor/designToProject.js +10 -0
- package/lib/services/editor/planToProject.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.d.ts +9 -3
- package/lib/services/editor/planToProject.helpers.d.ts.map +1 -1
- package/lib/services/editor/planToProject.helpers.js +17 -2
- package/lib/services/editor/planToProject.js +21 -3
- package/package.json +1 -1
|
@@ -36,6 +36,7 @@ declare const InputSchema: z.ZodObject<{
|
|
|
36
36
|
fx: "fx";
|
|
37
37
|
}>;
|
|
38
38
|
name: z.ZodOptional<z.ZodString>;
|
|
39
|
+
sourceTrackId: z.ZodOptional<z.ZodString>;
|
|
39
40
|
index: z.ZodNumber;
|
|
40
41
|
muted: z.ZodDefault<z.ZodBoolean>;
|
|
41
42
|
hidden: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -230,6 +231,14 @@ declare const InputSchema: z.ZodObject<{
|
|
|
230
231
|
}>>;
|
|
231
232
|
backgroundColor: z.ZodOptional<z.ZodString>;
|
|
232
233
|
shadow: z.ZodOptional<z.ZodString>;
|
|
234
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
235
|
+
none: "none";
|
|
236
|
+
"fade-soft": "fade-soft";
|
|
237
|
+
"kinetic-pop": "kinetic-pop";
|
|
238
|
+
"editorial-wipe": "editorial-wipe";
|
|
239
|
+
"bold-slam": "bold-slam";
|
|
240
|
+
"type-on": "type-on";
|
|
241
|
+
}>>;
|
|
233
242
|
id: z.ZodString;
|
|
234
243
|
trackId: z.ZodString;
|
|
235
244
|
display: z.ZodObject<{
|
|
@@ -285,6 +294,12 @@ declare const InputSchema: z.ZodObject<{
|
|
|
285
294
|
color: z.ZodDefault<z.ZodString>;
|
|
286
295
|
highlightColor: z.ZodOptional<z.ZodString>;
|
|
287
296
|
language: z.ZodDefault<z.ZodString>;
|
|
297
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
298
|
+
none: "none";
|
|
299
|
+
"tiktok-word": "tiktok-word";
|
|
300
|
+
"karaoke-fill": "karaoke-fill";
|
|
301
|
+
"block-cut": "block-cut";
|
|
302
|
+
}>>;
|
|
288
303
|
id: z.ZodString;
|
|
289
304
|
trackId: z.ZodString;
|
|
290
305
|
display: z.ZodObject<{
|
|
@@ -353,6 +368,7 @@ declare const InputSchema: z.ZodObject<{
|
|
|
353
368
|
"from-bottom-left": "from-bottom-left";
|
|
354
369
|
}>>;
|
|
355
370
|
}, z.core.$strip>>>;
|
|
371
|
+
masterVolume: z.ZodDefault<z.ZodNumber>;
|
|
356
372
|
agentRunId: z.ZodOptional<z.ZodString>;
|
|
357
373
|
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
358
374
|
createdAt: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimateCost.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/estimateCost.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE/D,QAAA,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"estimateCost.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/estimateCost.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE/D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;iBAmBhB,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAC3C,OAAO,WAAW,EAClB,OAAO,YAAY,CAgEpB,CAAC"}
|
|
@@ -202,6 +202,12 @@ declare const OutputSchema: z.ZodObject<{
|
|
|
202
202
|
fontWeight: z.ZodOptional<z.ZodNumber>;
|
|
203
203
|
color: z.ZodOptional<z.ZodString>;
|
|
204
204
|
highlightColor: z.ZodOptional<z.ZodString>;
|
|
205
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
206
|
+
none: "none";
|
|
207
|
+
"tiktok-word": "tiktok-word";
|
|
208
|
+
"karaoke-fill": "karaoke-fill";
|
|
209
|
+
"block-cut": "block-cut";
|
|
210
|
+
}>>;
|
|
205
211
|
}, z.core.$strip>>;
|
|
206
212
|
onScreenText: z.ZodOptional<z.ZodString>;
|
|
207
213
|
overlays: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -259,6 +265,14 @@ declare const OutputSchema: z.ZodObject<{
|
|
|
259
265
|
"word-pop": "word-pop";
|
|
260
266
|
"highlight-current": "highlight-current";
|
|
261
267
|
}>>;
|
|
268
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
269
|
+
none: "none";
|
|
270
|
+
"fade-soft": "fade-soft";
|
|
271
|
+
"kinetic-pop": "kinetic-pop";
|
|
272
|
+
"editorial-wipe": "editorial-wipe";
|
|
273
|
+
"bold-slam": "bold-slam";
|
|
274
|
+
"type-on": "type-on";
|
|
275
|
+
}>>;
|
|
262
276
|
startMs: z.ZodOptional<z.ZodNumber>;
|
|
263
277
|
endMs: z.ZodOptional<z.ZodNumber>;
|
|
264
278
|
persistAcrossScenes: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -348,7 +362,20 @@ declare const OutputSchema: z.ZodObject<{
|
|
|
348
362
|
fontWeight: z.ZodOptional<z.ZodNumber>;
|
|
349
363
|
color: z.ZodOptional<z.ZodString>;
|
|
350
364
|
highlightColor: z.ZodOptional<z.ZodString>;
|
|
365
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
366
|
+
none: "none";
|
|
367
|
+
"tiktok-word": "tiktok-word";
|
|
368
|
+
"karaoke-fill": "karaoke-fill";
|
|
369
|
+
"block-cut": "block-cut";
|
|
370
|
+
}>>;
|
|
351
371
|
}, z.core.$strip>>;
|
|
372
|
+
textStylePack: z.ZodOptional<z.ZodEnum<{
|
|
373
|
+
bold: "bold";
|
|
374
|
+
clean: "clean";
|
|
375
|
+
kinetic: "kinetic";
|
|
376
|
+
editorial: "editorial";
|
|
377
|
+
minimal: "minimal";
|
|
378
|
+
}>>;
|
|
352
379
|
bible: z.ZodOptional<z.ZodObject<{
|
|
353
380
|
characters: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
354
381
|
id: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planVideo.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/planVideo.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQ/D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAExD;AAED,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIf,CAAC;AAEH,QAAA,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"planVideo.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/planVideo.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQ/D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAExD;AAED,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEhB,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,cAAc,CACxC,OAAO,WAAW,EAClB,OAAO,YAAY,CAuBpB,CAAC"}
|
|
@@ -51,6 +51,7 @@ declare const InputSchema: z.ZodObject<{
|
|
|
51
51
|
fx: "fx";
|
|
52
52
|
}>;
|
|
53
53
|
name: z.ZodOptional<z.ZodString>;
|
|
54
|
+
sourceTrackId: z.ZodOptional<z.ZodString>;
|
|
54
55
|
index: z.ZodNumber;
|
|
55
56
|
muted: z.ZodDefault<z.ZodBoolean>;
|
|
56
57
|
hidden: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -245,6 +246,14 @@ declare const InputSchema: z.ZodObject<{
|
|
|
245
246
|
}>>;
|
|
246
247
|
backgroundColor: z.ZodOptional<z.ZodString>;
|
|
247
248
|
shadow: z.ZodOptional<z.ZodString>;
|
|
249
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
250
|
+
none: "none";
|
|
251
|
+
"fade-soft": "fade-soft";
|
|
252
|
+
"kinetic-pop": "kinetic-pop";
|
|
253
|
+
"editorial-wipe": "editorial-wipe";
|
|
254
|
+
"bold-slam": "bold-slam";
|
|
255
|
+
"type-on": "type-on";
|
|
256
|
+
}>>;
|
|
248
257
|
id: z.ZodString;
|
|
249
258
|
trackId: z.ZodString;
|
|
250
259
|
display: z.ZodObject<{
|
|
@@ -300,6 +309,12 @@ declare const InputSchema: z.ZodObject<{
|
|
|
300
309
|
color: z.ZodDefault<z.ZodString>;
|
|
301
310
|
highlightColor: z.ZodOptional<z.ZodString>;
|
|
302
311
|
language: z.ZodDefault<z.ZodString>;
|
|
312
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
313
|
+
none: "none";
|
|
314
|
+
"tiktok-word": "tiktok-word";
|
|
315
|
+
"karaoke-fill": "karaoke-fill";
|
|
316
|
+
"block-cut": "block-cut";
|
|
317
|
+
}>>;
|
|
303
318
|
id: z.ZodString;
|
|
304
319
|
trackId: z.ZodString;
|
|
305
320
|
display: z.ZodObject<{
|
|
@@ -368,6 +383,7 @@ declare const InputSchema: z.ZodObject<{
|
|
|
368
383
|
"from-bottom-left": "from-bottom-left";
|
|
369
384
|
}>>;
|
|
370
385
|
}, z.core.$strip>>>;
|
|
386
|
+
masterVolume: z.ZodDefault<z.ZodNumber>;
|
|
371
387
|
agentRunId: z.ZodOptional<z.ZodString>;
|
|
372
388
|
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
373
389
|
createdAt: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/render.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;IACvC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CAC3C,KAAK,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAGvC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAE5D;AAED,QAAA,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"render.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/render.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;IACvC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CAC3C,KAAK,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAGvC,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAE5D;AAED,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQf,CAAC;AAEH,QAAA,MAAM,YAAY;;;iBAGhB,CAAC;AAEH,eAAO,MAAM,UAAU,EAAE,cAAc,CACrC,OAAO,WAAW,EAClB,OAAO,YAAY,CA2BpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bytedance.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/bytedance/bytedance.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAUlB,qBAAa,gBAAiB,SAAQ,wBAAwB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CACsD;IAI9E,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,WAAW;IAIb,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"bytedance.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/bytedance/bytedance.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAUlB,qBAAa,gBAAiB,SAAQ,wBAAwB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CACsD;IAI9E,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,WAAW;IAIb,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA4L3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA4HjD,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAyEjD"}
|
|
@@ -123,25 +123,25 @@ class ByteDanceService extends baseAiGenProvider_service_1.BaseAiGenProviderServ
|
|
|
123
123
|
const param = parsed?.error?.param;
|
|
124
124
|
const message = parsed?.error?.message ?? "";
|
|
125
125
|
if (code?.startsWith("InputTextSensitiveContentDetected")) {
|
|
126
|
-
throw new errors_1.UserFacingError("Your prompt contains content that violates the content policy. Please modify your prompt and try again.");
|
|
126
|
+
throw new errors_1.UserFacingError("Your prompt contains content that violates the content policy. Please modify your prompt and try again.", errors_1.USER_FACING_ERROR_CODES.CONTENT_POLICY_VIOLATION);
|
|
127
127
|
}
|
|
128
128
|
if (code?.startsWith("InputImageSensitiveContentDetected")) {
|
|
129
|
-
throw new errors_1.UserFacingError("Your input image contains sensitive content and cannot be processed. Please use a different image.");
|
|
129
|
+
throw new errors_1.UserFacingError("Your input image contains sensitive content and cannot be processed. Please use a different image.", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
130
130
|
}
|
|
131
131
|
// Seedance r2v (reference-to-video) rejects input videos that contain
|
|
132
132
|
// real people / PII synchronously with this code. Treat as user-facing
|
|
133
133
|
// so we don't page Slack for moderation hits.
|
|
134
134
|
if (code?.startsWith("InputVideoSensitiveContentDetected")) {
|
|
135
|
-
throw new errors_1.UserFacingError("Your input video contains content (e.g. a recognizable real person) that this model cannot process. Please use a different video or an AI-generated clip.");
|
|
135
|
+
throw new errors_1.UserFacingError("Your input video contains content (e.g. a recognizable real person) that this model cannot process. Please use a different video or an AI-generated clip.", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
136
136
|
}
|
|
137
137
|
if (code === "InvalidParameter.UnsupportedImageFormat" || (code?.includes("UnsupportedImageFormat"))) {
|
|
138
|
-
throw new errors_1.UserFacingError("Your input image format is not supported. Please use JPEG or PNG.");
|
|
138
|
+
throw new errors_1.UserFacingError("Your input image format is not supported. Please use JPEG or PNG.", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
139
139
|
}
|
|
140
140
|
// Seedance rejects images larger than 30 MiB outright. New uploads are
|
|
141
141
|
// capped at 20 MiB in firebase-functions, but legacy storage URLs may
|
|
142
142
|
// still hit this — surface a user-facing message instead of paging Slack.
|
|
143
143
|
if (code === "InvalidParameter.OversizeImage" || (code?.includes("OversizeImage"))) {
|
|
144
|
-
throw new errors_1.UserFacingError("Your input image is too large for this model. Please upload an image under 20 MiB and try again.");
|
|
144
|
+
throw new errors_1.UserFacingError("Your input image is too large for this model. Please upload an image under 20 MiB and try again.", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
145
145
|
}
|
|
146
146
|
// Seedance 2.x reports image-related errors against `content[N]` (the
|
|
147
147
|
// reference image is the Nth item in the multipart `content` array)
|
|
@@ -150,15 +150,15 @@ class ByteDanceService extends baseAiGenProvider_service_1.BaseAiGenProviderServ
|
|
|
150
150
|
const isImageParam = param?.includes("image_url") || /^content\[\d+\]$/.test(param ?? "");
|
|
151
151
|
if (code === "InvalidParameter" && isImageParam) {
|
|
152
152
|
if (message.includes("aspect ratio")) {
|
|
153
|
-
throw new errors_1.UserFacingError("Your input image's aspect ratio is not supported by this model. Please use an image with an aspect ratio between 0.40 and 2.50 (e.g. 1:1, 9:16, 16:9).");
|
|
153
|
+
throw new errors_1.UserFacingError("Your input image's aspect ratio is not supported by this model. Please use an image with an aspect ratio between 0.40 and 2.50 (e.g. 1:1, 9:16, 16:9).", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
154
154
|
}
|
|
155
155
|
if (/pixel count|must be greater than or equal to \d+/i.test(message) ||
|
|
156
156
|
message.includes("width") ||
|
|
157
157
|
message.includes("height") ||
|
|
158
158
|
message.includes("px")) {
|
|
159
|
-
throw new errors_1.UserFacingError("Your input image is too small for this model. Please use a higher-resolution image (at least 640×640, or 300px on the shorter side).");
|
|
159
|
+
throw new errors_1.UserFacingError("Your input image is too small for this model. Please use a higher-resolution image (at least 640×640, or 300px on the shorter side).", errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
160
160
|
}
|
|
161
|
-
throw new errors_1.UserFacingError(`Your input image is not valid: ${message}
|
|
161
|
+
throw new errors_1.UserFacingError(`Your input image is not valid: ${message}`, errors_1.USER_FACING_ERROR_CODES.INPUT_IMAGE_REJECTED);
|
|
162
162
|
}
|
|
163
163
|
throw new Error(`ByteDance generateVideo failed (${resp.status}): ${errText}`);
|
|
164
164
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/google.service.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"google.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/google.service.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAkElB,qBAAa,aAAc,SAAQ,wBAAwB;IAKzD,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAK;;IAQ/C;;;;;;;;;OASG;IACG,YAAY,CAChB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAoChC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAoCvB;;;;OAIG;YACW,kBAAkB;IAsC1B,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA0O3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8J3C,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;YAiBnB,cAAc;IAwG5B;;;;;;OAMG;IACH;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAIjC,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAY,EAAE,UAAmB,EAAE,SAAiB,EAAE,SAAa,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,iBAAiB,GAAG,MAAM;CA8BpJ"}
|
|
@@ -22,6 +22,52 @@ const googleFetch_1 = require("./googleFetch");
|
|
|
22
22
|
const googleMusic_1 = require("./googleMusic");
|
|
23
23
|
const googleApiKeys_1 = require("./googleApiKeys");
|
|
24
24
|
const googleKeyPool_1 = require("./googleKeyPool");
|
|
25
|
+
/**
|
|
26
|
+
* Wait until a file exists AND its on-disk size has stopped growing, returning
|
|
27
|
+
* the final stable byte size. The Veo Files API downloader can resolve / create
|
|
28
|
+
* the file before all bytes are flushed; reading it immediately then streams a
|
|
29
|
+
* partial file — truncated at a chunk boundary (commonly exactly 4 MiB) — which
|
|
30
|
+
* drops the trailing `moov` atom and yields a corrupt MP4. Requiring the size to
|
|
31
|
+
* hold steady across consecutive polls closes that flush race.
|
|
32
|
+
*/
|
|
33
|
+
async function waitForStableFile(path, timeoutMs = 30000, intervalMs = 500) {
|
|
34
|
+
const start = Date.now();
|
|
35
|
+
let lastSize = -1;
|
|
36
|
+
let stablePolls = 0;
|
|
37
|
+
while (Date.now() - start < timeoutMs) {
|
|
38
|
+
let size = -1;
|
|
39
|
+
try {
|
|
40
|
+
size = (await promises_1.default.stat(path)).size;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// not created yet — keep polling
|
|
44
|
+
}
|
|
45
|
+
if (size > 0 && size === lastSize) {
|
|
46
|
+
// Two consecutive equal, non-zero reads ⇒ the writer has finished.
|
|
47
|
+
if (++stablePolls >= 2)
|
|
48
|
+
return size;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
stablePolls = 0;
|
|
52
|
+
}
|
|
53
|
+
lastSize = size;
|
|
54
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Timeout waiting for a stable (fully-written) file: ${path}`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Cheap structural check that a local MP4 is COMPLETE: a well-formed Veo clip
|
|
60
|
+
* carries both an `ftyp` box (header) and a `moov` box (movie metadata, written
|
|
61
|
+
* at the END for non-faststart output). A truncated download is missing `moov`
|
|
62
|
+
* — exactly what ffprobe reports downstream as "moov atom not found". Scans the
|
|
63
|
+
* file bytes (clips are a few MB) so we never need an ffprobe binary in this
|
|
64
|
+
* shared module.
|
|
65
|
+
*/
|
|
66
|
+
async function mp4IsComplete(path) {
|
|
67
|
+
const buf = await promises_1.default.readFile(path);
|
|
68
|
+
return (buf.includes(Buffer.from("ftyp", "ascii")) &&
|
|
69
|
+
buf.includes(Buffer.from("moov", "ascii")));
|
|
70
|
+
}
|
|
25
71
|
const VEO_3_1_MODELS = new Set([
|
|
26
72
|
aiModels_1.EVideoGenModels.GOOGLE_VEO_3_1,
|
|
27
73
|
aiModels_1.EVideoGenModels.GOOGLE_VEO_3_1_FAST,
|
|
@@ -402,14 +448,52 @@ class GoogleService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
402
448
|
// separate project, so downloading its videos via `this.ai` would 403/404.
|
|
403
449
|
// Use the re-selected `client` (falls back to `this.ai` for un-tagged
|
|
404
450
|
// legacy tasks, which were submitted on GOOGLE_API_KEY anyway).
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
451
|
+
// Download → validate-complete → upload, retried as a unit. The Files API
|
|
452
|
+
// downloader intermittently resolves before the clip is fully flushed to
|
|
453
|
+
// disk; uploading then truncates the scene at a chunk boundary (commonly
|
|
454
|
+
// exactly 4 MiB), dropping the trailing `moov` atom and yielding a corrupt
|
|
455
|
+
// MP4 that ffprobe rejects downstream (poster/watermark "moov atom not
|
|
456
|
+
// found", and a broken deliverable). Guard with (1) a stable-size wait so
|
|
457
|
+
// we only read a fully-written file, (2) a structural ftyp+moov check, and
|
|
458
|
+
// (3) a stored-vs-local size match after upload. Any failure re-runs the
|
|
459
|
+
// whole download instead of shipping corruption.
|
|
460
|
+
const MAX_FETCH_ATTEMPTS = 3;
|
|
461
|
+
let uploaded = false;
|
|
462
|
+
for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS && !uploaded; attempt++) {
|
|
463
|
+
await this.withTransientRetry("files.download", () => client.files.download({ file: video, downloadPath: localPath }));
|
|
464
|
+
const localSize = await waitForStableFile(localPath, 30000, 500);
|
|
465
|
+
if (await mp4IsComplete(localPath)) {
|
|
466
|
+
await (0, promises_2.pipeline)((0, fs_1.createReadStream)(localPath), file.createWriteStream({ contentType: "video/mp4" }));
|
|
467
|
+
const [meta] = await file.getMetadata();
|
|
468
|
+
const storedSize = Number(meta.size);
|
|
469
|
+
if (Number.isFinite(storedSize) && storedSize === localSize) {
|
|
470
|
+
uploaded = true;
|
|
471
|
+
break; // faithful, complete upload
|
|
472
|
+
}
|
|
473
|
+
logger_1.logger.warn("google: scene upload size mismatch — retrying", {
|
|
474
|
+
filePath,
|
|
475
|
+
attempt,
|
|
476
|
+
localSize,
|
|
477
|
+
storedSize,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
logger_1.logger.warn("google: downloaded scene missing moov atom — retrying", {
|
|
482
|
+
filePath,
|
|
483
|
+
attempt,
|
|
484
|
+
localSize,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
// Failed validation — discard the partial file before the next attempt.
|
|
488
|
+
await promises_1.default.unlink(localPath).catch(() => { });
|
|
489
|
+
}
|
|
490
|
+
if (!uploaded) {
|
|
491
|
+
logger_1.logger.error("google: scene download/upload failed integrity validation — giving up", { filePath });
|
|
492
|
+
return {
|
|
493
|
+
status: types_1.EVideoSceneStatus.FAILED,
|
|
494
|
+
errorMessage: "Generated video failed integrity validation (incomplete/truncated download).",
|
|
495
|
+
};
|
|
496
|
+
}
|
|
413
497
|
const [signedUrl] = await file.getSignedUrl({
|
|
414
498
|
action: "read",
|
|
415
499
|
expires: "03-09-2491",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/asr/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/asr/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC"}
|
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./assemblyai.service"), exports);
|
|
18
18
|
__exportStar(require("./whisper.service"), exports);
|
|
19
|
+
__exportStar(require("./transcribeWithFallback"), exports);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { TranscribeParams, TranscribeResult } from "./assemblyai.service";
|
|
2
|
+
/**
|
|
3
|
+
* Provider-agnostic ASR entry point with automatic AssemblyAI → Whisper
|
|
4
|
+
* fallback. Mirrors the `provider: "auto"` strategy already used by the agent's
|
|
5
|
+
* generate_captions tool, but reusable from the REST controller, the MCP tool,
|
|
6
|
+
* and the picker worker.
|
|
7
|
+
*
|
|
8
|
+
* Selection rule:
|
|
9
|
+
* - AssemblyAI is the PRIMARY (cheaper $0.15/hr, native diarization, URL
|
|
10
|
+
* submission for long audio) — used whenever ASSEMBLYAI_API_KEY is set.
|
|
11
|
+
* - Whisper is the FALLBACK (reuses OPENAI_API_KEY already provisioned;
|
|
12
|
+
* ~2.4× cost, 25 MB / short-audio only, no diarization) — used when the
|
|
13
|
+
* AssemblyAI key is absent OR the AssemblyAI call hard-fails at runtime.
|
|
14
|
+
*
|
|
15
|
+
* Historically the AssemblyAI key was never provisioned (a commented-out
|
|
16
|
+
* placeholder in every env), so the REST transcribe path always threw. Routing
|
|
17
|
+
* through here makes it work today on the existing OpenAI key and auto-upgrades
|
|
18
|
+
* to AssemblyAI the moment its key lands in Doppler — no code change needed.
|
|
19
|
+
*/
|
|
20
|
+
export type AsrProviderUsed = "assemblyai" | "whisper";
|
|
21
|
+
export interface AsrTranscribeOutcome {
|
|
22
|
+
result: TranscribeResult;
|
|
23
|
+
providerUsed: AsrProviderUsed;
|
|
24
|
+
}
|
|
25
|
+
/** True when at least one ASR provider has a usable key. */
|
|
26
|
+
export declare const isAsrConfigured: () => boolean;
|
|
27
|
+
/** The provider that a sync transcribe would START with, given current keys. */
|
|
28
|
+
export declare const primaryAsrProvider: () => AsrProviderUsed;
|
|
29
|
+
/**
|
|
30
|
+
* Credits for a given provider + audio duration. `getCreditUsed` is pure
|
|
31
|
+
* pricing math, but the service constructors key-guard, so we only instantiate
|
|
32
|
+
* the provider whose key is present — which for `providerUsed` it always is,
|
|
33
|
+
* since that provider just ran.
|
|
34
|
+
*/
|
|
35
|
+
export declare const asrCreditUsed: (provider: AsrProviderUsed, audioDurationSec: number, speakerLabels?: boolean) => number;
|
|
36
|
+
/** Whether async (submit + poll) is available — AssemblyAI only. */
|
|
37
|
+
export declare const supportsAsyncAsr: () => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Submit an async AssemblyAI job. Only valid when {@link supportsAsyncAsr} is
|
|
40
|
+
* true; Whisper has no submission endpoint.
|
|
41
|
+
*/
|
|
42
|
+
export declare const submitAsyncAsr: (params: TranscribeParams) => Promise<{
|
|
43
|
+
id: string;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Transcribe synchronously (poll-to-completion for AssemblyAI; single call for
|
|
47
|
+
* Whisper) with automatic fallback. Returns the result plus which provider
|
|
48
|
+
* actually produced it so callers can reconcile credits against the right rate.
|
|
49
|
+
*/
|
|
50
|
+
export declare const transcribeWithFallback: (params: TranscribeParams, opts?: {
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
intervalMs?: number;
|
|
53
|
+
}) => Promise<AsrTranscribeOutcome>;
|
|
54
|
+
//# sourceMappingURL=transcribeWithFallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcribeWithFallback.d.ts","sourceRoot":"","sources":["../../../src/services/asr/transcribeWithFallback.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAG9B;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,eAAe,CAAC;CAC/B;AAKD,4DAA4D;AAC5D,eAAO,MAAM,eAAe,QAAO,OAA0C,CAAC;AAE9E,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,QAAO,eAMrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,eAAe,EACzB,kBAAkB,MAAM,EACxB,uBAAqB,KACpB,MAKF,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,QAAO,OAA0B,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,gBAAgB,KACvB,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAKxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,gBAAgB,EACxB,OAAM;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,KACrD,OAAO,CAAC,oBAAoB,CAmC9B,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transcribeWithFallback = exports.submitAsyncAsr = exports.supportsAsyncAsr = exports.asrCreditUsed = exports.primaryAsrProvider = exports.isAsrConfigured = void 0;
|
|
4
|
+
const logger_1 = require("../../utils/logger");
|
|
5
|
+
const assemblyai_service_1 = require("./assemblyai.service");
|
|
6
|
+
const whisper_service_1 = require("./whisper.service");
|
|
7
|
+
const hasAssemblyAI = () => !!process.env.ASSEMBLYAI_API_KEY;
|
|
8
|
+
const hasWhisper = () => !!process.env.OPENAI_API_KEY;
|
|
9
|
+
/** True when at least one ASR provider has a usable key. */
|
|
10
|
+
const isAsrConfigured = () => hasAssemblyAI() || hasWhisper();
|
|
11
|
+
exports.isAsrConfigured = isAsrConfigured;
|
|
12
|
+
/** The provider that a sync transcribe would START with, given current keys. */
|
|
13
|
+
const primaryAsrProvider = () => {
|
|
14
|
+
if (hasAssemblyAI())
|
|
15
|
+
return "assemblyai";
|
|
16
|
+
if (hasWhisper())
|
|
17
|
+
return "whisper";
|
|
18
|
+
throw new Error("No ASR provider configured — set ASSEMBLYAI_API_KEY (preferred) or OPENAI_API_KEY");
|
|
19
|
+
};
|
|
20
|
+
exports.primaryAsrProvider = primaryAsrProvider;
|
|
21
|
+
/**
|
|
22
|
+
* Credits for a given provider + audio duration. `getCreditUsed` is pure
|
|
23
|
+
* pricing math, but the service constructors key-guard, so we only instantiate
|
|
24
|
+
* the provider whose key is present — which for `providerUsed` it always is,
|
|
25
|
+
* since that provider just ran.
|
|
26
|
+
*/
|
|
27
|
+
const asrCreditUsed = (provider, audioDurationSec, speakerLabels = false) => {
|
|
28
|
+
if (provider === "assemblyai") {
|
|
29
|
+
return new assemblyai_service_1.AssemblyAIService().getCreditUsed(audioDurationSec, speakerLabels);
|
|
30
|
+
}
|
|
31
|
+
return new whisper_service_1.WhisperAsrService().getCreditUsed(audioDurationSec);
|
|
32
|
+
};
|
|
33
|
+
exports.asrCreditUsed = asrCreditUsed;
|
|
34
|
+
/** Whether async (submit + poll) is available — AssemblyAI only. */
|
|
35
|
+
const supportsAsyncAsr = () => hasAssemblyAI();
|
|
36
|
+
exports.supportsAsyncAsr = supportsAsyncAsr;
|
|
37
|
+
/**
|
|
38
|
+
* Submit an async AssemblyAI job. Only valid when {@link supportsAsyncAsr} is
|
|
39
|
+
* true; Whisper has no submission endpoint.
|
|
40
|
+
*/
|
|
41
|
+
const submitAsyncAsr = async (params) => {
|
|
42
|
+
if (!hasAssemblyAI()) {
|
|
43
|
+
throw new Error("Async ASR requires AssemblyAI (ASSEMBLYAI_API_KEY not set)");
|
|
44
|
+
}
|
|
45
|
+
return new assemblyai_service_1.AssemblyAIService().submit(params);
|
|
46
|
+
};
|
|
47
|
+
exports.submitAsyncAsr = submitAsyncAsr;
|
|
48
|
+
/**
|
|
49
|
+
* Transcribe synchronously (poll-to-completion for AssemblyAI; single call for
|
|
50
|
+
* Whisper) with automatic fallback. Returns the result plus which provider
|
|
51
|
+
* actually produced it so callers can reconcile credits against the right rate.
|
|
52
|
+
*/
|
|
53
|
+
const transcribeWithFallback = async (params, opts = {}) => {
|
|
54
|
+
const runWhisper = async () => ({
|
|
55
|
+
result: await new whisper_service_1.WhisperAsrService().transcribe(params),
|
|
56
|
+
providerUsed: "whisper",
|
|
57
|
+
});
|
|
58
|
+
if (hasAssemblyAI()) {
|
|
59
|
+
try {
|
|
60
|
+
const result = await new assemblyai_service_1.AssemblyAIService().transcribe(params, opts);
|
|
61
|
+
// A hard provider error → try the fallback. A "processing" status is a
|
|
62
|
+
// legitimate long-audio timeout (caller polls later), not a failure, so
|
|
63
|
+
// we keep it on the AssemblyAI track.
|
|
64
|
+
if (result.status === "error" && hasWhisper()) {
|
|
65
|
+
logger_1.logger.warn("ASR: AssemblyAI returned error — falling back to Whisper", {
|
|
66
|
+
audioUrl: params.audioUrl,
|
|
67
|
+
err: result.errorMessage,
|
|
68
|
+
});
|
|
69
|
+
return await runWhisper();
|
|
70
|
+
}
|
|
71
|
+
return { result, providerUsed: "assemblyai" };
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (!hasWhisper())
|
|
75
|
+
throw err;
|
|
76
|
+
logger_1.logger.warn("ASR: AssemblyAI threw — falling back to Whisper", {
|
|
77
|
+
audioUrl: params.audioUrl,
|
|
78
|
+
err: err instanceof Error ? err.message : String(err),
|
|
79
|
+
});
|
|
80
|
+
return await runWhisper();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (hasWhisper())
|
|
84
|
+
return await runWhisper();
|
|
85
|
+
throw new Error("No ASR provider configured — set ASSEMBLYAI_API_KEY (preferred) or OPENAI_API_KEY");
|
|
86
|
+
};
|
|
87
|
+
exports.transcribeWithFallback = transcribeWithFallback;
|
|
@@ -62,6 +62,8 @@ export interface EditorDesignInput {
|
|
|
62
62
|
trackItemDetailsMap?: Record<string, DesignItemDetails>;
|
|
63
63
|
transitionIds?: string[];
|
|
64
64
|
transitionsMap?: Record<string, DesignTransition>;
|
|
65
|
+
/** Project-level master volume as the editor stores it: 0–100 (100 = unchanged). */
|
|
66
|
+
masterVolume?: number;
|
|
65
67
|
/** Server-write-zone field: editor passes it back as-is on autosave. */
|
|
66
68
|
agentRunId?: string;
|
|
67
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"designToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/designToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;;;;;;;;;GAiBG;AAEH,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,UAAU,iBAAkB,SAAQ,cAAc;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC/C,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA+BD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,OAAO,
|
|
1
|
+
{"version":3,"file":"designToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/designToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;;;;;;;;;GAiBG;AAEH,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,UAAU,iBAAkB,SAAQ,cAAc;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC/C,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA+BD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,EACf,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,OAAO,CAiGT"}
|
|
@@ -110,6 +110,10 @@ function designToProject(design, meta) {
|
|
|
110
110
|
size: { width, height },
|
|
111
111
|
aspect,
|
|
112
112
|
background: editorBackgroundToProject(d.background),
|
|
113
|
+
// Editor stores master volume as 0–100; canonical project uses 0–1.
|
|
114
|
+
masterVolume: typeof d.masterVolume === "number"
|
|
115
|
+
? Math.max(0, Math.min(100, d.masterVolume)) / 100
|
|
116
|
+
: 1,
|
|
113
117
|
tracks,
|
|
114
118
|
clips,
|
|
115
119
|
transitions,
|
|
@@ -210,8 +214,14 @@ function buildClip(id, trackId, type, base, detail, display, size) {
|
|
|
210
214
|
if (!text)
|
|
211
215
|
return null;
|
|
212
216
|
const align = details.align === "left" || details.align === "right" ? details.align : "center";
|
|
217
|
+
// Mirror of storeToProject (frontend): carry the text-box width into
|
|
218
|
+
// metadata.boxWidth so the renderer wraps long text within the canvas
|
|
219
|
+
// instead of overflowing at "max-content" width. Keeps the exported MP4
|
|
220
|
+
// in sync with the editor preview.
|
|
221
|
+
const boxWidth = numOr(details.width, 0);
|
|
213
222
|
return {
|
|
214
223
|
...common,
|
|
224
|
+
...(boxWidth > 0 ? { metadata: { ...cleanMetadata, boxWidth } } : {}),
|
|
215
225
|
type: "text",
|
|
216
226
|
text,
|
|
217
227
|
fontFamily: strOr(details.fontFamily, "Poppins"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"planToProject.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,OAAO,EAIR,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAehE,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAwZhE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Provenance, TextClip, Track, Transition } from "../../schemas/project.schema";
|
|
2
|
-
import type { PlannedScene, SceneAssetStrategy, TextOverlay, TransitionKind, VideoPlan } from "../../schemas/videoPlan.schema";
|
|
2
|
+
import type { PlannedScene, SceneAssetStrategy, TextOverlay, TextStylePack, TransitionKind, VideoPlan } from "../../schemas/videoPlan.schema";
|
|
3
3
|
import type { SceneRenderOutcome } from "./planToProject.types";
|
|
4
4
|
/**
|
|
5
5
|
* Pure building blocks for planToProject: track ids, strategy/transition/size
|
|
@@ -35,6 +35,12 @@ export declare function provenanceForScene(scene: PlannedScene, outcome: SceneRe
|
|
|
35
35
|
* of prior scene durations). `sceneDurationMs` clamps any overlay.endMs
|
|
36
36
|
* that overshoots the scene.
|
|
37
37
|
*/
|
|
38
|
-
export declare function buildOverlayClipsForScene(sceneIndex: number, offsetMs: number, sceneDurationMs: number, overlays: readonly TextOverlay[], frameHeight: number
|
|
39
|
-
|
|
38
|
+
export declare function buildOverlayClipsForScene(sceneIndex: number, offsetMs: number, sceneDurationMs: number, overlays: readonly TextOverlay[], frameHeight: number,
|
|
39
|
+
/**
|
|
40
|
+
* Per-video animation look. Resolves the preset for each overlay's role when
|
|
41
|
+
* the overlay didn't specify its own `preset`. Optional so regen callers that
|
|
42
|
+
* don't carry the plan still work (they fall through to "clean").
|
|
43
|
+
*/
|
|
44
|
+
stylePack?: TextStylePack): TextClip[];
|
|
45
|
+
export declare function makeTrack(id: string, kind: Track["kind"], index: number, name: string, sourceTrackId?: string): Track;
|
|
40
46
|
//# sourceMappingURL=planToProject.helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planToProject.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"planToProject.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/editor/planToProject.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACV,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;;GAMG;AAIH,eAAO,MAAM,QAAQ;;;;;;;CASX,CAAC;AASX,wBAAgB,eAAe,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAE9D;AAED,iFAAiF;AACjF,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAInD,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW5F;AAID,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,CASjF,CAAC;AAIF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,kBAAkB,GAAG,SAAS,GACtC,UAAU,CAiBZ;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,WAAW,EAAE,MAAM;AACnB;;;;GAIG;AACH,SAAS,CAAC,EAAE,aAAa,GACxB,QAAQ,EAAE,CA2CZ;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,KAAK,CAYP"}
|