@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.
@@ -1246,6 +1246,8 @@ interface SummarizationOptions extends ScopedMuxAIOptions {
1246
1246
  }
1247
1247
  declare function getSummaryAndTags(assetId: string, options?: SummarizationOptions): Promise<SummaryAndTagsResult>;
1248
1248
 
1249
+ /** What happened to the audio-only static rendition `translateAudio` created as dubbing input. */
1250
+ type StaticRenditionCleanupOutcome = "deleted" | "delete_failed" | "kept" | "not_created";
1249
1251
  /** Output returned from `translateAudio`. */
1250
1252
  interface AudioTranslationResult {
1251
1253
  assetId: string;
@@ -1263,6 +1265,10 @@ interface AudioTranslationResult {
1263
1265
  captionsTrackId?: string;
1264
1266
  /** Presigned URL for the dub's translated transcript (WebVTT) staged to S3. */
1265
1267
  captionsPresignedUrl?: string;
1268
+ /** ID of the audio-only static rendition this run created, `undefined` when a usable rendition already existed. */
1269
+ createdStaticRenditionId?: string;
1270
+ /** Outcome of cleaning up the static rendition this run created (`not_created` when it reused an existing one). */
1271
+ staticRenditionCleanup: StaticRenditionCleanupOutcome;
1266
1272
  /** Workflow usage metadata (asset duration, thumbnails, etc.). */
1267
1273
  usage?: TokenUsage;
1268
1274
  }
@@ -1305,6 +1311,14 @@ interface AudioTranslationOptions extends MuxAIOptions {
1305
1311
  * text tracks — callers decide conflict semantics before enabling this.
1306
1312
  */
1307
1313
  uploadCaptionsToMux?: boolean;
1314
+ /**
1315
+ * Cleanup for the audio-only static rendition this run created as dubbing
1316
+ * input: `"delete"` (default) removes it when the workflow finishes, success
1317
+ * or failure; `"keep"` leaves it. A pre-existing rendition is never deleted.
1318
+ * Concurrent dubs of one asset share a rendition, so create it up front or
1319
+ * pass `"keep"` — one run's delete can race a peer's source fetch.
1320
+ */
1321
+ staticRenditionCleanup?: "delete" | "keep";
1308
1322
  /** Optional storage adapter override for upload + presign operations. */
1309
1323
  storageAdapter?: StorageAdapter;
1310
1324
  /** Expiry duration in seconds for S3 presigned GET URLs. Defaults to 86400 (24 hours). */
@@ -1528,6 +1542,7 @@ type index_Question = Question;
1528
1542
  type index_QuestionAnswer = QuestionAnswer;
1529
1543
  type index_QuestionAnswerType = QuestionAnswerType;
1530
1544
  type index_ReplacementRecord = ReplacementRecord;
1545
+ type index_StaticRenditionCleanupOutcome = StaticRenditionCleanupOutcome;
1531
1546
  type index_SummarizationOptions = SummarizationOptions;
1532
1547
  type index_SummarizationPromptOverrides = SummarizationPromptOverrides;
1533
1548
  type index_SummarizationPromptSections = SummarizationPromptSections;
@@ -1570,7 +1585,7 @@ declare const index_translationSchema: typeof translationSchema;
1570
1585
  declare const index_validateNeverTranslateTerms: typeof validateNeverTranslateTerms;
1571
1586
  declare const index_verifyNeverTranslateTerms: typeof verifyNeverTranslateTerms;
1572
1587
  declare namespace index {
1573
- export { index_ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, index_ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, index_ASK_QUESTIONS_MAX_QUESTION_LENGTH as ASK_QUESTIONS_MAX_QUESTION_LENGTH, type index_AskQuestionsOptions as AskQuestionsOptions, type index_AskQuestionsResult as AskQuestionsResult, type index_AskQuestionsType as AskQuestionsType, type index_AudioTranslationOptions as AudioTranslationOptions, type index_AudioTranslationResult as AudioTranslationResult, type index_AutoCensorProfanityOptions as AutoCensorProfanityOptions, type index_BurnedInCaptionsAnalysis as BurnedInCaptionsAnalysis, type index_BurnedInCaptionsOptions as BurnedInCaptionsOptions, type index_BurnedInCaptionsPromptOverrides as BurnedInCaptionsPromptOverrides, type index_BurnedInCaptionsPromptSections as BurnedInCaptionsPromptSections, type index_BurnedInCaptionsResult as BurnedInCaptionsResult, type index_CaptionReplacement as CaptionReplacement, type index_CensorMode as CensorMode, type index_Chapter as Chapter, type index_ChapterSystemPromptSections as ChapterSystemPromptSections, type index_ChaptersOptions as ChaptersOptions, type index_ChaptersPromptOverrides as ChaptersPromptOverrides, type index_ChaptersPromptSections as ChaptersPromptSections, type index_ChaptersResult as ChaptersResult, type index_ChaptersType as ChaptersType, index_DEFAULT_DESCRIPTION_LENGTH as DEFAULT_DESCRIPTION_LENGTH, index_DEFAULT_SUMMARY_KEYWORD_LIMIT as DEFAULT_SUMMARY_KEYWORD_LIMIT, index_DEFAULT_TITLE_LENGTH as DEFAULT_TITLE_LENGTH, type index_EditCaptionsOptions as EditCaptionsOptions, type index_EditCaptionsResult as EditCaptionsResult, type index_EmbeddingsOptions as EmbeddingsOptions, type index_EmbeddingsResult as EmbeddingsResult, type index_EngagementInsightsOptions as EngagementInsightsOptions, type index_EngagementInsightsResult as EngagementInsightsResult, index_GOOGLE_VISION_LIKELIHOOD_TO_SCORE as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, index_HIVE_SEXUAL_CATEGORIES as HIVE_SEXUAL_CATEGORIES, index_HIVE_VIOLENCE_CATEGORIES as HIVE_VIOLENCE_CATEGORIES, type index_HiveModerationOutput as HiveModerationOutput, type index_HiveModerationSource as HiveModerationSource, type index_ModerationOptions as ModerationOptions, type index_ModerationProvider as ModerationProvider, type index_ModerationResult as ModerationResult, type index_MomentInsight as MomentInsight, type index_OverallInsight as OverallInsight, type index_ProfanityDetectionPayload as ProfanityDetectionPayload, type index_Question as Question, type index_QuestionAnswer as QuestionAnswer, type index_QuestionAnswerType as QuestionAnswerType, type index_ReplacementRecord as ReplacementRecord, type index_SummarizationOptions as SummarizationOptions, type index_SummarizationPromptOverrides as SummarizationPromptOverrides, type index_SummarizationPromptSections as SummarizationPromptSections, type index_SummaryAndTagsResult as SummaryAndTagsResult, type index_SummaryType as SummaryType, type index_ThumbnailModerationScore as ThumbnailModerationScore, type index_TranslationChunkingOptions as TranslationChunkingOptions, type index_TranslationOptions as TranslationOptions, type index_TranslationPayload as TranslationPayload, type index_TranslationResult as TranslationResult, index_aggregateTokenUsage as aggregateTokenUsage, index_applyOverrideLists as applyOverrideLists, index_applyReplacements as applyReplacements, index_askQuestions as askQuestions, index_buildReplacementRegex as buildReplacementRegex, index_burnedInCaptionsSchema as burnedInCaptionsSchema, index_censorVttContent as censorVttContent, index_chapterSchema as chapterSchema, index_chaptersSchema as chaptersSchema, index_createReplacer as createReplacer, index_editCaptions as editCaptions, index_extractTranscriptSegmentsForHotspots as extractTranscriptSegmentsForHotspots, index_generateChapters as generateChapters, index_generateEmbeddings as generateEmbeddings, index_generateEngagementInsights as generateEngagementInsights, index_generateVideoEmbeddings as generateVideoEmbeddings, index_getModerationScores as getModerationScores, index_getSummaryAndTags as getSummaryAndTags, index_hasBurnedInCaptions as hasBurnedInCaptions, index_mapShotsToHotspots as mapShotsToHotspots, index_normalizeTranslatedVtt as normalizeTranslatedVtt, index_profanityDetectionSchema as profanityDetectionSchema, index_questionAnswerSchema as questionAnswerSchema, index_shouldSplitChunkTranslationError as shouldSplitChunkTranslationError, index_summarySchema as summarySchema, index_transformCueText as transformCueText, index_translateAudio as translateAudio, index_translateCaptions as translateCaptions, index_translationSchema as translationSchema, index_validateNeverTranslateTerms as validateNeverTranslateTerms, index_verifyNeverTranslateTerms as verifyNeverTranslateTerms };
1588
+ export { index_ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, index_ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, index_ASK_QUESTIONS_MAX_QUESTION_LENGTH as ASK_QUESTIONS_MAX_QUESTION_LENGTH, type index_AskQuestionsOptions as AskQuestionsOptions, type index_AskQuestionsResult as AskQuestionsResult, type index_AskQuestionsType as AskQuestionsType, type index_AudioTranslationOptions as AudioTranslationOptions, type index_AudioTranslationResult as AudioTranslationResult, type index_AutoCensorProfanityOptions as AutoCensorProfanityOptions, type index_BurnedInCaptionsAnalysis as BurnedInCaptionsAnalysis, type index_BurnedInCaptionsOptions as BurnedInCaptionsOptions, type index_BurnedInCaptionsPromptOverrides as BurnedInCaptionsPromptOverrides, type index_BurnedInCaptionsPromptSections as BurnedInCaptionsPromptSections, type index_BurnedInCaptionsResult as BurnedInCaptionsResult, type index_CaptionReplacement as CaptionReplacement, type index_CensorMode as CensorMode, type index_Chapter as Chapter, type index_ChapterSystemPromptSections as ChapterSystemPromptSections, type index_ChaptersOptions as ChaptersOptions, type index_ChaptersPromptOverrides as ChaptersPromptOverrides, type index_ChaptersPromptSections as ChaptersPromptSections, type index_ChaptersResult as ChaptersResult, type index_ChaptersType as ChaptersType, index_DEFAULT_DESCRIPTION_LENGTH as DEFAULT_DESCRIPTION_LENGTH, index_DEFAULT_SUMMARY_KEYWORD_LIMIT as DEFAULT_SUMMARY_KEYWORD_LIMIT, index_DEFAULT_TITLE_LENGTH as DEFAULT_TITLE_LENGTH, type index_EditCaptionsOptions as EditCaptionsOptions, type index_EditCaptionsResult as EditCaptionsResult, type index_EmbeddingsOptions as EmbeddingsOptions, type index_EmbeddingsResult as EmbeddingsResult, type index_EngagementInsightsOptions as EngagementInsightsOptions, type index_EngagementInsightsResult as EngagementInsightsResult, index_GOOGLE_VISION_LIKELIHOOD_TO_SCORE as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, index_HIVE_SEXUAL_CATEGORIES as HIVE_SEXUAL_CATEGORIES, index_HIVE_VIOLENCE_CATEGORIES as HIVE_VIOLENCE_CATEGORIES, type index_HiveModerationOutput as HiveModerationOutput, type index_HiveModerationSource as HiveModerationSource, type index_ModerationOptions as ModerationOptions, type index_ModerationProvider as ModerationProvider, type index_ModerationResult as ModerationResult, type index_MomentInsight as MomentInsight, type index_OverallInsight as OverallInsight, type index_ProfanityDetectionPayload as ProfanityDetectionPayload, type index_Question as Question, type index_QuestionAnswer as QuestionAnswer, type index_QuestionAnswerType as QuestionAnswerType, type index_ReplacementRecord as ReplacementRecord, type index_StaticRenditionCleanupOutcome as StaticRenditionCleanupOutcome, type index_SummarizationOptions as SummarizationOptions, type index_SummarizationPromptOverrides as SummarizationPromptOverrides, type index_SummarizationPromptSections as SummarizationPromptSections, type index_SummaryAndTagsResult as SummaryAndTagsResult, type index_SummaryType as SummaryType, type index_ThumbnailModerationScore as ThumbnailModerationScore, type index_TranslationChunkingOptions as TranslationChunkingOptions, type index_TranslationOptions as TranslationOptions, type index_TranslationPayload as TranslationPayload, type index_TranslationResult as TranslationResult, index_aggregateTokenUsage as aggregateTokenUsage, index_applyOverrideLists as applyOverrideLists, index_applyReplacements as applyReplacements, index_askQuestions as askQuestions, index_buildReplacementRegex as buildReplacementRegex, index_burnedInCaptionsSchema as burnedInCaptionsSchema, index_censorVttContent as censorVttContent, index_chapterSchema as chapterSchema, index_chaptersSchema as chaptersSchema, index_createReplacer as createReplacer, index_editCaptions as editCaptions, index_extractTranscriptSegmentsForHotspots as extractTranscriptSegmentsForHotspots, index_generateChapters as generateChapters, index_generateEmbeddings as generateEmbeddings, index_generateEngagementInsights as generateEngagementInsights, index_generateVideoEmbeddings as generateVideoEmbeddings, index_getModerationScores as getModerationScores, index_getSummaryAndTags as getSummaryAndTags, index_hasBurnedInCaptions as hasBurnedInCaptions, index_mapShotsToHotspots as mapShotsToHotspots, index_normalizeTranslatedVtt as normalizeTranslatedVtt, index_profanityDetectionSchema as profanityDetectionSchema, index_questionAnswerSchema as questionAnswerSchema, index_shouldSplitChunkTranslationError as shouldSplitChunkTranslationError, index_summarySchema as summarySchema, index_transformCueText as transformCueText, index_translateAudio as translateAudio, index_translateCaptions as translateCaptions, index_translationSchema as translationSchema, index_validateNeverTranslateTerms as validateNeverTranslateTerms, index_verifyNeverTranslateTerms as verifyNeverTranslateTerms };
1574
1589
  }
1575
1590
 
1576
- export { type MomentInsight as $, ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH as A, type BurnedInCaptionsAnalysis as B, type CaptionReplacement as C, type ChaptersPromptOverrides as D, type ChaptersPromptSections as E, type ChaptersResult as F, type ChaptersType as G, DEFAULT_DESCRIPTION_LENGTH as H, type ISO639_1 as I, DEFAULT_SUMMARY_KEYWORD_LIMIT as J, DEFAULT_TITLE_LENGTH as K, type LanguageCodePair as L, type EditCaptionsOptions as M, type EditCaptionsResult as N, type EmbeddingsOptions as O, type EmbeddingsResult as P, type EngagementInsightsOptions as Q, type EngagementInsightsResult as R, type SupportedISO639_1 as S, GOOGLE_VISION_LIKELIHOOD_TO_SCORE as T, HIVE_SEXUAL_CATEGORIES as U, HIVE_VIOLENCE_CATEGORIES as V, type HiveModerationOutput as W, type HiveModerationSource as X, type ModerationOptions as Y, type ModerationProvider as Z, type ModerationResult as _, type ISO639_3 as a, type OverallInsight as a0, type ProfanityDetectionPayload as a1, type Question as a2, type QuestionAnswer as a3, type QuestionAnswerType as a4, type ReplacementRecord as a5, type SummarizationOptions as a6, type SummarizationPromptOverrides as a7, type SummarizationPromptSections as a8, type SummaryAndTagsResult as a9, normalizeTranslatedVtt as aA, profanityDetectionSchema as aB, questionAnswerSchema as aC, shouldSplitChunkTranslationError as aD, summarySchema as aE, transformCueText as aF, translateAudio as aG, translateCaptions as aH, translationSchema as aI, validateNeverTranslateTerms as aJ, verifyNeverTranslateTerms as aK, type SummaryType as aa, type ThumbnailModerationScore as ab, type TranslationChunkingOptions as ac, type TranslationOptions as ad, type TranslationPayload as ae, type TranslationResult as af, aggregateTokenUsage as ag, applyOverrideLists as ah, applyReplacements as ai, askQuestions as aj, buildReplacementRegex as ak, burnedInCaptionsSchema as al, censorVttContent as am, chapterSchema as an, chaptersSchema as ao, createReplacer as ap, editCaptions as aq, extractTranscriptSegmentsForHotspots as ar, generateChapters as as, generateEmbeddings as at, generateEngagementInsights as au, generateVideoEmbeddings as av, getModerationScores as aw, getSummaryAndTags as ax, hasBurnedInCaptions as ay, mapShotsToHotspots as az, type SupportedISO639_3 as b, getLanguageName as c, isValidISO639_1 as d, isValidISO639_3 as e, toISO639_3 as f, getLanguageCodePair as g, index as h, isUndeterminedLanguageCode as i, ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH as j, ASK_QUESTIONS_MAX_QUESTION_LENGTH as k, type AskQuestionsOptions as l, type AskQuestionsResult as m, type AskQuestionsType as n, type AudioTranslationOptions as o, type AudioTranslationResult as p, type AutoCensorProfanityOptions as q, type BurnedInCaptionsOptions as r, type BurnedInCaptionsPromptOverrides as s, toISO639_1 as t, type BurnedInCaptionsPromptSections as u, type BurnedInCaptionsResult as v, type CensorMode as w, type Chapter as x, type ChapterSystemPromptSections as y, type ChaptersOptions as z };
1591
+ export { type MomentInsight as $, ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH as A, type BurnedInCaptionsAnalysis as B, type CaptionReplacement as C, type ChaptersPromptOverrides as D, type ChaptersPromptSections as E, type ChaptersResult as F, type ChaptersType as G, DEFAULT_DESCRIPTION_LENGTH as H, type ISO639_1 as I, DEFAULT_SUMMARY_KEYWORD_LIMIT as J, DEFAULT_TITLE_LENGTH as K, type LanguageCodePair as L, type EditCaptionsOptions as M, type EditCaptionsResult as N, type EmbeddingsOptions as O, type EmbeddingsResult as P, type EngagementInsightsOptions as Q, type EngagementInsightsResult as R, type SupportedISO639_1 as S, GOOGLE_VISION_LIKELIHOOD_TO_SCORE as T, HIVE_SEXUAL_CATEGORIES as U, HIVE_VIOLENCE_CATEGORIES as V, type HiveModerationOutput as W, type HiveModerationSource as X, type ModerationOptions as Y, type ModerationProvider as Z, type ModerationResult as _, type ISO639_3 as a, type OverallInsight as a0, type ProfanityDetectionPayload as a1, type Question as a2, type QuestionAnswer as a3, type QuestionAnswerType as a4, type ReplacementRecord as a5, type StaticRenditionCleanupOutcome as a6, type SummarizationOptions as a7, type SummarizationPromptOverrides as a8, type SummarizationPromptSections as a9, mapShotsToHotspots as aA, normalizeTranslatedVtt as aB, profanityDetectionSchema as aC, questionAnswerSchema as aD, shouldSplitChunkTranslationError as aE, summarySchema as aF, transformCueText as aG, translateAudio as aH, translateCaptions as aI, translationSchema as aJ, validateNeverTranslateTerms as aK, verifyNeverTranslateTerms as aL, type SummaryAndTagsResult as aa, type SummaryType as ab, type ThumbnailModerationScore as ac, type TranslationChunkingOptions as ad, type TranslationOptions as ae, type TranslationPayload as af, type TranslationResult as ag, aggregateTokenUsage as ah, applyOverrideLists as ai, applyReplacements as aj, askQuestions as ak, buildReplacementRegex as al, burnedInCaptionsSchema as am, censorVttContent as an, chapterSchema as ao, chaptersSchema as ap, createReplacer as aq, editCaptions as ar, extractTranscriptSegmentsForHotspots as as, generateChapters as at, generateEmbeddings as au, generateEngagementInsights as av, generateVideoEmbeddings as aw, getModerationScores as ax, getSummaryAndTags as ay, hasBurnedInCaptions as az, type SupportedISO639_3 as b, getLanguageName as c, isValidISO639_1 as d, isValidISO639_3 as e, toISO639_3 as f, getLanguageCodePair as g, index as h, isUndeterminedLanguageCode as i, ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH as j, ASK_QUESTIONS_MAX_QUESTION_LENGTH as k, type AskQuestionsOptions as l, type AskQuestionsResult as m, type AskQuestionsType as n, type AudioTranslationOptions as o, type AudioTranslationResult as p, type AutoCensorProfanityOptions as q, type BurnedInCaptionsOptions as r, type BurnedInCaptionsPromptOverrides as s, toISO639_1 as t, type BurnedInCaptionsPromptSections as u, type BurnedInCaptionsResult as v, type CensorMode as w, type Chapter as x, type ChapterSystemPromptSections as y, type ChaptersOptions as z };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { I as ISO639_1, a as ISO639_3, L as LanguageCodePair, S as SupportedISO639_1, b as SupportedISO639_3, g as getLanguageCodePair, c as getLanguageName, i as isUndeterminedLanguageCode, d as isValidISO639_1, e as isValidISO639_3, t as toISO639_1, f as toISO639_3, h as workflows } from './index-Chccb380.js';
1
+ export { I as ISO639_1, a as ISO639_3, L as LanguageCodePair, S as SupportedISO639_1, b as SupportedISO639_3, g as getLanguageCodePair, c as getLanguageName, i as isUndeterminedLanguageCode, d as isValidISO639_1, e as isValidISO639_3, t as toISO639_1, f as toISO639_3, h as workflows } from './index-B5l0yXZD.js';
2
2
  import { W as WorkflowCredentials, S as StoragePutObjectInput, a as StoragePresignGetObjectInput } from './shots-BMbViFbZ.js';
3
3
  export { A as AssetTextTrack, C as ChunkEmbedding, b as ChunkingStrategy, E as Encrypted, c as EncryptedPayload, I as ImageSubmissionMode, M as MuxAIOptions, d as MuxAsset, P as PlaybackAsset, e as PlaybackPolicy, f as ScopedMuxAIOptions, g as StorageAdapter, T as TextChunk, h as TokenChunkingConfig, i as TokenUsage, j as ToneType, U as UsageMetadata, V as VTTChunkingConfig, k as VideoEmbeddingsResult, l as WorkflowCredentialsInput, m as WorkflowMuxClient, n as WorkflowScope, o as decryptFromWorkflow, p as encryptForWorkflow } from './shots-BMbViFbZ.js';
4
4
  import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
@@ -9,7 +9,7 @@ import '@ai-sdk/google';
9
9
  import '@ai-sdk/openai';
10
10
  import '@mux/mux-node';
11
11
 
12
- var version = "0.33.0";
12
+ var version = "0.34.0";
13
13
 
14
14
  type MuxAiErrorType = "validation_error" | "processing_error" | "timeout_error" | "content_policy_error";
15
15
  /**
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // package.json
8
- var version = "0.33.0";
8
+ var version = "0.34.0";
9
9
 
10
10
  // src/lib/language-codes.ts
11
11
  var ISO639_1_TO_3 = {
@@ -7242,19 +7242,41 @@ async function requestStaticRenditionCreation(assetId, credentials) {
7242
7242
  const muxClient = await resolveMuxClient(credentials);
7243
7243
  const mux = await muxClient.createClient();
7244
7244
  try {
7245
- await mux.video.assets.createStaticRendition(assetId, {
7245
+ const rendition = await mux.video.assets.createStaticRendition(assetId, {
7246
7246
  resolution: "audio-only"
7247
7247
  });
7248
+ return rendition.id;
7248
7249
  } catch (error) {
7249
7250
  const statusCode = error?.status ?? error?.statusCode;
7250
7251
  const messages = error?.error?.messages;
7251
7252
  const alreadyDefined = messages?.some((message) => message.toLowerCase().includes("already defined")) ?? error?.message?.toLowerCase().includes("already defined");
7252
7253
  if (statusCode === 409 || alreadyDefined) {
7253
- return;
7254
+ return void 0;
7254
7255
  }
7255
7256
  wrapError(error, "Failed to request static rendition from Mux");
7256
7257
  }
7257
7258
  }
7259
+ async function deleteCreatedStaticRendition(assetId, staticRenditionId, credentials) {
7260
+ "use step";
7261
+ try {
7262
+ const muxClient = await resolveMuxClient(credentials);
7263
+ const mux = await muxClient.createClient();
7264
+ await mux.video.assets.deleteStaticRendition(assetId, staticRenditionId);
7265
+ console.warn(`\u{1F9F9} Deleted static rendition ${staticRenditionId} created on asset ${assetId}`);
7266
+ return "deleted";
7267
+ } catch (error) {
7268
+ const statusCode = error?.status ?? error?.statusCode;
7269
+ if (statusCode === 404) {
7270
+ console.warn(`\u{1F9F9} Static rendition ${staticRenditionId} on asset ${assetId} was already deleted`);
7271
+ return "deleted";
7272
+ }
7273
+ const message = error instanceof Error ? error.message : String(error);
7274
+ console.warn(
7275
+ `\u26A0\uFE0F Failed to delete static rendition ${staticRenditionId} on asset ${assetId} (status: ${statusCode ?? "unknown"}): ${message}`
7276
+ );
7277
+ return "delete_failed";
7278
+ }
7279
+ }
7258
7280
  async function retrieveAsset(assetId, credentials) {
7259
7281
  "use step";
7260
7282
  const muxClient = await resolveMuxClient(credentials);
@@ -7270,14 +7292,6 @@ async function waitForAudioStaticRendition({
7270
7292
  if (hasReadyAudioStaticRendition(currentAsset)) {
7271
7293
  return currentAsset;
7272
7294
  }
7273
- const status = currentAsset.static_renditions?.status ?? "not_requested";
7274
- if (status === "not_requested" || status === void 0) {
7275
- await requestStaticRenditionCreation(assetId, credentials);
7276
- } else if (status === "errored") {
7277
- await requestStaticRenditionCreation(assetId, credentials);
7278
- } else {
7279
- console.warn(`\u2139\uFE0F Static rendition already ${status}. Waiting for it to finish...`);
7280
- }
7281
7295
  for (let attempt = 1; attempt <= STATIC_RENDITION_MAX_ATTEMPTS; attempt++) {
7282
7296
  await sleep2(STATIC_RENDITION_POLL_INTERVAL_MS);
7283
7297
  currentAsset = await retrieveAsset(assetId, credentials);
@@ -7484,6 +7498,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7484
7498
  uploadToS3: uploadToS3Option,
7485
7499
  uploadToMux: uploadToMuxOption,
7486
7500
  uploadCaptionsToMux = false,
7501
+ staticRenditionCleanup: staticRenditionCleanupOption = "delete",
7487
7502
  storageAdapter,
7488
7503
  credentials: providedCredentials
7489
7504
  } = options;
@@ -7505,144 +7520,167 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7505
7520
  const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
7506
7521
  const assetDurationSeconds = getAssetDurationSecondsFromAsset(initialAsset);
7507
7522
  let currentAsset = initialAsset;
7523
+ let createdStaticRenditionId;
7508
7524
  if (!hasReadyAudioStaticRendition(currentAsset)) {
7509
7525
  console.warn("\u274C No ready audio static rendition found. Requesting one now...");
7510
- currentAsset = await waitForAudioStaticRendition({
7511
- assetId,
7512
- initialAsset: currentAsset,
7513
- credentials
7514
- });
7515
- }
7516
- const audioRendition = getReadyAudioStaticRendition(currentAsset);
7517
- if (!audioRendition) {
7518
- throw new MuxAiError(
7519
- "Unable to obtain an audio-only static rendition for this asset. Please verify static renditions are enabled in Mux.",
7520
- { type: "validation_error" }
7521
- );
7522
- }
7523
- let audioUrl = `${getMuxStreamOrigin()}/${playbackId}/audio.m4a`;
7524
- if (policy === "signed") {
7525
- audioUrl = await signUrl(audioUrl, playbackId, "video", void 0, credentials);
7526
+ const renditionStatus = currentAsset.static_renditions?.status ?? "not_requested";
7527
+ if (renditionStatus === "not_requested" || renditionStatus === "errored") {
7528
+ createdStaticRenditionId = await requestStaticRenditionCreation(assetId, credentials);
7529
+ } else {
7530
+ console.warn(`\u2139\uFE0F Static rendition already ${renditionStatus}. Waiting for it to finish...`);
7531
+ }
7526
7532
  }
7527
- console.warn("\u{1F399}\uFE0F Creating dubbing job in ElevenLabs...");
7528
- const elevenLabsLangCode = toISO639_3(toLanguageCode);
7529
- const normalizedFromLanguageCode = fromLanguageCode?.trim();
7530
- const elevenLabsSourceLangCode = normalizedFromLanguageCode ? toISO639_3(normalizedFromLanguageCode) : void 0;
7531
- console.warn(
7532
- `\u{1F50D} Creating dubbing job for asset ${assetId}: ${elevenLabsSourceLangCode ?? "auto"} -> ${elevenLabsLangCode}`
7533
- );
7533
+ let staticRenditionCleanup = "not_created";
7534
7534
  let dubbingId;
7535
+ let presignedUrl;
7536
+ let uploadedTrackId;
7537
+ let captionsPresignedUrl;
7538
+ let captionsTrackId;
7535
7539
  try {
7536
- dubbingId = await createElevenLabsDubbingJob({
7537
- sourceUrl: audioUrl,
7538
- assetId,
7539
- elevenLabsLangCode,
7540
- elevenLabsSourceLangCode,
7541
- numSpeakers,
7542
- credentials
7543
- });
7544
- console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
7545
- } catch (error) {
7546
- wrapError(error, "Failed to create ElevenLabs dubbing job");
7547
- }
7548
- console.warn("\u23F3 Waiting for dubbing to complete...");
7549
- const dubbingPollTimeoutSeconds = options.dubbingPollTimeoutSeconds ?? DEFAULT_DUBBING_POLL_TIMEOUT_SECONDS;
7550
- const maxPollAttempts = Math.max(1, Math.ceil(dubbingPollTimeoutSeconds * 1e3 / DUBBING_POLL_INTERVAL_MS));
7551
- let dubbingStatus = "dubbing";
7552
- let pollAttempts = 0;
7553
- let targetLanguages = [];
7554
- while (dubbingStatus !== "dubbed" && pollAttempts < maxPollAttempts) {
7555
- await sleep2(DUBBING_POLL_INTERVAL_MS);
7556
- pollAttempts++;
7557
- try {
7558
- const statusResult = await checkElevenLabsDubbingStatus({
7559
- dubbingId,
7540
+ if (!hasReadyAudioStaticRendition(currentAsset)) {
7541
+ currentAsset = await waitForAudioStaticRendition({
7542
+ assetId,
7543
+ initialAsset: currentAsset,
7560
7544
  credentials
7561
7545
  });
7562
- dubbingStatus = statusResult.status;
7563
- targetLanguages = statusResult.targetLanguages;
7564
- } catch (error) {
7565
- wrapError(error, "Failed to check dubbing status");
7566
7546
  }
7567
- if (dubbingStatus === "failed") {
7568
- throw new MuxAiError("ElevenLabs reported that the dubbing job failed.", { type: "processing_error" });
7547
+ const audioRendition = getReadyAudioStaticRendition(currentAsset);
7548
+ if (!audioRendition) {
7549
+ throw new MuxAiError(
7550
+ "Unable to obtain an audio-only static rendition for this asset. Please verify static renditions are enabled in Mux.",
7551
+ { type: "validation_error" }
7552
+ );
7569
7553
  }
7570
- }
7571
- if (dubbingStatus !== "dubbed") {
7572
- throw new MuxAiError("Audio translation timed out or failed. Please try again.", { type: "timeout_error", retryable: true });
7573
- }
7574
- console.warn("\u2705 Dubbing completed successfully!");
7575
- let presignedUrl;
7576
- let uploadedTrackId;
7577
- let captionsPresignedUrl;
7578
- let captionsTrackId;
7579
- if (uploadToS3) {
7580
- console.warn("\u{1F4E5} Downloading dubbed audio from ElevenLabs and staging to S3...");
7581
- const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
7554
+ let audioUrl = `${getMuxStreamOrigin()}/${playbackId}/audio.m4a`;
7555
+ if (policy === "signed") {
7556
+ audioUrl = await signUrl(audioUrl, playbackId, "video", void 0, credentials);
7557
+ }
7558
+ console.warn("\u{1F399}\uFE0F Creating dubbing job in ElevenLabs...");
7559
+ const elevenLabsLangCode = toISO639_3(toLanguageCode);
7560
+ const normalizedFromLanguageCode = fromLanguageCode?.trim();
7561
+ const elevenLabsSourceLangCode = normalizedFromLanguageCode ? toISO639_3(normalizedFromLanguageCode) : void 0;
7562
+ console.warn(
7563
+ `\u{1F50D} Creating dubbing job for asset ${assetId}: ${elevenLabsSourceLangCode ?? "auto"} -> ${elevenLabsLangCode}`
7564
+ );
7582
7565
  try {
7583
- presignedUrl = await downloadAndUploadDubbedAudio({
7584
- dubbingId,
7585
- languageCode: downloadLangCode,
7566
+ dubbingId = await createElevenLabsDubbingJob({
7567
+ sourceUrl: audioUrl,
7586
7568
  assetId,
7587
- toLanguageCode,
7588
- s3Endpoint,
7589
- s3Region,
7590
- s3Bucket,
7591
- storageAdapter: effectiveStorageAdapter,
7592
- s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7569
+ elevenLabsLangCode,
7570
+ elevenLabsSourceLangCode,
7571
+ numSpeakers,
7593
7572
  credentials
7594
7573
  });
7595
- console.warn("\u2705 Dubbed audio staged to S3 successfully!");
7574
+ console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
7596
7575
  } catch (error) {
7597
- wrapError(error, "Failed to download and upload dubbed audio");
7598
- }
7599
- if (uploadToMux) {
7600
- console.warn("\u{1F4F9} Adding dubbed audio track to Mux asset...");
7601
- const muxLangCode = toISO639_1(toLanguageCode);
7576
+ wrapError(error, "Failed to create ElevenLabs dubbing job");
7577
+ }
7578
+ console.warn("\u23F3 Waiting for dubbing to complete...");
7579
+ const dubbingPollTimeoutSeconds = options.dubbingPollTimeoutSeconds ?? DEFAULT_DUBBING_POLL_TIMEOUT_SECONDS;
7580
+ const maxPollAttempts = Math.max(1, Math.ceil(dubbingPollTimeoutSeconds * 1e3 / DUBBING_POLL_INTERVAL_MS));
7581
+ let dubbingStatus = "dubbing";
7582
+ let pollAttempts = 0;
7583
+ let targetLanguages = [];
7584
+ while (dubbingStatus !== "dubbed" && pollAttempts < maxPollAttempts) {
7585
+ await sleep2(DUBBING_POLL_INTERVAL_MS);
7586
+ pollAttempts++;
7602
7587
  try {
7603
- uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl, credentials);
7604
- const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7605
- const trackName = `${languageName} (auto-dubbed)`;
7606
- console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
7607
- console.warn(`\u{1F4CB} Track name: "${trackName}"`);
7588
+ const statusResult = await checkElevenLabsDubbingStatus({
7589
+ dubbingId,
7590
+ credentials
7591
+ });
7592
+ dubbingStatus = statusResult.status;
7593
+ targetLanguages = statusResult.targetLanguages;
7608
7594
  } catch (error) {
7609
- console.warn(`\u26A0\uFE0F Failed to add audio track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
7610
- console.warn("\u{1F517} You can manually add the track using this presigned URL:");
7611
- console.warn(presignedUrl);
7595
+ wrapError(error, "Failed to check dubbing status");
7596
+ }
7597
+ if (dubbingStatus === "failed") {
7598
+ throw new MuxAiError("ElevenLabs reported that the dubbing job failed.", { type: "processing_error" });
7612
7599
  }
7613
7600
  }
7614
- try {
7615
- console.warn("\u{1F4E5} Downloading dub transcript from ElevenLabs and staging to S3...");
7616
- captionsPresignedUrl = await downloadAndUploadDubTranscript({
7617
- dubbingId,
7618
- languageCode: downloadLangCode,
7619
- assetId,
7620
- toLanguageCode,
7621
- s3Endpoint,
7622
- s3Region,
7623
- s3Bucket,
7624
- storageAdapter: effectiveStorageAdapter,
7625
- s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7626
- credentials
7627
- });
7628
- if (uploadCaptionsToMux) {
7629
- console.warn("\u{1F4F9} Adding dubbed captions track to Mux asset...");
7601
+ if (dubbingStatus !== "dubbed") {
7602
+ throw new MuxAiError("Audio translation timed out or failed. Please try again.", { type: "timeout_error", retryable: true });
7603
+ }
7604
+ console.warn("\u2705 Dubbing completed successfully!");
7605
+ if (uploadToS3) {
7606
+ console.warn("\u{1F4E5} Downloading dubbed audio from ElevenLabs and staging to S3...");
7607
+ const downloadLangCode = targetLanguages[0] ?? toISO639_1(toLanguageCode);
7608
+ try {
7609
+ presignedUrl = await downloadAndUploadDubbedAudio({
7610
+ dubbingId,
7611
+ languageCode: downloadLangCode,
7612
+ assetId,
7613
+ toLanguageCode,
7614
+ s3Endpoint,
7615
+ s3Region,
7616
+ s3Bucket,
7617
+ storageAdapter: effectiveStorageAdapter,
7618
+ s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7619
+ credentials
7620
+ });
7621
+ console.warn("\u2705 Dubbed audio staged to S3 successfully!");
7622
+ } catch (error) {
7623
+ wrapError(error, "Failed to download and upload dubbed audio");
7624
+ }
7625
+ if (uploadToMux) {
7626
+ console.warn("\u{1F4F9} Adding dubbed audio track to Mux asset...");
7630
7627
  const muxLangCode = toISO639_1(toLanguageCode);
7631
- const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7632
- captionsTrackId = await createTextTrackOnMux(
7628
+ try {
7629
+ uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl, credentials);
7630
+ const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7631
+ const trackName = `${languageName} (auto-dubbed)`;
7632
+ console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
7633
+ console.warn(`\u{1F4CB} Track name: "${trackName}"`);
7634
+ } catch (error) {
7635
+ console.warn(`\u26A0\uFE0F Failed to add audio track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
7636
+ console.warn("\u{1F517} You can manually add the track using this presigned URL:");
7637
+ console.warn(presignedUrl);
7638
+ }
7639
+ }
7640
+ try {
7641
+ console.warn("\u{1F4E5} Downloading dub transcript from ElevenLabs and staging to S3...");
7642
+ captionsPresignedUrl = await downloadAndUploadDubTranscript({
7643
+ dubbingId,
7644
+ languageCode: downloadLangCode,
7633
7645
  assetId,
7634
- muxLangCode,
7635
- `${languageName} (auto-dubbed)`,
7636
- captionsPresignedUrl,
7646
+ toLanguageCode,
7647
+ s3Endpoint,
7648
+ s3Region,
7649
+ s3Bucket,
7650
+ storageAdapter: effectiveStorageAdapter,
7651
+ s3SignedUrlExpirySeconds: options.s3SignedUrlExpirySeconds,
7637
7652
  credentials
7638
- );
7639
- console.warn(`\u2705 Captions track added to Mux asset with ID: ${captionsTrackId}`);
7653
+ });
7654
+ if (uploadCaptionsToMux) {
7655
+ console.warn("\u{1F4F9} Adding dubbed captions track to Mux asset...");
7656
+ const muxLangCode = toISO639_1(toLanguageCode);
7657
+ const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
7658
+ captionsTrackId = await createTextTrackOnMux(
7659
+ assetId,
7660
+ muxLangCode,
7661
+ `${languageName} (auto-dubbed)`,
7662
+ captionsPresignedUrl,
7663
+ credentials
7664
+ );
7665
+ console.warn(`\u2705 Captions track added to Mux asset with ID: ${captionsTrackId}`);
7666
+ }
7667
+ } catch (error) {
7668
+ console.warn(`\u26A0\uFE0F Failed to attach dubbed captions: ${error instanceof Error ? error.message : "Unknown error"}`);
7669
+ if (captionsPresignedUrl) {
7670
+ console.warn("\u{1F517} You can manually add the captions track using this presigned URL:");
7671
+ console.warn(captionsPresignedUrl);
7672
+ }
7640
7673
  }
7641
- } catch (error) {
7642
- console.warn(`\u26A0\uFE0F Failed to attach dubbed captions: ${error instanceof Error ? error.message : "Unknown error"}`);
7643
- if (captionsPresignedUrl) {
7644
- console.warn("\u{1F517} You can manually add the captions track using this presigned URL:");
7645
- console.warn(captionsPresignedUrl);
7674
+ }
7675
+ } finally {
7676
+ if (createdStaticRenditionId) {
7677
+ if (staticRenditionCleanupOption === "keep") {
7678
+ console.warn(
7679
+ `\u2139\uFE0F Keeping static rendition ${createdStaticRenditionId} on asset ${assetId} (staticRenditionCleanup: "keep")`
7680
+ );
7681
+ staticRenditionCleanup = "kept";
7682
+ } else {
7683
+ staticRenditionCleanup = await deleteCreatedStaticRendition(assetId, createdStaticRenditionId, credentials);
7646
7684
  }
7647
7685
  }
7648
7686
  }
@@ -7656,6 +7694,8 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
7656
7694
  presignedUrl,
7657
7695
  captionsTrackId,
7658
7696
  captionsPresignedUrl,
7697
+ createdStaticRenditionId,
7698
+ staticRenditionCleanup,
7659
7699
  usage: {
7660
7700
  metadata: {
7661
7701
  assetDurationSeconds