@mux/ai 0.46.0 → 0.48.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 { E as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, F as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, G as ASK_QUESTIONS_MAX_QUESTIONS_PER_CALL, H as ASK_QUESTIONS_MAX_QUESTION_LENGTH, J as AskQuestionsOptions, K as AskQuestionsResult, N as AskQuestionsType, O as AudioTranslationOptions, P as AudioTranslationResult, Q as AutoCensorProfanityOptions, U as BurnedInCaptionsAnalysis, V as BurnedInCaptionsOptions, W as BurnedInCaptionsPromptOverrides, X as BurnedInCaptionsPromptSections, Y as BurnedInCaptionsResult, Z as CaptionReplacement, _ as CensorMode, $ as Chapter, a0 as ChapterSystemPromptSections, a1 as ChaptersOptions, a2 as ChaptersPromptOverrides, a3 as ChaptersPromptSections, a4 as ChaptersResult, a5 as ChaptersType, a6 as EditCaptionsOptions, a7 as EditCaptionsResult, a8 as EmbeddingsOptions, a9 as EmbeddingsResult, aa as EngagementInsightsOptions, ab as EngagementInsightsResult, ac as GENERATE_TEXT_CALLS_TO_ACTION, ad as GENERATE_TEXT_CHANNELS, ae as GENERATE_TEXT_CHANNEL_CEILINGS, af as GENERATE_TEXT_FORMATS, ag as GENERATE_TEXT_LENGTH_BOUNDS, ah as GENERATE_TEXT_MAX_ARTIFACTS, ai as GENERATE_TEXT_MAX_AUDIENCE_CHARS, aj as GENERATE_TEXT_MAX_BRAND_TERMS, ak as GENERATE_TEXT_MAX_BRAND_TERMS_TOTAL_CHARS, al as GENERATE_TEXT_MAX_BRAND_TERM_CHARS, am as GENERATE_TEXT_MAX_CONCURRENT_GENERATIONS, an as GENERATE_TEXT_MAX_INSTRUCTIONS_CHARS, ao as GENERATE_TEXT_MAX_SHOT_FRAMES, ap as GENERATE_TEXT_MAX_VARIANTS, aq as GENERATE_TEXT_VOICES, ar as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, as as GenerateTextArtifact, at as GenerateTextCallToAction, au as GenerateTextChannel, av as GenerateTextFormat, aw as GenerateTextKeyedItem, ax as GenerateTextLengthLimit, ay as GenerateTextOptions, az as GenerateTextResult, aA as GenerateTextVariant, aB as GenerateTextVoice, aC as GeneratedTextArtifact, aD as GeneratedTextVariant, aE as HIVE_SEXUAL_CATEGORIES, aF as HIVE_VIOLENCE_CATEGORIES, aG as HiveModerationOutput, aH as HiveModerationSource, aI as ModerationOptions, aJ as ModerationProvider, aK as ModerationResult, aL as MomentInsight, aM as OverallInsight, aN as ProfanityDetectionPayload, aO as Question, aP as QuestionAnswer, aQ as QuestionAnswerType, aR as ReplacementRecord, aS as SpeakerReplacement, aT as StaticRenditionCleanupOutcome, aU as SummarizationOptions, aV as SummarizationPromptOverrides, aW as SummarizationPromptSections, aX as SummaryAndTagsResult, aY as SummaryType, aZ as ThumbnailModerationScore, a_ as TranslationChunkingOptions, a$ as TranslationOptions, b0 as TranslationPayload, b1 as TranslationResult, b2 as aggregateTokenUsage, b3 as applyOverrideLists, b4 as applyReplacements, b5 as applySpeakerReplacements, b6 as askQuestions, b7 as buildReplacementRegex, b8 as burnedInCaptionsSchema, b9 as censorVttContent, ba as chapterSchema, bb as chaptersSchema, bc as createReplacer, bd as editCaptions, be as extractTranscriptSegmentsForHotspots, bf as findGenerateTextLengthViolation, bg as generateChapters, bh as generateEmbeddings, bi as generateEngagementInsights, bj as generateText, bk as generateVideoEmbeddings, bl as getModerationScores, bm as getSummaryAndTags, bn as hasBurnedInCaptions, bo as mapShotsToHotspots, bp as measureGenerateTextLength, bq as normalizeTranslatedVtt, br as profanityDetectionSchema, bs as questionAnswerSchema, bt as resolveGenerateTextLengthLimit, bu as resolveGenerateTextLengthLimits, bv as resolveGenerateTextOptions, bw as selectGenerateTextShotFrames, bx as shouldSplitChunkTranslationError, by as summarySchema, bz as transformCueText, bA as translateAudio, bB as translateCaptions, bC as translationSchema, bD as validateNeverTranslateTerms, bE as verifyNeverTranslateTerms } from '../index-CIcGZD3x.js';
1
+ export { J as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, K as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, N as ASK_QUESTIONS_MAX_QUESTIONS_PER_CALL, O as ASK_QUESTIONS_MAX_QUESTION_LENGTH, P as AskQuestionsOptions, Q as AskQuestionsResult, U as AskQuestionsType, V as AudioTranslationOptions, W as AudioTranslationResult, X as AutoCensorProfanityOptions, Y as BurnedInCaptionsAnalysis, Z as BurnedInCaptionsOptions, _ as BurnedInCaptionsPromptOverrides, $ as BurnedInCaptionsPromptSections, a0 as BurnedInCaptionsResult, a1 as CaptionReplacement, a2 as CensorMode, a3 as Chapter, a4 as ChapterSystemPromptSections, a5 as ChaptersOptions, a6 as ChaptersPromptOverrides, a7 as ChaptersPromptSections, a8 as ChaptersResult, a9 as ChaptersType, aa as EditCaptionsOptions, ab as EditCaptionsResult, ac as EmbeddingsOptions, ad as EmbeddingsResult, ae as EngagementInsightsOptions, af as EngagementInsightsResult, ag as GENERATE_TEXT_CALLS_TO_ACTION, ah as GENERATE_TEXT_CHANNELS, ai as GENERATE_TEXT_CHANNEL_CEILINGS, aj as GENERATE_TEXT_FORMATS, ak as GENERATE_TEXT_LENGTH_BOUNDS, al as GENERATE_TEXT_MAX_ARTIFACTS, am as GENERATE_TEXT_MAX_AUDIENCE_CHARS, an as GENERATE_TEXT_MAX_BRAND_TERMS, ao as GENERATE_TEXT_MAX_BRAND_TERMS_TOTAL_CHARS, ap as GENERATE_TEXT_MAX_BRAND_TERM_CHARS, aq as GENERATE_TEXT_MAX_CONCURRENT_GENERATIONS, ar as GENERATE_TEXT_MAX_INSTRUCTIONS_CHARS, as as GENERATE_TEXT_MAX_SHOT_FRAMES, at as GENERATE_TEXT_MAX_VARIANTS, au as GENERATE_TEXT_VOICES, av as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, aw as GenerateTextArtifact, ax as GenerateTextCallToAction, ay as GenerateTextChannel, az as GenerateTextFormat, aA as GenerateTextKeyedItem, aB as GenerateTextLengthLimit, aC as GenerateTextOptions, aD as GenerateTextResult, aE as GenerateTextVariant, aF as GenerateTextVoice, aG as GeneratedTextArtifact, aH as GeneratedTextVariant, aI as HIVE_SEXUAL_CATEGORIES, aJ as HIVE_VIOLENCE_CATEGORIES, aK as HiveModerationOutput, aL as HiveModerationSource, aM as ModerationOptions, aN as ModerationProvider, aO as ModerationResult, aP as MomentInsight, aQ as OverallInsight, aR as ProfanityDetectionPayload, aS as Question, aT as QuestionAnswer, aU as QuestionAnswerType, aV as ReplacementRecord, aW as SpeakerReplacement, aX as StaticRenditionCleanupOutcome, aY as SummarizationOptions, aZ as SummarizationPromptOverrides, a_ as SummarizationPromptSections, a$ as SummaryAndTagsResult, b0 as SummaryType, b1 as ThumbnailModerationScore, b2 as TranslationChunkingOptions, b3 as TranslationOptions, b4 as TranslationPayload, b5 as TranslationResult, b6 as aggregateTokenUsage, b7 as applyOverrideLists, b8 as applyReplacements, b9 as applySpeakerReplacements, ba as askQuestions, bb as buildReplacementRegex, bc as burnedInCaptionsSchema, bd as censorVttContent, be as chapterSchema, bf as chaptersSchema, bg as createReplacer, bh as editCaptions, bi as extractTranscriptSegmentsForHotspots, bj as findGenerateTextLengthViolation, bk as generateChapters, bl as generateEmbeddings, bm as generateEngagementInsights, bn as generateText, bo as generateVideoEmbeddings, bp as getModerationScores, bq as getSummaryAndTags, br as hasBurnedInCaptions, bs as mapShotsToHotspots, bt as measureGenerateTextLength, bu as normalizeTranslatedVtt, bv as profanityDetectionSchema, bw as questionAnswerSchema, bx as resolveGenerateTextLengthLimit, by as resolveGenerateTextLengthLimits, bz as resolveGenerateTextOptions, bA as selectGenerateTextShotFrames, bB as shouldSplitChunkTranslationError, bC as summarySchema, bD as transformCueText, bE as translateAudio, bF as translateCaptions, bG as translationSchema, bH as validateNeverTranslateTerms, bI as verifyNeverTranslateTerms } from '../index-DxAt9Jq8.js';
2
2
  export { D as DEFAULT_DESCRIPTION_LENGTH, a as DEFAULT_SUMMARY_KEYWORD_LIMIT, b as DEFAULT_TITLE_LENGTH } from '../summarization-BFmhXeAu.js';
