@mux/ai 0.33.0 → 0.34.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.
@@ -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 SummarizationOptions, a7 as SummarizationPromptOverrides, a8 as SummarizationPromptSections, a9 as SummaryAndTagsResult, aa as SummaryType, ab as ThumbnailModerationScore, ac as TranslationChunkingOptions, ad as TranslationOptions, ae as TranslationPayload, af as TranslationResult, ag as aggregateTokenUsage, ah as applyOverrideLists, ai as applyReplacements, aj as askQuestions, ak as buildReplacementRegex, al as burnedInCaptionsSchema, am as censorVttContent, an as chapterSchema, ao as chaptersSchema, ap as createReplacer, aq as editCaptions, ar as extractTranscriptSegmentsForHotspots, as as generateChapters, at as generateEmbeddings, au as generateEngagementInsights, av as generateVideoEmbeddings, aw as getModerationScores, ax as getSummaryAndTags, ay as hasBurnedInCaptions, az as mapShotsToHotspots, aA as normalizeTranslatedVtt, aB as profanityDetectionSchema, aC as questionAnswerSchema, aD as shouldSplitChunkTranslationError, aE as summarySchema, aF as transformCueText, aG as translateAudio, aH as translateCaptions, aI as translationSchema, aJ as validateNeverTranslateTerms, aK as verifyNeverTranslateTerms } from '../index-Chccb380.js';
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-B5l0yXZD.js';
2
2
  import 'zod';
3
3
  import '@ai-sdk/anthropic';
4
4
  import '@ai-sdk/google';
