@mux/ai 0.52.0 → 0.54.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,3 +1,3 @@
1
- export { D as DEFAULT_STORYBOARD_WIDTH, H as HeatmapOptions, a as HeatmapResponse, L as LOW_CONFIDENCE_THRESHOLD, M as MAX_CUE_TEXT_CHARS, T as ThumbnailOptions, b as TranscriptFetchOptions, c as TranscriptResult, V as VTTCue, d as VTTCueBudgetChunkingOptions, e as VTTDurationChunk, f as VTTDurationChunkingOptions, g as buildTranscriptUrl, h as buildVttFromCueBlocks, j as buildVttFromTranslatedCueBlocks, k as chunkByTokens, l as chunkText, m as chunkVTTCues, n as chunkVTTCuesByBudget, o as chunkVTTCuesByDuration, p as concatenateVttSegments, q as estimateTokenCount, r as extractTextFromVTT, s as extractTimestampedTranscript, t as fetchTranscriptForAsset, u as filterVttByScope, v as findCaptionTrack, w as getHeatmapForAsset, x as getHeatmapForPlaybackId, y as getHeatmapForVideo, z as getReadyTextTracks, A as getReliableLanguageCode, B as getStoryboardUrl, C as getThumbnailUrls, E as parseVTTCues, F as replaceCueText, G as sanitizeUntrustedText, I as secondsToTimestamp, J as splitVttPreambleAndCueBlocks, K as stripVttMetadataBlocks, N as vttTimestampToSeconds } from '../index-nu1UOAMW.js';
2
- export { q as CompletedShotsResult, D as DeletedShotsResult, r as ErroredShotsResult, H as Hotspot, s as HotspotOptions, t as HotspotResponse, u as PendingShotsResult, v as Shot, w as ShotRequestOptions, x as ShotsResult, y as SkippedShotsResult, z as WaitForShotsOptions, B as getHotspotsForAsset, F as getHotspotsForPlaybackId, G as getHotspotsForVideo, J as getShotsForAsset, K as requestShotsForAsset, L as waitForShotsForAsset } from '../shots-3wmvZnUV.js';
1
+ export { D as DEFAULT_STORYBOARD_WIDTH, H as HeatmapOptions, a as HeatmapResponse, T as ThumbnailOptions, V as VTTCueBudgetChunkingOptions, b as VTTDurationChunk, c as VTTDurationChunkingOptions, d as chunkByTokens, e as chunkText, f as chunkVTTCues, g as chunkVTTCuesByBudget, h as chunkVTTCuesByDuration, j as estimateTokenCount, k as getHeatmapForAsset, l as getHeatmapForPlaybackId, m as getHeatmapForVideo, n as getStoryboardUrl, o as getThumbnailUrls } from '../index-cbaPe-aE.js';
2
+ export { r as CompletedShotsResult, D as DeletedShotsResult, s as ErroredShotsResult, H as Hotspot, t as HotspotOptions, u as HotspotResponse, L as LOW_CONFIDENCE_THRESHOLD, v as MAX_CUE_TEXT_CHARS, w as ParseVTTCuesOptions, x as PendingShotsResult, y as Shot, z as ShotRequestOptions, B as ShotsResult, F as SkippedShotsResult, G as TranscriptEmptyReason, J as TranscriptFetchOptions, K as TranscriptFetchStepResult, N as TranscriptResult, q as VTTCue, O as WaitForShotsOptions, Q as buildTranscriptUrl, R as buildVttFromCueBlocks, X as buildVttFromTranslatedCueBlocks, Y as concatenateVttSegments, Z as extractTextFromVTT, _ as extractTimestampedTranscript, $ as fetchTranscriptDataForUrl, a0 as fetchTranscriptForAsset, a1 as filterVttByScope, a2 as findCaptionTrack, a3 as getHotspotsForAsset, a4 as getHotspotsForPlaybackId, a5 as getHotspotsForVideo, a6 as getReadyTextTracks, a7 as getReliableLanguageCode, a8 as getShotsForAsset, a9 as parseVTTCues, aa as replaceCueText, ab as requestShotsForAsset, ac as sanitizeUntrustedText, ad as secondsToTimestamp, ae as splitVttPreambleAndCueBlocks, af as stripVttMetadataBlocks, ag as vttTimestampToSeconds, ah as waitForShotsForAsset } from '../transcripts-BCtzC8hZ.js';
3
3
  import '@mux/ts';
@@ -921,6 +921,9 @@ var MuxAiError = class extends Error {
921
921
  super(message);
922
922
  /** Structural brand for duck-type identification. */
923
923
  this.__robots_error = true;
924
+ if (opts?.cause !== void 0) {
925
+ Object.defineProperty(this, "cause", { value: opts.cause, writable: true, configurable: true });
926
+ }
924
927
  this.name = "FatalError";
925
928
  this.publicType = opts?.type ?? "processing_error";
926
929
  this.publicMessage = message;
@@ -1916,9 +1919,10 @@ function extractTimestampedTranscript(vttContent) {
1916
1919
  segments.map((segment) => `[${Math.floor(segment.time)}s] ${segment.text}`).join("\n")
1917
1920
  );
1918
1921
  }