3
3
  import 'zod';
4
4
  import '@ai-sdk/anthropic';
@@ -3975,17 +3975,24 @@ function findNameCollisionTextTracks(asset, target) {
3975
3975
  }
3976
3976
  return listTracks(asset, targetType(target)).filter((track) => normalizeTrackName(track.name) === targetName);
3977
3977
  }
3978
+ function countTracks(tracks, label, singularVerb, pluralVerb) {
3979
+ const kind = label.toLowerCase();
3980
+ if (tracks.length === 1) {
3981
+ return `${kind === "audio" ? "An" : "A"} ${kind} track ${singularVerb}`;
3982
+ }
3983
+ return `${tracks.length} ${kind} tracks ${pluralVerb}`;
3984
+ }
3985
+ function itOrThem(tracks) {
3986
+ return tracks.length === 1 ? "it" : "them";
3987
+ }
3978
3988
  function describeTracks(tracks) {
3979
3989
  return tracks.map((track) => `${track.name ?? "(unnamed)"} [${track.language_code ?? "?"}, ${track.type === "audio" ? track.primary ? "primary audio" : "audio" : track.text_source ?? "unknown source"}, ${track.status ?? "ready"}]`).join("; ");
3980
3990
  }
3981
- function planTextTrackReplacement(asset, target, policy, options = {}) {
3991
+ function planTextTrackReplacement(asset, target, policy) {
3982
3992
  const label = targetType(target) === "audio" ? "Audio" : "Text";
3983
- const keep = new Set(options.keepTrackIds ?? []);
3984
3993
  const conflicts = /* @__PURE__ */ new Map();
3985
3994
  for (const track of [...findSameLanguageTextTracks(asset, target), ...findNameCollisionTextTracks(asset, target)]) {
3986
- if (!keep.has(track.id)) {
3987
- conflicts.set(track.id, track);
3988
- }
3995
+ conflicts.set(track.id, track);
3989
3996
  }
3990
3997
  const conflicting = [...conflicts.values()];
3991
3998
  if (conflicting.length === 0) {
@@ -3994,7 +4001,7 @@ function planTextTrackReplacement(asset, target, policy, options = {}) {
3994
4001
  if (policy === "fail") {
3995
4002
  return {
3996
4003
  kind: "blocked",
3997
- reason: `${label} track(s) already exist for language '${target.languageCode}' or name '${target.name}': ${describeTracks(conflicting)}. Set replaceExistingTracks to replace them.`,
4004
+ reason: `${countTracks(conflicting, label, "already exists", "already exist")} for language '${target.languageCode}' or name '${target.name}': ${describeTracks(conflicting)}. Set replaceExistingTracks to replace ${itOrThem(conflicting)}.`,
3998
4005
  tracks: conflicting.map(summarizeTextTrack)
3999
4006
  };
4000
4007
  }
@@ -4011,13 +4018,26 @@ function planTextTrackReplacement(asset, target, policy, options = {}) {
4011
4018
  if (notGenerated.length > 0) {
4012
4019
  return {
4013
4020
  kind: "blocked",
4014
- reason: `${label} track(s) that are not Mux-generated exist for language '${target.languageCode}' or name '${target.name}': ${describeTracks(notGenerated)}. Use replaceExistingTracks: "replace_all" to replace them.`,
4021
+ reason: `${countTracks(notGenerated, label, "that is not Mux-generated exists", "that are not Mux-generated exist")} for language '${target.languageCode}' or name '${target.name}': ${describeTracks(notGenerated)}. Use replaceExistingTracks: "replace_all" to replace ${itOrThem(notGenerated)}.`,
4015
4022
  tracks: notGenerated.map(summarizeTextTrack)
4016
4023
  };
4017
4024
  }
4018
4025
  }
4019
4026
  return { kind: "replace", toDelete: conflicting.map(summarizeTextTrack) };
4020
4027
  }
4028
+ function planSourceTrackReplacement(asset, sourceTrackId, target, policy) {
4029
+ const colliding = findNameCollisionTextTracks(asset, target);
4030
+ const blocking = policy === "fail" ? colliding : colliding.filter((track) => track.id !== sourceTrackId);
4031
+ if (blocking.length > 0) {
4032
+ return {
4033
+ kind: "blocked",
4034
+ reason: `${countTracks(blocking, "Text", "already has", "already have")} the name '${target.name}': ${describeTracks(blocking)}. Choose a different trackName.`,
4035
+ tracks: blocking.map(summarizeTextTrack)
4036
+ };
4037
+ }
4038
+ const source = policy === "replace" ? listTracks(asset, targetType(target)).find((track) => track.id === sourceTrackId) : void 0;
4039
+ return source ? { kind: "replace", toDelete: [summarizeTextTrack(source)] } : { kind: "clear" };
4040
+ }
4021
4041
  function isDuplicateTrackNameError(error) {
4022
4042
  if (typeof error !== "object" || error === null) {
4023
4043
  return false;
@@ -4073,6 +4093,14 @@ async function createTextTrackOnMux(assetId, languageCode, trackName, presignedU
4073
4093
  }
4074
4094
  async function replaceAndCreateTrack(input) {
4075
4095
  "use step";
4096
+ return writeTrack(input, (asset) => planTextTrackReplacement(asset, input.target, input.policy));
4097
+ }
4098
+ async function replaceSourceTrack(input) {
4099
+ "use step";
4100
+ const target = { ...input.target, type: "text" };
4101
+ return writeTrack({ ...input, target }, (asset) => planSourceTrackReplacement(asset, input.sourceTrackId, target, input.policy));
4102
+ }
4103
+ async function writeTrack(input, plan) {
4076
4104
  const muxClient = await resolveMuxClient(input.credentials);
4077
4105
  const mux = await muxClient.createClient();
4078
4106
  const type = targetType(input.target);
@@ -4092,12 +4120,12 @@ async function replaceAndCreateTrack(input) {
4092
4120
  }
4093
4121
  return failed(error);
4094
4122
  }
4095
- const plan = planTextTrackReplacement(asset, input.target, input.policy, { keepTrackIds: input.keepTrackIds });
4096
- if (plan.kind === "blocked") {
4097
- return { ...plan, deleted };
4123
+ const planned = plan(asset);
4124
+ if (planned.kind === "blocked") {
4125
+ return { ...planned, deleted };
4098
4126
  }
4099
- if (plan.kind === "replace") {
4100
- for (const track of plan.toDelete) {
4127
+ if (planned.kind === "replace") {
4128
+ for (const track of planned.toDelete) {
4101
4129
  try {
4102
4130
  await mux.video.assets.deleteTrack(input.assetId, track.id);
4103
4131
  deleted.push(track);
@@ -4721,7 +4749,13 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
4721
4749
  { type: "validation_error" }
4722
4750
  );
4723
4751
  }
4724
- const replaceExistingTracks = replaceExistingTracksOption ?? "replace_all";
4752
+ if (replaceExistingTracksOption !== void 0 && replaceExistingTracksOption !== "replace" && replaceExistingTracksOption !== "fail") {
4753
+ throw new MuxAiError(
4754
+ `replaceExistingTracks must be "replace" or "fail" for editCaptions (received "${String(replaceExistingTracksOption)}").`,
4755
+ { type: "validation_error" }
4756
+ );
4757
+ }
4758
+ const replaceExistingTracks = replaceExistingTracksOption ?? "replace";
4725
4759
  if (!legacyTrackNaming && replaceExistingTracks === "fail" && !providedTrackName) {
4726
4760
  throw new MuxAiError(
4727
4761
  `trackName is required when replaceExistingTracks is "fail": the edited track cannot reuse the source track's name while the source is kept.`,
@@ -4777,15 +4811,14 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
4777
4811
  languageCode: sourceLanguageCode,
4778
4812
  name: providedTrackName ?? sourceName
4779
4813
  };
4780
- const keepTrackIds = replaceExistingTracks === "fail" ? [trackId] : [];
4781
4814
  if (replaceExistingTracks === "fail" && normalizeTrackName(outputTrack.name) === normalizeTrackName(sourceName)) {
4782
4815
  throw new MuxAiError(
4783
- `trackName "${outputTrack.name}" matches the source track's name. Mux track names must be unique; choose a different trackName or use replaceExistingTracks: "replace_all" to replace the source.`,
4816
+ `trackName "${outputTrack.name}" matches the source track's name. Mux track names must be unique; choose a different trackName or use replaceExistingTracks: "replace" to replace the source.`,
4784
4817
  { type: "validation_error" }
4785
4818
  );
4786
4819
  }
4787
4820
  if (uploadToMux && !legacyTrackNaming) {
4788
- const plan = planTextTrackReplacement(assetData, outputTrack, replaceExistingTracks, { keepTrackIds });
4821
+ const plan = planSourceTrackReplacement(assetData, trackId, outputTrack, replaceExistingTracks);
4789
4822
  if (plan.kind === "blocked") {
4790
4823
  throw new MuxAiError(plan.reason, { type: "validation_error" });
4791
4824
  }
@@ -4907,14 +4940,14 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
4907
4940
  } else if (uploadToMux) {
4908
4941
  let outcome;
4909
4942
  try {
4910
- outcome = await replaceAndCreateTextTrack({
4943
+ outcome = await replaceSourceTrack({
4911
4944
  assetId,
4945
+ sourceTrackId: trackId,
4912
4946
  target: outputTrack,
4913
4947
  policy: replaceExistingTracks,
4914
4948
  presignedUrl,
4915
4949
  closedCaptions: sourceTrack.closed_captions,
4916
4950
  passthrough: trackPassthrough,
4917
- keepTrackIds,
4918
4951
  credentials
4919
4952
  });
4920
4953
  } catch (error) {
@@ -5486,17 +5519,15 @@ async function transformShotsResponse(data) {
5486
5519
  status: "pending",
5487
5520
  createdAt: data.created_at
5488
5521
  };
5489
- case "errored": {
5490
- const details = data.errors ?? data.error;
5522
+ case "errored":
5491
5523
  return {
5492
5524
  status: "errored",
5493
5525
  createdAt: data.created_at,
5494
5526
  error: {
5495
- type: details?.type ?? "unknown",
5496
- messages: details?.messages ?? []
5527
+ type: data.errors?.type ?? "unknown",
5528
+ messages: data.errors?.messages ?? []
5497
5529
  }
5498
5530
  };
5499
- }
5500
5531
  case "completed":
5501
5532
  if (!data.shots_manifest_url) {
5502
5533
  throw new Error("Completed shots response is missing shots_manifest_url");