@@ -6914,19 +6914,41 @@ async function requestStaticRenditionCreation(assetId, credentials) {
6914
6914
  const muxClient = await resolveMuxClient(credentials);
6915
6915
  const mux = await muxClient.createClient();
6916
6916
  try {
6917
- await mux.video.assets.createStaticRendition(assetId, {
6917
+ const rendition = await mux.video.assets.createStaticRendition(assetId, {
6918
6918
  resolution: "audio-only"
6919
6919
  });
6920
+ return rendition.id;
6920
6921
  } catch (error) {
6921
6922
  const statusCode = error?.status ?? error?.statusCode;
6922
6923
  const messages = error?.error?.messages;
6923
6924
  const alreadyDefined = messages?.some((message) => message.toLowerCase().includes("already defined")) ?? error?.message?.toLowerCase().includes("already defined");
6924
6925
  if (statusCode === 409 || alreadyDefined) {
6925
- return;
6926
+ return void 0;
6926
6927
  }
6927
6928
  wrapError(error, "Failed to request static rendition from Mux");
6928
6929
  }
6929
6930
  }
6931
+ async function deleteCreatedStaticRendition(assetId, staticRenditionId, credentials) {
6932
+ "use step";
6933
+ try {
6934
+ const muxClient = await resolveMuxClient(credentials);
6935
+ const mux = await muxClient.createClient();
6936
+ await mux.video.assets.deleteStaticRendition(assetId, staticRenditionId);
6937
+ console.warn(`\u{1F9F9} Deleted static rendition ${staticRenditionId} created on asset ${assetId}`);
6938
+ return "deleted";
6939
+ } catch (error) {
6940
+ const statusCode = error?.status ?? error?.statusCode;
6941
+ if (statusCode === 404) {
6942
+ console.warn(`\u{1F9F9} Static rendition ${staticRenditionId} on asset ${assetId} was already deleted`);
6943
+ return "deleted";
6944
+ }
6945
+ const message = error instanceof Error ? error.message : String(error);
6946
+ console.warn(
6947
+ `\u26A0\uFE0F Failed to delete static rendition ${staticRenditionId} on asset ${assetId} (status: ${statusCode ?? "unknown"}): ${message}`
6948
+ );
6949
+ return "delete_failed";
6950
+ }
6951
+ }
6930
6952
  async function retrieveAsset(assetId, credentials) {
6931
6953
  "use step";
6932
6954
  const muxClient = await resolveMuxClient(credentials);
@@ -6942,14 +6964,6 @@ async function waitForAudioStaticRendition({
6942
6964
  if (hasReadyAudioStaticRendition(currentAsset)) {
6943
6965
  return currentAsset;
6944
6966
  }
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
6967
  for (let attempt = 1; attempt <= STATIC_RENDITION_MAX_ATTEMPTS; attempt++) {
6954
6968
  await sleep(STATIC_RENDITION_POLL_INTERVAL_MS);
6955
6969
  currentAsset = await retrieveAsset(assetId, credentials);
@@ -7156,6 +7170,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7156
7170
  uploadToS3: uploadToS3Option,
7157
7171
  uploadToMux: uploadToMuxOption,
7158
7172
  uploadCaptionsToMux = false,
7173
+ staticRenditionCleanup: staticRenditionCleanupOption = "delete",
7159
7174
  storageAdapter,
7160
7175
  credentials: providedCredentials
7161
7176
  } = options;
@@ -7177,144 +7192,167 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7177
7192
  const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
7178
7193
  const assetDurationSeconds = getAssetDurationSecondsFromAsset(initialAsset);
7179
7194
  let currentAsset = initialAsset;
7195
+ let createdStaticRenditionId;
7180
7196
  if (!hasReadyAudioStaticRendition(currentAsset)) {
7181
7197
  console.warn("\u274C No ready audio static rendition found. Requesting one now...");
7182
- currentAsset = await waitForAudioStaticRendition({
7183
- assetId,
7184
- initialAsset: currentAsset,
7185
- credentials
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);
7198
+ const renditionStatus = currentAsset.static_renditions?.status ?? "not_requested";
7199
+ if (renditionStatus === "not_requested" || renditionStatus === "errored") {
7200
+ createdStaticRenditionId = await requestStaticRenditionCreation(assetId, credentials);
7201
+ } else {
7202
+ console.warn(`\u2139\uFE0F Static rendition already ${renditionStatus}. Waiting for it to finish...`);
7203
+ }
7198
7204
  }
7199
- console.warn("\u{1F399}\uFE0F Creating dubbing job in ElevenLabs...");
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
- );
7205
+ let staticRenditionCleanup = "not_created";
7206
7206
  let dubbingId;
7207
+ let presignedUrl;
7208
+ let uploadedTrackId;
7209
+ let captionsPresignedUrl;
7210
+ let captionsTrackId;
7207
7211
  try {
7208
- dubbingId = await createElevenLabsDubbingJob({
7209
- sourceUrl: audioUrl,
7210
- assetId,
7211
- elevenLabsLangCode,
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,
7212
+ if (!hasReadyAudioStaticRendition(currentAsset)) {
7213
+ currentAsset = await waitForAudioStaticRendition({
7214
+ assetId,
7215
+ initialAsset: currentAsset,
7232
7216
  credentials
7233
7217
  });
7234
- dubbingStatus = statusResult.status;
7235
- targetLanguages = statusResult.targetLanguages;
7236
- } catch (error) {
7237
- wrapError(error, "Failed to check dubbing status");
7238
7218
  }
7239
- if (dubbingStatus === "failed") {
7240
- throw new MuxAiError("ElevenLabs reported that the dubbing job failed.", { type: "processing_error" });
7219
+ const audioRendition = getReadyAudioStaticRendition(currentAsset);
7220
+ if (!audioRendition) {
7221
+ throw new MuxAiError(
7222
+ "Unable to obtain an audio-only static rendition for this asset. Please verify static renditions are enabled in Mux.",
7223
+ { type: "validation_error" }
7224
+ );
7241
7225
  }
7242
- }
7243
- if (dubbingStatus !== "dubbed") {
7244
- throw new MuxAiError("Audio translation timed out or failed. Please try again.", { type: "timeout_error", retryable: true });
7245
- }
7246
- console.warn("\u2705 Dubbing completed successfully!");
7247
- let presignedUrl;
7248
- let uploadedTrackId;
7249
- let captionsPresignedUrl;
7250
- let captionsTrackId;
7251
- if (uploadToS3) {
7252
- console.warn("\u{1F4E5} Downloading dubbed audio from ElevenLabs and staging to S3...");
7253
- const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
7226
+ let audioUrl = `${getMuxStreamOrigin()}/${playbackId}/audio.m4a`;
7227
+ if (policy === "signed") {
7228
+ audioUrl = await signUrl(audioUrl, playbackId, "video", void 0, credentials);
7229
+ }
7230
+ console.warn("\u{1F399}\uFE0F Creating dubbing job in ElevenLabs...");
7231
+ const elevenLabsLangCode = toISO639_3(toLanguageCode);
7232
+ const normalizedFromLanguageCode = fromLanguageCode?.trim();
7233
+ const elevenLabsSourceLangCode = normalizedFromLanguageCode ? toISO639_3(normalizedFromLanguageCode) : void 0;
7234
+ console.warn(
7235
+ `\u{1F50D} Creating dubbing job for asset ${assetId}: ${elevenLabsSourceLangCode ?? "auto"} -> ${elevenLabsLangCode}`
7236
+ );
7254
7237
  try {
7255
- presignedUrl = await downloadAndUploadDubbedAudio({
7256
- dubbingId,
7257
- languageCode: downloadLangCode,
7238
+ dubbingId = await createElevenLabsDubbingJob({
7239
+ sourceUrl: audioUrl,
7258
7240
  assetId,
7259
- toLanguageCode,
7260
- s3Endpoint,
7261
- s3Region,
7262
- s3Bucket,
7263
- storageAdapter: effectiveStorageAdapter,
7264
- s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7241
+ elevenLabsLangCode,
7242
+ elevenLabsSourceLangCode,
7243
+ numSpeakers,
7265
7244
  credentials
7266
7245
  });
7267
- console.warn("\u2705 Dubbed audio staged to S3 successfully!");
7246
+ console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
7268
7247
  } catch (error) {
7269
- wrapError(error, "Failed to download and upload dubbed audio");
7270
- }
7271
- if (uploadToMux) {
7272
- console.warn("\u{1F4F9} Adding dubbed audio track to Mux asset...");
7273
- const muxLangCode = toISO639_1(toLanguageCode);
7248
+ wrapError(error, "Failed to create ElevenLabs dubbing job");
7249
+ }
7250
+ console.warn("\u23F3 Waiting for dubbing to complete...");
7251
+ const dubbingPollTimeoutSeconds = options.dubbingPollTimeoutSeconds ?? DEFAULT_DUBBING_POLL_TIMEOUT_SECONDS;
7252
+ const maxPollAttempts = Math.max(1, Math.ceil(dubbingPollTimeoutSeconds * 1e3 / DUBBING_POLL_INTERVAL_MS));
7253
+ let dubbingStatus = "dubbing";
7254
+ let pollAttempts = 0;
7255
+ let targetLanguages = [];
7256
+ while (dubbingStatus !== "dubbed" && pollAttempts < maxPollAttempts) {
7257
+ await sleep(DUBBING_POLL_INTERVAL_MS);
7258
+ pollAttempts++;
7274
7259
  try {
7275
- uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl, credentials);
7276
- const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7277
- const trackName = `${languageName} (auto-dubbed)`;
7278
- console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
7279
- console.warn(`\u{1F4CB} Track name: "${trackName}"`);
7260
+ const statusResult = await checkElevenLabsDubbingStatus({
7261
+ dubbingId,
7262
+ credentials
7263
+ });
7264
+ dubbingStatus = statusResult.status;
7265
+ targetLanguages = statusResult.targetLanguages;
7280
7266
  } catch (error) {
7281
- console.warn(`\u26A0\uFE0F Failed to add audio track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
7282
- console.warn("\u{1F517} You can manually add the track using this presigned URL:");
7283
- console.warn(presignedUrl);
7267
+ wrapError(error, "Failed to check dubbing status");
7268
+ }
7269
+ if (dubbingStatus === "failed") {
7270
+ throw new MuxAiError("ElevenLabs reported that the dubbing job failed.", { type: "processing_error" });
7284
7271
  }
7285
7272
  }
7286
- try {
7287
- console.warn("\u{1F4E5} Downloading dub transcript from ElevenLabs and staging to S3...");
7288
- captionsPresignedUrl = await downloadAndUploadDubTranscript({
7289
- dubbingId,
7290
- languageCode: downloadLangCode,
7291
- assetId,
7292
- toLanguageCode,
7293
- s3Endpoint,
7294
- s3Region,
7295
- s3Bucket,
7296
- storageAdapter: effectiveStorageAdapter,
7297
- s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7298
- credentials
7299
- });
7300
- if (uploadCaptionsToMux) {
7301
- console.warn("\u{1F4F9} Adding dubbed captions track to Mux asset...");
7273
+ if (dubbingStatus !== "dubbed") {
7274
+ throw new MuxAiError("Audio translation timed out or failed. Please try again.", { type: "timeout_error", retryable: true });
7275
+ }
7276
+ console.warn("\u2705 Dubbing completed successfully!");
7277
+ if (uploadToS3) {
7278
+ console.warn("\u{1F4E5} Downloading dubbed audio from ElevenLabs and staging to S3...");
7279
+ const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
7280
+ try {
7281
+ presignedUrl = await downloadAndUploadDubbedAudio({
7282
+ dubbingId,
7283
+ languageCode: downloadLangCode,
7284
+ assetId,
7285
+ toLanguageCode,
7286
+ s3Endpoint,
7287
+ s3Region,
7288
+ s3Bucket,
7289
+ storageAdapter: effectiveStorageAdapter,
7290
+ s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7291
+ credentials
7292
+ });
7293
+ console.warn("\u2705 Dubbed audio staged to S3 successfully!");
7294
+ } catch (error) {
7295
+ wrapError(error, "Failed to download and upload dubbed audio");
7296
+ }
7297
+ if (uploadToMux) {
7298
+ console.warn("\u{1F4F9} Adding dubbed audio track to Mux asset...");
7302
7299
  const muxLangCode = toISO639_1(toLanguageCode);
7303
- const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7304
- captionsTrackId = await createTextTrackOnMux(
7300
+ try {
7301
+ uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl, credentials);
7302
+ const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7303
+ const trackName = `${languageName} (auto-dubbed)`;
7304
+ console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
7305
+ console.warn(`\u{1F4CB} Track name: "${trackName}"`);
7306
+ } catch (error) {
7307
+ console.warn(`\u26A0\uFE0F Failed to add audio track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
7308
+ console.warn("\u{1F517} You can manually add the track using this presigned URL:");
7309
+ console.warn(presignedUrl);
7310
+ }
7311
+ }
7312
+ try {
7313
+ console.warn("\u{1F4E5} Downloading dub transcript from ElevenLabs and staging to S3...");
7314
+ captionsPresignedUrl = await downloadAndUploadDubTranscript({
7315
+ dubbingId,
7316
+ languageCode: downloadLangCode,
7305
7317
  assetId,
7306
- muxLangCode,
7307
- `${languageName} (auto-dubbed)`,
7308
- captionsPresignedUrl,
7318
+ toLanguageCode,
7319
+ s3Endpoint,
7320
+ s3Region,
7321
+ s3Bucket,
7322
+ storageAdapter: effectiveStorageAdapter,
7323
+ s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7309
7324
  credentials
7310
- );
7311
- console.warn(`\u2705 Captions track added to Mux asset with ID: ${captionsTrackId}`);
7325
+ });
7326
+ if (uploadCaptionsToMux) {
7327
+ console.warn("\u{1F4F9} Adding dubbed captions track to Mux asset...");
7328
+ const muxLangCode = toISO639_1(toLanguageCode);
7329
+ const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7330
+ captionsTrackId = await createTextTrackOnMux(
7331
+ assetId,
7332
+ muxLangCode,
7333
+ `${languageName} (auto-dubbed)`,
7334
+ captionsPresignedUrl,
7335
+ credentials
7336
+ );
7337
+ console.warn(`\u2705 Captions track added to Mux asset with ID: ${captionsTrackId}`);
7338
+ }
7339
+ } catch (error) {
7340
+ console.warn(`\u26A0\uFE0F Failed to attach dubbed captions: ${error instanceof Error ? error.message : "Unknown error"}`);
7341
+ if (captionsPresignedUrl) {
7342
+ console.warn("\u{1F517} You can manually add the captions track using this presigned URL:");
7343
+ console.warn(captionsPresignedUrl);
7344
+ }
7312
7345
  }
7313
- } catch (error) {
7314
- console.warn(`\u26A0\uFE0F Failed to attach dubbed captions: ${error instanceof Error ? error.message : "Unknown error"}`);
7315
- if (captionsPresignedUrl) {
7316
- console.warn("\u{1F517} You can manually add the captions track using this presigned URL:");
7317
- console.warn(captionsPresignedUrl);
7346
+ }
7347
+ } finally {
7348
+ if (createdStaticRenditionId) {
7349
+ if (staticRenditionCleanupOption === "keep") {
7350
+ console.warn(
7351
+ `\u2139\uFE0F Keeping static rendition ${createdStaticRenditionId} on asset ${assetId} (staticRenditionCleanup: "keep")`
7352
+ );
7353
+ staticRenditionCleanup = "kept";
7354
+ } else {
7355
+ staticRenditionCleanup = await deleteCreatedStaticRendition(assetId, createdStaticRenditionId, credentials);
7318
7356
  }
7319
7357
  }
7320
7358
  }
@@ -7328,6 +7366,8 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7328
7366
  presignedUrl,
7329
7367
  captionsTrackId,
7330
7368
  captionsPresignedUrl,
7369
+ createdStaticRenditionId,
7370
+ staticRenditionCleanup,
7331
7371
  usage: {
7332
7372
  metadata: {
7333
7373
  assetDurationSeconds