@mux/ai 0.33.0 → 0.35.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-Chccb380.d.ts → index-fU3hmKZu.d.ts} +21 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +205 -132
- package/dist/index.js.map +1 -1
- package/dist/workflows/index.d.ts +1 -1
- package/dist/workflows/index.js +204 -131
- package/dist/workflows/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, j as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, k as ASK_QUESTIONS_MAX_QUESTION_LENGTH, l as AskQuestionsOptions, m as AskQuestionsResult, n as AskQuestionsType, o as AudioTranslationOptions, p as AudioTranslationResult, q as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, r as BurnedInCaptionsOptions, s as BurnedInCaptionsPromptOverrides, u as BurnedInCaptionsPromptSections, v as BurnedInCaptionsResult, C as CaptionReplacement, w as CensorMode, x as Chapter, y as ChapterSystemPromptSections, z as ChaptersOptions, D as ChaptersPromptOverrides, E as ChaptersPromptSections, F as ChaptersResult, G as ChaptersType, H as DEFAULT_DESCRIPTION_LENGTH, J as DEFAULT_SUMMARY_KEYWORD_LIMIT, K as DEFAULT_TITLE_LENGTH, M as EditCaptionsOptions, N as EditCaptionsResult, O as EmbeddingsOptions, P as EmbeddingsResult, Q as EngagementInsightsOptions, R as EngagementInsightsResult, T as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, U as HIVE_SEXUAL_CATEGORIES, V as HIVE_VIOLENCE_CATEGORIES, W as HiveModerationOutput, X as HiveModerationSource, Y as ModerationOptions, Z as ModerationProvider, _ as ModerationResult, $ as MomentInsight, a0 as OverallInsight, a1 as ProfanityDetectionPayload, a2 as Question, a3 as QuestionAnswer, a4 as QuestionAnswerType, a5 as ReplacementRecord, a6 as
|
|
1
|
+
export { A as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, j as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, k as ASK_QUESTIONS_MAX_QUESTION_LENGTH, l as AskQuestionsOptions, m as AskQuestionsResult, n as AskQuestionsType, o as AudioTranslationOptions, p as AudioTranslationResult, q as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, r as BurnedInCaptionsOptions, s as BurnedInCaptionsPromptOverrides, u as BurnedInCaptionsPromptSections, v as BurnedInCaptionsResult, C as CaptionReplacement, w as CensorMode, x as Chapter, y as ChapterSystemPromptSections, z as ChaptersOptions, D as ChaptersPromptOverrides, E as ChaptersPromptSections, F as ChaptersResult, G as ChaptersType, H as DEFAULT_DESCRIPTION_LENGTH, J as DEFAULT_SUMMARY_KEYWORD_LIMIT, K as DEFAULT_TITLE_LENGTH, M as EditCaptionsOptions, N as EditCaptionsResult, O as EmbeddingsOptions, P as EmbeddingsResult, Q as EngagementInsightsOptions, R as EngagementInsightsResult, T as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, U as HIVE_SEXUAL_CATEGORIES, V as HIVE_VIOLENCE_CATEGORIES, W as HiveModerationOutput, X as HiveModerationSource, Y as ModerationOptions, Z as ModerationProvider, _ as ModerationResult, $ as MomentInsight, a0 as OverallInsight, a1 as ProfanityDetectionPayload, a2 as Question, a3 as QuestionAnswer, a4 as QuestionAnswerType, a5 as ReplacementRecord, a6 as StaticRenditionCleanupOutcome, a7 as SummarizationOptions, a8 as SummarizationPromptOverrides, a9 as SummarizationPromptSections, aa as SummaryAndTagsResult, ab as SummaryType, ac as ThumbnailModerationScore, ad as TranslationChunkingOptions, ae as TranslationOptions, af as TranslationPayload, ag as TranslationResult, ah as aggregateTokenUsage, ai as applyOverrideLists, aj as applyReplacements, ak as askQuestions, al as buildReplacementRegex, am as burnedInCaptionsSchema, an as censorVttContent, ao as chapterSchema, ap as chaptersSchema, aq as createReplacer, ar as editCaptions, as as extractTranscriptSegmentsForHotspots, at as generateChapters, au as generateEmbeddings, av as generateEngagementInsights, aw as generateVideoEmbeddings, ax as getModerationScores, ay as getSummaryAndTags, az as hasBurnedInCaptions, aA as mapShotsToHotspots, aB as normalizeTranslatedVtt, aC as profanityDetectionSchema, aD as questionAnswerSchema, aE as shouldSplitChunkTranslationError, aF as summarySchema, aG as transformCueText, aH as translateAudio, aI as translateCaptions, aJ as translationSchema, aK as validateNeverTranslateTerms, aL as verifyNeverTranslateTerms } from '../index-fU3hmKZu.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@ai-sdk/anthropic';
|
|
4
4
|
import '@ai-sdk/google';
|
package/dist/workflows/index.js
CHANGED
|
@@ -643,6 +643,22 @@ var CONTENT_POLICY_REASONS = /* @__PURE__ */ new Set([
|
|
|
643
643
|
"SAFETY",
|
|
644
644
|
"SPII"
|
|
645
645
|
]);
|
|
646
|
+
var IncompleteGenerationError = class extends MuxAiError {
|
|
647
|
+
constructor(finishReason, rawFinishReason, usage) {
|
|
648
|
+
const reason = rawFinishReason ?? finishReason;
|
|
649
|
+
const message = finishReason === "length" ? `The model reached its output limit before producing a complete response (finish reason: ${reason}).` : `The model stopped before producing a complete response (finish reason: ${reason}).`;
|
|
650
|
+
super(message, {
|
|
651
|
+
type: "processing_error",
|
|
652
|
+
retryable: finishReason !== "length"
|
|
653
|
+
});
|
|
654
|
+
this.finishReason = finishReason;
|
|
655
|
+
this.rawFinishReason = rawFinishReason;
|
|
656
|
+
this.usage = usage;
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
function isIncompleteGenerationError(error) {
|
|
660
|
+
return MuxAiError.is(error) && typeof error.finishReason === "string";
|
|
661
|
+
}
|
|
646
662
|
async function withContentPolicyErrorHandling(operation) {
|
|
647
663
|
try {
|
|
648
664
|
return await operation();
|
|
@@ -669,6 +685,14 @@ function getGeneratedOutputWithContentPolicyHandling(response) {
|
|
|
669
685
|
const reason = rawReason.success && isContentPolicyReason(rawReason.data) ? rawReason.data : "CONTENT_FILTER";
|
|
670
686
|
throwContentPolicyError({ reason }, getErrorTokenUsage(response));
|
|
671
687
|
}
|
|
688
|
+
if (response.finishReason !== "stop") {
|
|
689
|
+
const rawReason = PolicyTokenSchema.safeParse(response.rawFinishReason);
|
|
690
|
+
throw new IncompleteGenerationError(
|
|
691
|
+
response.finishReason,
|
|
692
|
+
rawReason.success ? rawReason.data : void 0,
|
|
693
|
+
getErrorTokenUsage(response)
|
|
694
|
+
);
|
|
695
|
+
}
|
|
672
696
|
return response.output;
|
|
673
697
|
}
|
|
674
698
|
function throwContentPolicyError(block, usage) {
|
|
@@ -6914,19 +6938,41 @@ async function requestStaticRenditionCreation(assetId, credentials) {
|
|
|
6914
6938
|
const muxClient = await resolveMuxClient(credentials);
|
|
6915
6939
|
const mux = await muxClient.createClient();
|
|
6916
6940
|
try {
|
|
6917
|
-
await mux.video.assets.createStaticRendition(assetId, {
|
|
6941
|
+
const rendition = await mux.video.assets.createStaticRendition(assetId, {
|
|
6918
6942
|
resolution: "audio-only"
|
|
6919
6943
|
});
|
|
6944
|
+
return rendition.id;
|
|
6920
6945
|
} catch (error) {
|
|
6921
6946
|
const statusCode = error?.status ?? error?.statusCode;
|
|
6922
6947
|
const messages = error?.error?.messages;
|
|
6923
6948
|
const alreadyDefined = messages?.some((message) => message.toLowerCase().includes("already defined")) ?? error?.message?.toLowerCase().includes("already defined");
|
|
6924
6949
|
if (statusCode === 409 || alreadyDefined) {
|
|
6925
|
-
return;
|
|
6950
|
+
return void 0;
|
|
6926
6951
|
}
|
|
6927
6952
|
wrapError(error, "Failed to request static rendition from Mux");
|
|
6928
6953
|
}
|
|
6929
6954
|
}
|
|
6955
|
+
async function deleteCreatedStaticRendition(assetId, staticRenditionId, credentials) {
|
|
6956
|
+
"use step";
|
|
6957
|
+
try {
|
|
6958
|
+
const muxClient = await resolveMuxClient(credentials);
|
|
6959
|
+
const mux = await muxClient.createClient();
|
|
6960
|
+
await mux.video.assets.deleteStaticRendition(assetId, staticRenditionId);
|
|
6961
|
+
console.warn(`\u{1F9F9} Deleted static rendition ${staticRenditionId} created on asset ${assetId}`);
|
|
6962
|
+
return "deleted";
|
|
6963
|
+
} catch (error) {
|
|
6964
|
+
const statusCode = error?.status ?? error?.statusCode;
|
|
6965
|
+
if (statusCode === 404) {
|
|
6966
|
+
console.warn(`\u{1F9F9} Static rendition ${staticRenditionId} on asset ${assetId} was already deleted`);
|
|
6967
|
+
return "deleted";
|
|
6968
|
+
}
|
|
6969
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6970
|
+
console.warn(
|
|
6971
|
+
`\u26A0\uFE0F Failed to delete static rendition ${staticRenditionId} on asset ${assetId} (status: ${statusCode ?? "unknown"}): ${message}`
|
|
6972
|
+
);
|
|
6973
|
+
return "delete_failed";
|
|
6974
|
+
}
|
|
6975
|
+
}
|
|
6930
6976
|
async function retrieveAsset(assetId, credentials) {
|
|
6931
6977
|
"use step";
|
|
6932
6978
|
const muxClient = await resolveMuxClient(credentials);
|
|
@@ -6942,14 +6988,6 @@ async function waitForAudioStaticRendition({
|
|
|
6942
6988
|
if (hasReadyAudioStaticRendition(currentAsset)) {
|
|
6943
6989
|
return currentAsset;
|
|
6944
6990
|
}
|
|
6945
|
-
const status = currentAsset.static_renditions?.status ?? "not_requested";
|
|
6946
|
-
if (status === "not_requested" || status === void 0) {
|
|
6947
|
-
await requestStaticRenditionCreation(assetId, credentials);
|
|
6948
|
-
} else if (status === "errored") {
|
|
6949
|
-
await requestStaticRenditionCreation(assetId, credentials);
|
|
6950
|
-
} else {
|
|
6951
|
-
console.warn(`\u2139\uFE0F Static rendition already ${status}. Waiting for it to finish...`);
|
|
6952
|
-
}
|
|
6953
6991
|
for (let attempt = 1; attempt <= STATIC_RENDITION_MAX_ATTEMPTS; attempt++) {
|
|
6954
6992
|
await sleep(STATIC_RENDITION_POLL_INTERVAL_MS);
|
|
6955
6993
|
currentAsset = await retrieveAsset(assetId, credentials);
|
|
@@ -7156,6 +7194,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7156
7194
|
uploadToS3: uploadToS3Option,
|
|
7157
7195
|
uploadToMux: uploadToMuxOption,
|
|
7158
7196
|
uploadCaptionsToMux = false,
|
|
7197
|
+
staticRenditionCleanup: staticRenditionCleanupOption = "delete",
|
|
7159
7198
|
storageAdapter,
|
|
7160
7199
|
credentials: providedCredentials
|
|
7161
7200
|
} = options;
|
|
@@ -7177,144 +7216,167 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7177
7216
|
const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
7178
7217
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(initialAsset);
|
|
7179
7218
|
let currentAsset = initialAsset;
|
|
7219
|
+
let createdStaticRenditionId;
|
|
7180
7220
|
if (!hasReadyAudioStaticRendition(currentAsset)) {
|
|
7181
7221
|
console.warn("\u274C No ready audio static rendition found. Requesting one now...");
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
const audioRendition = getReadyAudioStaticRendition(currentAsset);
|
|
7189
|
-
if (!audioRendition) {
|
|
7190
|
-
throw new MuxAiError(
|
|
7191
|
-
"Unable to obtain an audio-only static rendition for this asset. Please verify static renditions are enabled in Mux.",
|
|
7192
|
-
{ type: "validation_error" }
|
|
7193
|
-
);
|
|
7194
|
-
}
|
|
7195
|
-
let audioUrl = `${getMuxStreamOrigin()}/${playbackId}/audio.m4a`;
|
|
7196
|
-
if (policy === "signed") {
|
|
7197
|
-
audioUrl = await signUrl(audioUrl, playbackId, "video", void 0, credentials);
|
|
7222
|
+
const renditionStatus = currentAsset.static_renditions?.status ?? "not_requested";
|
|
7223
|
+
if (renditionStatus === "not_requested" || renditionStatus === "errored") {
|
|
7224
|
+
createdStaticRenditionId = await requestStaticRenditionCreation(assetId, credentials);
|
|
7225
|
+
} else {
|
|
7226
|
+
console.warn(`\u2139\uFE0F Static rendition already ${renditionStatus}. Waiting for it to finish...`);
|
|
7227
|
+
}
|
|
7198
7228
|
}
|
|
7199
|
-
|
|
7200
|
-
const elevenLabsLangCode = toISO639_3(toLanguageCode);
|
|
7201
|
-
const normalizedFromLanguageCode = fromLanguageCode?.trim();
|
|
7202
|
-
const elevenLabsSourceLangCode = normalizedFromLanguageCode ? toISO639_3(normalizedFromLanguageCode) : void 0;
|
|
7203
|
-
console.warn(
|
|
7204
|
-
`\u{1F50D} Creating dubbing job for asset ${assetId}: ${elevenLabsSourceLangCode ?? "auto"} -> ${elevenLabsLangCode}`
|
|
7205
|
-
);
|
|
7229
|
+
let staticRenditionCleanup = "not_created";
|
|
7206
7230
|
let dubbingId;
|
|
7231
|
+
let presignedUrl;
|
|
7232
|
+
let uploadedTrackId;
|
|
7233
|
+
let captionsPresignedUrl;
|
|
7234
|
+
let captionsTrackId;
|
|
7207
7235
|
try {
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
elevenLabsSourceLangCode,
|
|
7213
|
-
numSpeakers,
|
|
7214
|
-
credentials
|
|
7215
|
-
});
|
|
7216
|
-
console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
|
|
7217
|
-
} catch (error) {
|
|
7218
|
-
wrapError(error, "Failed to create ElevenLabs dubbing job");
|
|
7219
|
-
}
|
|
7220
|
-
console.warn("\u23F3 Waiting for dubbing to complete...");
|
|
7221
|
-
const dubbingPollTimeoutSeconds = options.dubbingPollTimeoutSeconds ?? DEFAULT_DUBBING_POLL_TIMEOUT_SECONDS;
|
|
7222
|
-
const maxPollAttempts = Math.max(1, Math.ceil(dubbingPollTimeoutSeconds * 1e3 / DUBBING_POLL_INTERVAL_MS));
|
|
7223
|
-
let dubbingStatus = "dubbing";
|
|
7224
|
-
let pollAttempts = 0;
|
|
7225
|
-
let targetLanguages = [];
|
|
7226
|
-
while (dubbingStatus !== "dubbed" && pollAttempts < maxPollAttempts) {
|
|
7227
|
-
await sleep(DUBBING_POLL_INTERVAL_MS);
|
|
7228
|
-
pollAttempts++;
|
|
7229
|
-
try {
|
|
7230
|
-
const statusResult = await checkElevenLabsDubbingStatus({
|
|
7231
|
-
dubbingId,
|
|
7236
|
+
if (!hasReadyAudioStaticRendition(currentAsset)) {
|
|
7237
|
+
currentAsset = await waitForAudioStaticRendition({
|
|
7238
|
+
assetId,
|
|
7239
|
+
initialAsset: currentAsset,
|
|
7232
7240
|
credentials
|
|
7233
7241
|
});
|
|
7234
|
-
dubbingStatus = statusResult.status;
|
|
7235
|
-
targetLanguages = statusResult.targetLanguages;
|
|
7236
|
-
} catch (error) {
|
|
7237
|
-
wrapError(error, "Failed to check dubbing status");
|
|
7238
7242
|
}
|
|
7239
|
-
|
|
7240
|
-
|
|
7243
|
+
const audioRendition = getReadyAudioStaticRendition(currentAsset);
|
|
7244
|
+
if (!audioRendition) {
|
|
7245
|
+
throw new MuxAiError(
|
|
7246
|
+
"Unable to obtain an audio-only static rendition for this asset. Please verify static renditions are enabled in Mux.",
|
|
7247
|
+
{ type: "validation_error" }
|
|
7248
|
+
);
|
|
7241
7249
|
}
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
|
|
7250
|
+
let audioUrl = `${getMuxStreamOrigin()}/${playbackId}/audio.m4a`;
|
|
7251
|
+
if (policy === "signed") {
|
|
7252
|
+
audioUrl = await signUrl(audioUrl, playbackId, "video", void 0, credentials);
|
|
7253
|
+
}
|
|
7254
|
+
console.warn("\u{1F399}\uFE0F Creating dubbing job in ElevenLabs...");
|
|
7255
|
+
const elevenLabsLangCode = toISO639_3(toLanguageCode);
|
|
7256
|
+
const normalizedFromLanguageCode = fromLanguageCode?.trim();
|
|
7257
|
+
const elevenLabsSourceLangCode = normalizedFromLanguageCode ? toISO639_3(normalizedFromLanguageCode) : void 0;
|
|
7258
|
+
console.warn(
|
|
7259
|
+
`\u{1F50D} Creating dubbing job for asset ${assetId}: ${elevenLabsSourceLangCode ?? "auto"} -> ${elevenLabsLangCode}`
|
|
7260
|
+
);
|
|
7254
7261
|
try {
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
languageCode: downloadLangCode,
|
|
7262
|
+
dubbingId = await createElevenLabsDubbingJob({
|
|
7263
|
+
sourceUrl: audioUrl,
|
|
7258
7264
|
assetId,
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
s3Bucket,
|
|
7263
|
-
storageAdapter: effectiveStorageAdapter,
|
|
7264
|
-
s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
|
|
7265
|
+
elevenLabsLangCode,
|
|
7266
|
+
elevenLabsSourceLangCode,
|
|
7267
|
+
numSpeakers,
|
|
7265
7268
|
credentials
|
|
7266
7269
|
});
|
|
7267
|
-
console.warn(
|
|
7270
|
+
console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
|
|
7268
7271
|
} catch (error) {
|
|
7269
|
-
wrapError(error, "Failed to
|
|
7270
|
-
}
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7272
|
+
wrapError(error, "Failed to create ElevenLabs dubbing job");
|
|
7273
|
+
}
|
|
7274
|
+
console.warn("\u23F3 Waiting for dubbing to complete...");
|
|
7275
|
+
const dubbingPollTimeoutSeconds = options.dubbingPollTimeoutSeconds ?? DEFAULT_DUBBING_POLL_TIMEOUT_SECONDS;
|
|
7276
|
+
const maxPollAttempts = Math.max(1, Math.ceil(dubbingPollTimeoutSeconds * 1e3 / DUBBING_POLL_INTERVAL_MS));
|
|
7277
|
+
let dubbingStatus = "dubbing";
|
|
7278
|
+
let pollAttempts = 0;
|
|
7279
|
+
let targetLanguages = [];
|
|
7280
|
+
while (dubbingStatus !== "dubbed" && pollAttempts < maxPollAttempts) {
|
|
7281
|
+
await sleep(DUBBING_POLL_INTERVAL_MS);
|
|
7282
|
+
pollAttempts++;
|
|
7274
7283
|
try {
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7284
|
+
const statusResult = await checkElevenLabsDubbingStatus({
|
|
7285
|
+
dubbingId,
|
|
7286
|
+
credentials
|
|
7287
|
+
});
|
|
7288
|
+
dubbingStatus = statusResult.status;
|
|
7289
|
+
targetLanguages = statusResult.targetLanguages;
|
|
7280
7290
|
} catch (error) {
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7291
|
+
wrapError(error, "Failed to check dubbing status");
|
|
7292
|
+
}
|
|
7293
|
+
if (dubbingStatus === "failed") {
|
|
7294
|
+
throw new MuxAiError("ElevenLabs reported that the dubbing job failed.", { type: "processing_error" });
|
|
7284
7295
|
}
|
|
7285
7296
|
}
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7297
|
+
if (dubbingStatus !== "dubbed") {
|
|
7298
|
+
throw new MuxAiError("Audio translation timed out or failed. Please try again.", { type: "timeout_error", retryable: true });
|
|
7299
|
+
}
|
|
7300
|
+
console.warn("\u2705 Dubbing completed successfully!");
|
|
7301
|
+
if (uploadToS3) {
|
|
7302
|
+
console.warn("\u{1F4E5} Downloading dubbed audio from ElevenLabs and staging to S3...");
|
|
7303
|
+
const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
|
|
7304
|
+
try {
|
|
7305
|
+
presignedUrl = await downloadAndUploadDubbedAudio({
|
|
7306
|
+
dubbingId,
|
|
7307
|
+
languageCode: downloadLangCode,
|
|
7308
|
+
assetId,
|
|
7309
|
+
toLanguageCode,
|
|
7310
|
+
s3Endpoint,
|
|
7311
|
+
s3Region,
|
|
7312
|
+
s3Bucket,
|
|
7313
|
+
storageAdapter: effectiveStorageAdapter,
|
|
7314
|
+
s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
|
|
7315
|
+
credentials
|
|
7316
|
+
});
|
|
7317
|
+
console.warn("\u2705 Dubbed audio staged to S3 successfully!");
|
|
7318
|
+
} catch (error) {
|
|
7319
|
+
wrapError(error, "Failed to download and upload dubbed audio");
|
|
7320
|
+
}
|
|
7321
|
+
if (uploadToMux) {
|
|
7322
|
+
console.warn("\u{1F4F9} Adding dubbed audio track to Mux asset...");
|
|
7302
7323
|
const muxLangCode = toISO639_1(toLanguageCode);
|
|
7303
|
-
|
|
7304
|
-
|
|
7324
|
+
try {
|
|
7325
|
+
uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl, credentials);
|
|
7326
|
+
const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
|
|
7327
|
+
const trackName = `${languageName} (auto-dubbed)`;
|
|
7328
|
+
console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
|
|
7329
|
+
console.warn(`\u{1F4CB} Track name: "${trackName}"`);
|
|
7330
|
+
} catch (error) {
|
|
7331
|
+
console.warn(`\u26A0\uFE0F Failed to add audio track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
7332
|
+
console.warn("\u{1F517} You can manually add the track using this presigned URL:");
|
|
7333
|
+
console.warn(presignedUrl);
|
|
7334
|
+
}
|
|
7335
|
+
}
|
|
7336
|
+
try {
|
|
7337
|
+
console.warn("\u{1F4E5} Downloading dub transcript from ElevenLabs and staging to S3...");
|
|
7338
|
+
captionsPresignedUrl = await downloadAndUploadDubTranscript({
|
|
7339
|
+
dubbingId,
|
|
7340
|
+
languageCode: downloadLangCode,
|
|
7305
7341
|
assetId,
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7342
|
+
toLanguageCode,
|
|
7343
|
+
s3Endpoint,
|
|
7344
|
+
s3Region,
|
|
7345
|
+
s3Bucket,
|
|
7346
|
+
storageAdapter: effectiveStorageAdapter,
|
|
7347
|
+
s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
|
|
7309
7348
|
credentials
|
|
7310
|
-
);
|
|
7311
|
-
|
|
7349
|
+
});
|
|
7350
|
+
if (uploadCaptionsToMux) {
|
|
7351
|
+
console.warn("\u{1F4F9} Adding dubbed captions track to Mux asset...");
|
|
7352
|
+
const muxLangCode = toISO639_1(toLanguageCode);
|
|
7353
|
+
const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
|
|
7354
|
+
captionsTrackId = await createTextTrackOnMux(
|
|
7355
|
+
assetId,
|
|
7356
|
+
muxLangCode,
|
|
7357
|
+
`${languageName} (auto-dubbed)`,
|
|
7358
|
+
captionsPresignedUrl,
|
|
7359
|
+
credentials
|
|
7360
|
+
);
|
|
7361
|
+
console.warn(`\u2705 Captions track added to Mux asset with ID: ${captionsTrackId}`);
|
|
7362
|
+
}
|
|
7363
|
+
} catch (error) {
|
|
7364
|
+
console.warn(`\u26A0\uFE0F Failed to attach dubbed captions: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
7365
|
+
if (captionsPresignedUrl) {
|
|
7366
|
+
console.warn("\u{1F517} You can manually add the captions track using this presigned URL:");
|
|
7367
|
+
console.warn(captionsPresignedUrl);
|
|
7368
|
+
}
|
|
7312
7369
|
}
|
|
7313
|
-
}
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
console.warn(
|
|
7370
|
+
}
|
|
7371
|
+
} finally {
|
|
7372
|
+
if (createdStaticRenditionId) {
|
|
7373
|
+
if (staticRenditionCleanupOption === "keep") {
|
|
7374
|
+
console.warn(
|
|
7375
|
+
`\u2139\uFE0F Keeping static rendition ${createdStaticRenditionId} on asset ${assetId} (staticRenditionCleanup: "keep")`
|
|
7376
|
+
);
|
|
7377
|
+
staticRenditionCleanup = "kept";
|
|
7378
|
+
} else {
|
|
7379
|
+
staticRenditionCleanup = await deleteCreatedStaticRendition(assetId, createdStaticRenditionId, credentials);
|
|
7318
7380
|
}
|
|
7319
7381
|
}
|
|
7320
7382
|
}
|
|
@@ -7328,6 +7390,8 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7328
7390
|
presignedUrl,
|
|
7329
7391
|
captionsTrackId,
|
|
7330
7392
|
captionsPresignedUrl,
|
|
7393
|
+
createdStaticRenditionId,
|
|
7394
|
+
staticRenditionCleanup,
|
|
7331
7395
|
usage: {
|
|
7332
7396
|
metadata: {
|
|
7333
7397
|
assetDurationSeconds
|
|
@@ -7341,6 +7405,7 @@ import {
|
|
|
7341
7405
|
APICallError as APICallError3,
|
|
7342
7406
|
generateText as generateText7,
|
|
7343
7407
|
NoObjectGeneratedError as NoObjectGeneratedError2,
|
|
7408
|
+
NoOutputGeneratedError as NoOutputGeneratedError2,
|
|
7344
7409
|
Output as Output7,
|
|
7345
7410
|
RetryError as RetryError2,
|
|
7346
7411
|
TypeValidationError
|
|
@@ -7504,7 +7569,7 @@ function shouldSplitChunkTranslationError(error) {
|
|
|
7504
7569
|
if (isProviderServiceError(error)) {
|
|
7505
7570
|
return false;
|
|
7506
7571
|
}
|
|
7507
|
-
return NoObjectGeneratedError2.isInstance(error) || TypeValidationError.isInstance(error) || isTranslationChunkValidationError(error);
|
|
7572
|
+
return NoObjectGeneratedError2.isInstance(error) || NoOutputGeneratedError2.isInstance(error) || TypeValidationError.isInstance(error) || isIncompleteGenerationError(error) || isTranslationChunkValidationError(error);
|
|
7508
7573
|
}
|
|
7509
7574
|
function resolveTranslationChunkingOptions(options) {
|
|
7510
7575
|
const targetChunkDurationSeconds = Math.max(
|
|
@@ -7601,9 +7666,13 @@ function buildTranslationChunkRequests(vttContent, assetDurationSeconds, chunkin
|
|
|
7601
7666
|
if (typeof assetDurationSeconds !== "number" || assetDurationSeconds < resolvedChunking.minimumAssetDurationSeconds) {
|
|
7602
7667
|
return {
|
|
7603
7668
|
preamble,
|
|
7604
|
-
chunks:
|
|
7605
|
-
|
|
7606
|
-
|
|
7669
|
+
chunks: splitTranslationChunkRequestByBudget(
|
|
7670
|
+
"chunk-0",
|
|
7671
|
+
cues,
|
|
7672
|
+
cueBlocks,
|
|
7673
|
+
resolvedChunking.maxCuesPerChunk,
|
|
7674
|
+
resolvedChunking.maxCueTextTokensPerChunk
|
|
7675
|
+
)
|
|
7607
7676
|
};
|
|
7608
7677
|
}
|
|
7609
7678
|
const targetChunkDurationSeconds = resolvedChunking.targetChunkDurationSeconds;
|
|
@@ -7864,7 +7933,11 @@ async function translateChunkWithFallback({
|
|
|
7864
7933
|
);
|
|
7865
7934
|
return {
|
|
7866
7935
|
translatedVtt: concatenateVttSegments([leftResult.translatedVtt, rightResult.translatedVtt]),
|
|
7867
|
-
usage: aggregateTokenUsage([
|
|
7936
|
+
usage: aggregateTokenUsage([
|
|
7937
|
+
...failedAttemptUsage ? [failedAttemptUsage] : [],
|
|
7938
|
+
leftResult.usage,
|
|
7939
|
+
rightResult.usage
|
|
7940
|
+
]),
|
|
7868
7941
|
scrubbedCueCounts: mergeScrubbedCueCounts(
|
|
7869
7942
|
leftResult.scrubbedCueCounts,
|
|
7870
7943
|
rightResult.scrubbedCueCounts
|