1919
- function parseVTTCues(vttContent) {
1922
+ function parseVTTCues(vttContent, options = {}) {
1920
1923
  if (!vttContent.trim())
1921
1924
  return [];
1925
+ const { capCueText = true } = options;
1922
1926
  const lines = vttContent.split("\n");
1923
1927
  const cues = [];
1924
1928
  let previousCueIdentifier = null;
@@ -1950,15 +1954,16 @@ function parseVTTCues(vttContent) {
1950
1954
  }
1951
1955
  const textLines = rawTextLines.map((textLine) => textLine.replace(/<[^>]*>/g, "")).filter(Boolean);
1952
1956
  if (textLines.length > 0) {
1957
+ const sanitized = sanitizeUntrustedText(textLines.join(" "));
1953
1958
  cues.push({
1954
1959
  startTime,
1955
1960
  endTime,
1956
1961
  // Sanitize at the cue boundary so every downstream consumer
1957
1962
  // (engagement-insights, translate-captions chunked path, etc.)
1958
1963
  // receives text free of invisible / bidi obfuscation. Length-
1959
- // cap the result so an adversarially oversized cue cannot
1960
- // smuggle a large injection payload into the prompt.
1961
- text: capCueTextLength(sanitizeUntrustedText(textLines.join(" ")))
1964
+ // cap the result by default so an adversarially oversized cue
1965
+ // cannot smuggle a large injection payload into a prompt.
1966
+ text: capCueText ? capCueTextLength(sanitized) : sanitized
1962
1967
  });
1963
1968
  }
1964
1969
  previousCueIdentifier = currentCueIdentifier;
@@ -2082,16 +2087,32 @@ async function buildTranscriptUrl(playbackId, trackId, shouldSign = false, crede
2082
2087
  }
2083
2088
  return baseUrl;
2084
2089
  }
2085
- async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
2090
+ async function fetchTranscriptDataForUrl(transcriptUrl, options = {}) {
2086
2091
  "use step";
2087
- const {
2088
- languageCode,
2089
- cleanTranscript = true,
2090
- scope,
2091
- shouldSign,
2092
- credentials,
2093
- required = false
2094
- } = options;
2092
+ const { cleanTranscript = true, scope } = options;
2093
+ try {
2094
+ const response = await fetch(transcriptUrl);
2095
+ if (!response.ok) {
2096
+ throw new Error(`Failed to fetch transcript (HTTP ${response.status})`);
2097
+ }
2098
+ const rawVtt = await response.text();
2099
+ const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
2100
+ const scopedVtt = filterVttByScope(rawVtt, effectiveScope);
2101
+ const transcriptText = cleanTranscript ? extractTextFromVTT(scopedVtt) : scopedVtt;
2102
+ const hasScopedCues = !effectiveScope || parseVTTCues(scopedVtt).length > 0;
2103
+ if (!transcriptText.trim() || !hasScopedCues) {
2104
+ return {
2105
+ transcriptText,
2106
+ emptyReason: hasScopedCues ? "empty_body" : "no_scoped_cues"
2107
+ };
2108
+ }
2109
+ return { transcriptText };
2110
+ } catch (error) {
2111
+ wrapError(error, "Failed to fetch transcript");
2112
+ }
2113
+ }
2114
+ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
2115
+ const { required = false, languageCode, cleanTranscript, scope, shouldSign, credentials } = options;
2095
2116
  const track = findCaptionTrack(asset, languageCode);
2096
2117
  if (!track) {
2097
2118
  if (required) {
@@ -2110,33 +2131,25 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
2110
2131
  return { transcriptText: "", track };
2111
2132
  }
2112
2133
  const transcriptUrl = await buildTranscriptUrl(playbackId, track.id, shouldSign, credentials);
2134
+ let result;
2113
2135
  try {
2114
- const response = await fetch(transcriptUrl);
2115
- if (!response.ok) {
2116
- if (required) {
2117
- throw new Error(`Failed to fetch transcript (HTTP ${response.status})`);
2118
- }
2119
- return { transcriptText: "", transcriptUrl, track };
2120
- }
2121
- const rawVtt = await response.text();
2122
- const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
2123
- const scopedVtt = filterVttByScope(rawVtt, effectiveScope);
2124
- const transcriptText = cleanTranscript ? extractTextFromVTT(scopedVtt) : scopedVtt;
2125
- const hasScopedCues = !effectiveScope || parseVTTCues(scopedVtt).length > 0;
2126
- if (required && (!transcriptText.trim() || !hasScopedCues)) {
2127
- throw new MuxAiError(
2128
- effectiveScope ? "Transcript has no cues in the requested scope." : "Transcript is empty.",
2129
- { type: "validation_error" }
2130
- );
2131
- }
2132
- return { transcriptText, transcriptUrl, track };
2136
+ result = await fetchTranscriptDataForUrl(transcriptUrl, { cleanTranscript, scope });
2133
2137
  } catch (error) {
2134
2138
  if (required) {
2135
- wrapError(error, "Failed to fetch transcript");
2139
+ throw error;
2136
2140
  }
2137
2141
  console.warn("Failed to fetch transcript:", error);
2138
2142
  return { transcriptText: "", transcriptUrl, track };
2139
2143
  }
2144
+ if (!required || !result.emptyReason) {
2145
+ return { transcriptText: result.transcriptText, transcriptUrl, track };
2146
+ }
2147
+ switch (result.emptyReason) {
2148
+ case "no_scoped_cues":
2149
+ throw new MuxAiError("Transcript has no cues in the requested scope.", { type: "validation_error" });
2150
+ case "empty_body":
2151
+ throw new MuxAiError("Transcript is empty.", { type: "validation_error" });
2152
+ }
2140
2153
  }
2141
2154
  export {
2142
2155
  DEFAULT_STORYBOARD_WIDTH,
@@ -2154,6 +2167,7 @@ export {
2154
2167
  estimateTokenCount,
2155
2168
  extractTextFromVTT,
2156
2169
  extractTimestampedTranscript,
2170
+ fetchTranscriptDataForUrl,
2157
2171
  fetchTranscriptForAsset,
2158
2172
  filterVttByScope,
2159
2173
  findCaptionTrack,