@mux/ai 0.9.0 → 0.10.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, b as Hotspot, c as HotspotOptions, d as HotspotResponse, T as ThumbnailOptions, e as TranscriptFetchOptions, f as TranscriptResult, V as VTTCue, g as buildTranscriptUrl, h as chunkByTokens, j as chunkText, k as chunkVTTCues, l as estimateTokenCount, m as extractTextFromVTT, n as extractTimestampedTranscript, o as fetchTranscriptForAsset, p as findCaptionTrack, q as getHeatmapForAsset, r as getHeatmapForPlaybackId, s as getHeatmapForVideo, t as getHotspotsForAsset, u as getHotspotsForPlaybackId, v as getHotspotsForVideo, w as getReadyTextTracks, x as getStoryboardUrl, y as getThumbnailUrls, z as parseVTTCues, A as secondsToTimestamp, B as vttTimestampToSeconds } from '../index-Nxf6BaBO.js';
1
+ export { D as DEFAULT_STORYBOARD_WIDTH, H as HeatmapOptions, a as HeatmapResponse, b as Hotspot, c as HotspotOptions, d as HotspotResponse, T as ThumbnailOptions, e as TranscriptFetchOptions, f as TranscriptResult, V as VTTCue, g as VTTCueBudgetChunkingOptions, h as VTTDurationChunk, j as VTTDurationChunkingOptions, k as buildTranscriptUrl, l as buildVttFromCueBlocks, m as buildVttFromTranslatedCueBlocks, n as chunkByTokens, o as chunkText, p as chunkVTTCues, q as chunkVTTCuesByBudget, r as chunkVTTCuesByDuration, s as concatenateVttSegments, t as estimateTokenCount, u as extractTextFromVTT, v as extractTimestampedTranscript, w as fetchTranscriptForAsset, x as findCaptionTrack, y as getHeatmapForAsset, z as getHeatmapForPlaybackId, A as getHeatmapForVideo, B as getHotspotsForAsset, C as getHotspotsForPlaybackId, E as getHotspotsForVideo, F as getReadyTextTracks, G as getStoryboardUrl, I as getThumbnailUrls, J as parseVTTCues, K as replaceCueText, L as secondsToTimestamp, M as splitVttPreambleAndCueBlocks, N as vttTimestampToSeconds } from '../index-C8-E3VR9.js';
2
2
  import '../types-BRbaGW3t.js';
3
3
  import '@mux/mux-node';
@@ -679,6 +679,14 @@ async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, sh
679
679
  }
680
680
 
681
681
  // src/primitives/text-chunking.ts
682
+ var DEFAULT_MIN_CHUNK_DURATION_RATIO = 2 / 3;
683
+ var DEFAULT_BOUNDARY_LOOKAHEAD_CUES = 12;
684
+ var DEFAULT_BOUNDARY_PAUSE_SECONDS = 1.25;
685
+ var STRONG_BOUNDARY_SCORE = 4;
686
+ var PREFERRED_BOUNDARY_WINDOW_SECONDS = 5 * 60;
687
+ var SENTENCE_BOUNDARY_REGEX = /[.!?]["')\]]*$/;
688
+ var CLAUSE_BOUNDARY_REGEX = /[,;:]["')\]]*$/;
689
+ var NEXT_SENTENCE_START_REGEX = /^[A-Z0-9"'([{]/;
682
690
  function estimateTokenCount(text) {
683
691
  const words = text.trim().split(/\s+/).length;
684
692
  return Math.ceil(words / 0.75);
@@ -751,6 +759,151 @@ function chunkVTTCues(cues, maxTokens, overlapCues = 2) {
751
759
  }
752
760
  return chunks;
753
761
  }
762
+ function scoreCueBoundary(cues, index, boundaryPauseSeconds) {
763
+ const cue = cues[index];
764
+ const nextCue = cues[index + 1];
765
+ if (!nextCue) {
766
+ return Number.POSITIVE_INFINITY;
767
+ }
768
+ const trimmedText = cue.text.trim();
769
+ let score = 0;
770
+ if (SENTENCE_BOUNDARY_REGEX.test(trimmedText)) {
771
+ score += 4;
772
+ } else if (CLAUSE_BOUNDARY_REGEX.test(trimmedText)) {
773
+ score += 2;
774
+ }
775
+ if (nextCue.startTime - cue.endTime >= boundaryPauseSeconds) {
776
+ score += 2;
777
+ }
778
+ if (NEXT_SENTENCE_START_REGEX.test(nextCue.text.trim())) {
779
+ score += 1;
780
+ }
781
+ return score;
782
+ }
783
+ function chunkVTTCuesByBudget(cues, options) {
784
+ if (cues.length === 0) {
785
+ return [];
786
+ }
787
+ const maxCuesPerChunk = Math.max(1, options.maxCuesPerChunk);
788
+ let maxTextTokensPerChunk = Number.POSITIVE_INFINITY;
789
+ if (options.maxTextTokensPerChunk) {
790
+ maxTextTokensPerChunk = Math.max(1, options.maxTextTokensPerChunk);
791
+ }
792
+ const chunks = [];
793
+ let chunkIndex = 0;
794
+ let cueStartIndex = 0;
795
+ let currentTokenCount = 0;
796
+ for (let cueIndex = 0; cueIndex < cues.length; cueIndex++) {
797
+ const cue = cues[cueIndex];
798
+ const cueTokenCount = estimateTokenCount(cue.text);
799
+ const currentCueCount = cueIndex - cueStartIndex;
800
+ const wouldExceedCueCount = currentCueCount >= maxCuesPerChunk;
801
+ const wouldExceedTokenCount = currentCueCount > 0 && currentTokenCount + cueTokenCount > maxTextTokensPerChunk;
802
+ if (wouldExceedCueCount || wouldExceedTokenCount) {
803
+ chunks.push({
804
+ id: `chunk-${chunkIndex}`,
805
+ cueStartIndex,
806
+ cueEndIndex: cueIndex - 1,
807
+ cueCount: cueIndex - cueStartIndex,
808
+ startTime: cues[cueStartIndex].startTime,
809
+ endTime: cues[cueIndex - 1].endTime
810
+ });
811
+ cueStartIndex = cueIndex;
812
+ currentTokenCount = 0;
813
+ chunkIndex++;
814
+ }
815
+ currentTokenCount += cueTokenCount;
816
+ }
817
+ chunks.push({
818
+ id: `chunk-${chunkIndex}`,
819
+ cueStartIndex,
820
+ cueEndIndex: cues.length - 1,
821
+ cueCount: cues.length - cueStartIndex,
822
+ startTime: cues[cueStartIndex].startTime,
823
+ endTime: cues[cues.length - 1].endTime
824
+ });
825
+ return chunks;
826
+ }
827
+ function chunkVTTCuesByDuration(cues, options) {
828
+ if (cues.length === 0) {
829
+ return [];
830
+ }
831
+ const targetChunkDurationSeconds = Math.max(1, options.targetChunkDurationSeconds);
832
+ const maxChunkDurationSeconds = Math.max(targetChunkDurationSeconds, options.maxChunkDurationSeconds);
833
+ const minChunkDurationSeconds = Math.min(
834
+ targetChunkDurationSeconds,
835
+ Math.max(
836
+ 1,
837
+ options.minChunkDurationSeconds ?? Math.floor(targetChunkDurationSeconds * DEFAULT_MIN_CHUNK_DURATION_RATIO)
838
+ )
839
+ );
840
+ const boundaryLookaheadCues = Math.max(1, options.boundaryLookaheadCues ?? DEFAULT_BOUNDARY_LOOKAHEAD_CUES);
841
+ const boundaryPauseSeconds = options.boundaryPauseSeconds ?? DEFAULT_BOUNDARY_PAUSE_SECONDS;
842
+ const preferredBoundaryStartSeconds = Math.max(
843
+ minChunkDurationSeconds,
844
+ targetChunkDurationSeconds - Math.min(PREFERRED_BOUNDARY_WINDOW_SECONDS, targetChunkDurationSeconds / 6)
845
+ );
846
+ const chunks = [];
847
+ let chunkIndex = 0;
848
+ let cueStartIndex = 0;
849
+ while (cueStartIndex < cues.length) {
850
+ const chunkStartTime = cues[cueStartIndex].startTime;
851
+ let cueEndIndex = cueStartIndex;
852
+ let bestBoundaryIndex = -1;
853
+ let bestBoundaryScore = -1;
854
+ let bestPreferredBoundaryIndex = -1;
855
+ let bestPreferredBoundaryScore = -1;
856
+ while (cueEndIndex < cues.length) {
857
+ const cue = cues[cueEndIndex];
858
+ const currentDuration = cue.endTime - chunkStartTime;
859
+ if (currentDuration >= minChunkDurationSeconds) {
860
+ const boundaryScore = scoreCueBoundary(cues, cueEndIndex, boundaryPauseSeconds);
861
+ if (boundaryScore >= bestBoundaryScore) {
862
+ bestBoundaryIndex = cueEndIndex;
863
+ bestBoundaryScore = boundaryScore;
864
+ }
865
+ if (currentDuration >= preferredBoundaryStartSeconds && boundaryScore >= bestPreferredBoundaryScore) {
866
+ bestPreferredBoundaryIndex = cueEndIndex;
867
+ bestPreferredBoundaryScore = boundaryScore;
868
+ }
869
+ }
870
+ const nextCue = cues[cueEndIndex + 1];
871
+ if (!nextCue) {
872
+ break;
873
+ }
874
+ const nextDuration = nextCue.endTime - chunkStartTime;
875
+ const lookaheadExceeded = cueEndIndex - cueStartIndex >= boundaryLookaheadCues;
876
+ const preferredBoundaryIndex = bestPreferredBoundaryIndex >= cueStartIndex ? bestPreferredBoundaryIndex : bestBoundaryIndex;
877
+ const preferredBoundaryScore = bestPreferredBoundaryIndex >= cueStartIndex ? bestPreferredBoundaryScore : bestBoundaryScore;
878
+ if (currentDuration >= targetChunkDurationSeconds) {
879
+ if (preferredBoundaryIndex >= cueStartIndex && preferredBoundaryScore >= STRONG_BOUNDARY_SCORE) {
880
+ cueEndIndex = preferredBoundaryIndex;
881
+ break;
882
+ }
883
+ if (nextDuration > maxChunkDurationSeconds || lookaheadExceeded) {
884
+ cueEndIndex = preferredBoundaryIndex >= cueStartIndex ? preferredBoundaryIndex : cueEndIndex;
885
+ break;
886
+ }
887
+ }
888
+ if (nextDuration > maxChunkDurationSeconds) {
889
+ cueEndIndex = preferredBoundaryIndex >= cueStartIndex ? preferredBoundaryIndex : cueEndIndex;
890
+ break;
891
+ }
892
+ cueEndIndex++;
893
+ }
894
+ chunks.push({
895
+ id: `chunk-${chunkIndex}`,
896
+ cueStartIndex,
897
+ cueEndIndex,
898
+ cueCount: cueEndIndex - cueStartIndex + 1,
899
+ startTime: cues[cueStartIndex].startTime,
900
+ endTime: cues[cueEndIndex].endTime
901
+ });
902
+ cueStartIndex = cueEndIndex + 1;
903
+ chunkIndex++;
904
+ }
905
+ return chunks;
906
+ }
754
907
  function chunkText(text, strategy) {
755
908
  switch (strategy.type) {
756
909
  case "token": {
@@ -792,10 +945,8 @@ async function getThumbnailUrls(playbackId, duration, options = {}) {
792
945
  }
793
946
  const baseUrl = getMuxThumbnailBaseUrl(playbackId);
794
947
  const urlPromises = timestamps.map(async (time) => {
795
- if (shouldSign) {
796
- return signUrl(baseUrl, playbackId, "thumbnail", { time, width }, credentials);
797
- }
798
- return `${baseUrl}?time=${time}&width=${width}`;
948
+ const url = shouldSign ? await signUrl(baseUrl, playbackId, "thumbnail", { time, width }, credentials) : `${baseUrl}?time=${time}&width=${width}`;
949
+ return { url, time };
799
950
  });
800
951
  return Promise.all(urlPromises);
801
952
  }
@@ -817,24 +968,82 @@ function findCaptionTrack(asset, languageCode) {
817
968
  (track) => track.text_type === "subtitles" && track.language_code === languageCode
818
969
  );
819
970
  }
971
+ function normalizeLineEndings(value) {
972
+ return value.replace(/\r\n/g, "\n");
973
+ }
974
+ function isTimingLine(line) {
975
+ return line.includes("-->");
976
+ }
977
+ function parseNumericCueIdentifier(line) {
978
+ if (!/^\d+$/.test(line)) {
979
+ return null;
980
+ }
981
+ return Number.parseInt(line, 10);
982
+ }
983
+ function isLikelyTitledCueIdentifier(line) {
984
+ return /^\d+\s+-\s+\S.*$/.test(line);
985
+ }
986
+ function isLikelyCueIdentifier({
987
+ line,
988
+ nextLine,
989
+ previousCueIdentifier
990
+ }) {
991
+ if (!line || !nextLine || !isTimingLine(nextLine)) {
992
+ return false;
993
+ }
994
+ const numericIdentifier = parseNumericCueIdentifier(line);
995
+ if (numericIdentifier !== null) {
996
+ if (previousCueIdentifier === null || previousCueIdentifier === void 0) {
997
+ return numericIdentifier === 1;
998
+ }
999
+ return numericIdentifier === previousCueIdentifier + 1;
1000
+ }
1001
+ return isLikelyTitledCueIdentifier(line);
1002
+ }
1003
+ function getCueIdentifierLineIndex(lines, timingLineIndex, previousCueIdentifier) {
1004
+ const identifierIndex = timingLineIndex - 1;
1005
+ if (identifierIndex < 0) {
1006
+ return -1;
1007
+ }
1008
+ const candidate = lines[identifierIndex].trim();
1009
+ if (!candidate || isTimingLine(candidate)) {
1010
+ return -1;
1011
+ }
1012
+ return isLikelyCueIdentifier({
1013
+ line: candidate,
1014
+ nextLine: lines[timingLineIndex]?.trim(),
1015
+ previousCueIdentifier
1016
+ }) ? identifierIndex : -1;
1017
+ }
820
1018
  function extractTextFromVTT(vttContent) {
821
1019
  if (!vttContent.trim()) {
822
1020
  return "";
823
1021
  }
824
1022
  const lines = vttContent.split("\n");
825
1023
  const textLines = [];
1024
+ let previousCueIdentifier = null;
1025
+ let isInsideNoteBlock = false;
826
1026
  for (let i = 0; i < lines.length; i++) {
827
1027
  const line = lines[i].trim();
828
- if (!line)
1028
+ const nextLine = lines[i + 1]?.trim();
1029
+ if (!line) {
1030
+ isInsideNoteBlock = false;
1031
+ continue;
1032
+ }
1033
+ if (isInsideNoteBlock)
829
1034
  continue;
830
1035
  if (line === "WEBVTT")
831
1036
  continue;
832
- if (line.startsWith("NOTE "))
1037
+ if (line === "NOTE" || line.startsWith("NOTE ")) {
1038
+ isInsideNoteBlock = true;
833
1039
  continue;
834
- if (line.includes("-->"))
1040
+ }
1041
+ if (isTimingLine(line))
835
1042
  continue;
836
- if (/^[\w-]+$/.test(line) && !line.includes(" "))
1043
+ if (isLikelyCueIdentifier({ line, nextLine, previousCueIdentifier })) {
1044
+ previousCueIdentifier = parseNumericCueIdentifier(line);
837
1045
  continue;
1046
+ }
838
1047
  if (line.startsWith("STYLE") || line.startsWith("REGION"))
839
1048
  continue;
840
1049
  const cleanLine = line.replace(/<[^>]*>/g, "").trim();
@@ -893,20 +1102,34 @@ function parseVTTCues(vttContent) {
893
1102
  return [];
894
1103
  const lines = vttContent.split("\n");
895
1104
  const cues = [];
1105
+ let previousCueIdentifier = null;
896
1106
  for (let i = 0; i < lines.length; i++) {
897
1107
  const line = lines[i].trim();
898
- if (line.includes("-->")) {
1108
+ if (isTimingLine(line)) {
899
1109
  const [startStr, endStr] = line.split(" --> ").map((s) => s.trim());
900
1110
  const startTime = vttTimestampToSeconds(startStr);
901
1111
  const endTime = vttTimestampToSeconds(endStr.split(" ")[0]);
902
- const textLines = [];
1112
+ const currentCueIdentifierLine = lines[i - 1]?.trim() ?? "";
1113
+ const currentCueIdentifier = isLikelyCueIdentifier({
1114
+ line: currentCueIdentifierLine,
1115
+ nextLine: line,
1116
+ previousCueIdentifier
1117
+ }) ? parseNumericCueIdentifier(currentCueIdentifierLine) : null;
1118
+ const rawTextLines = [];
903
1119
  let j = i + 1;
904
- while (j < lines.length && lines[j].trim() && !lines[j].includes("-->")) {
905
- const cleanLine = lines[j].trim().replace(/<[^>]*>/g, "");
906
- if (cleanLine)
907
- textLines.push(cleanLine);
1120
+ while (j < lines.length && lines[j].trim() && !isTimingLine(lines[j].trim())) {
1121
+ rawTextLines.push(lines[j].trim());
908
1122
  j++;
909
1123
  }
1124
+ const trailingNumericLine = parseNumericCueIdentifier(rawTextLines.at(-1) ?? "");
1125
+ if (trailingNumericLine !== null && isLikelyCueIdentifier({
1126
+ line: rawTextLines.at(-1) ?? "",
1127
+ nextLine: lines[j]?.trim(),
1128
+ previousCueIdentifier: currentCueIdentifier
1129
+ }) && rawTextLines.length > 1) {
1130
+ rawTextLines.pop();
1131
+ }
1132
+ const textLines = rawTextLines.map((textLine) => textLine.replace(/<[^>]*>/g, "")).filter(Boolean);
910
1133
  if (textLines.length > 0) {
911
1134
  cues.push({
912
1135
  startTime,
@@ -914,10 +1137,102 @@ function parseVTTCues(vttContent) {
914
1137
  text: textLines.join(" ")
915
1138
  });
916
1139
  }
1140
+ previousCueIdentifier = currentCueIdentifier;
917
1141
  }
918
1142
  }
919
1143
  return cues;
920
1144
  }
1145
+ function splitVttPreambleAndCueBlocks(vttContent) {
1146
+ const normalizedContent = normalizeLineEndings(vttContent).trim();
1147
+ if (!normalizedContent) {
1148
+ return {
1149
+ preamble: "WEBVTT",
1150
+ cueBlocks: []
1151
+ };
1152
+ }
1153
+ const rawBlocks = normalizedContent.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
1154
+ const cueBlockStartIndex = rawBlocks.findIndex((block) => block.includes("-->"));
1155
+ if (cueBlockStartIndex === -1) {
1156
+ return {
1157
+ preamble: normalizedContent.startsWith("WEBVTT") ? normalizedContent : `WEBVTT
1158
+
1159
+ ${normalizedContent}`,
1160
+ cueBlocks: []
1161
+ };
1162
+ }
1163
+ const hasMergedCueBlocks = rawBlocks.slice(cueBlockStartIndex).some((block) => (block.match(/-->/g) ?? []).length > 1);
1164
+ if (hasMergedCueBlocks) {
1165
+ const lines = normalizedContent.split("\n");
1166
+ const timingLineIndices = lines.map((line, index) => isTimingLine(line.trim()) ? index : -1).filter((index) => index >= 0);
1167
+ let previousCueIdentifier = null;
1168
+ const firstCueStartIndex = getCueIdentifierLineIndex(lines, timingLineIndices[0], previousCueIdentifier);
1169
+ const preambleEndIndex = firstCueStartIndex >= 0 ? firstCueStartIndex : timingLineIndices[0];
1170
+ const preamble2 = lines.slice(0, preambleEndIndex).join("\n").trim() || "WEBVTT";
1171
+ const cueBlocks2 = timingLineIndices.map((timingLineIndex, index) => {
1172
+ const cueIdentifierLineIndex = getCueIdentifierLineIndex(lines, timingLineIndex, previousCueIdentifier);
1173
+ const cueStartIndex = cueIdentifierLineIndex >= 0 ? cueIdentifierLineIndex : timingLineIndex;
1174
+ const currentCueIdentifier = cueIdentifierLineIndex >= 0 ? parseNumericCueIdentifier(lines[cueIdentifierLineIndex].trim()) : null;
1175
+ const nextTimingLineIndex = timingLineIndices[index + 1] ?? lines.length;
1176
+ let cueEndIndex = nextTimingLineIndex - 1;
1177
+ while (cueEndIndex > timingLineIndex && !lines[cueEndIndex].trim()) {
1178
+ cueEndIndex--;
1179
+ }
1180
+ const nextCueIdentifierLineIndex = index < timingLineIndices.length - 1 ? getCueIdentifierLineIndex(lines, nextTimingLineIndex, currentCueIdentifier) : -1;
1181
+ if (nextCueIdentifierLineIndex === cueEndIndex) {
1182
+ cueEndIndex--;
1183
+ }
1184
+ while (cueEndIndex > timingLineIndex && !lines[cueEndIndex].trim()) {
1185
+ cueEndIndex--;
1186
+ }
1187
+ previousCueIdentifier = currentCueIdentifier;
1188
+ return lines.slice(cueStartIndex, cueEndIndex + 1).join("\n").trim();
1189
+ });
1190
+ return {
1191
+ preamble: preamble2,
1192
+ cueBlocks: cueBlocks2
1193
+ };
1194
+ }
1195
+ const preambleBlocks = rawBlocks.slice(0, cueBlockStartIndex);
1196
+ const cueBlocks = rawBlocks.slice(cueBlockStartIndex);
1197
+ const preamble = preambleBlocks.length > 0 ? preambleBlocks.join("\n\n") : "WEBVTT";
1198
+ return {
1199
+ preamble,
1200
+ cueBlocks
1201
+ };
1202
+ }
1203
+ function buildVttFromCueBlocks(cueBlocks, preamble = "WEBVTT") {
1204
+ if (cueBlocks.length === 0) {
1205
+ return `${preamble.trim()}
1206
+ `;
1207
+ }
1208
+ return `${preamble.trim()}
1209
+
1210
+ ${cueBlocks.map((block) => block.trim()).join("\n\n")}
1211
+ `;
1212
+ }
1213
+ function replaceCueText(cueBlock, translatedText) {
1214
+ const lines = normalizeLineEndings(cueBlock).split("\n").map((line) => line.trim()).filter(Boolean);
1215
+ const timingLineIndex = lines.findIndex((line) => line.includes("-->"));
1216
+ if (timingLineIndex === -1) {
1217
+ throw new Error("Cue block is missing a timestamp line");
1218
+ }
1219
+ const headerLines = lines.slice(0, timingLineIndex + 1);
1220
+ const translatedLines = normalizeLineEndings(translatedText).split("\n").map((line) => line.trim()).filter(Boolean);
1221
+ return [...headerLines, ...translatedLines].join("\n");
1222
+ }
1223
+ function buildVttFromTranslatedCueBlocks(cueBlocks, translatedTexts, preamble = "WEBVTT") {
1224
+ if (cueBlocks.length !== translatedTexts.length) {
1225
+ throw new Error(`Expected ${cueBlocks.length} translated cues, received ${translatedTexts.length}`);
1226
+ }
1227
+ return buildVttFromCueBlocks(
1228
+ cueBlocks.map((cueBlock, index) => replaceCueText(cueBlock, translatedTexts[index])),
1229
+ preamble
1230
+ );
1231
+ }
1232
+ function concatenateVttSegments(segments, preamble = "WEBVTT") {
1233
+ const cueBlocks = segments.flatMap((segment) => splitVttPreambleAndCueBlocks(segment).cueBlocks);
1234
+ return buildVttFromCueBlocks(cueBlocks, preamble);
1235
+ }
921
1236
  async function buildTranscriptUrl(playbackId, trackId, shouldSign = false, credentials) {
922
1237
  "use step";
923
1238
  const baseUrl = `https://stream.mux.com/${playbackId}/text/${trackId}.vtt`;
@@ -979,9 +1294,14 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
979
1294
  export {
980
1295
  DEFAULT_STORYBOARD_WIDTH,
981
1296
  buildTranscriptUrl,
1297
+ buildVttFromCueBlocks,
1298
+ buildVttFromTranslatedCueBlocks,
982
1299
  chunkByTokens,
983
1300
  chunkText,
984
1301
  chunkVTTCues,
1302
+ chunkVTTCuesByBudget,
1303
+ chunkVTTCuesByDuration,
1304
+ concatenateVttSegments,
985
1305
  estimateTokenCount,
986
1306
  extractTextFromVTT,
987
1307
  extractTimestampedTranscript,
@@ -997,7 +1317,9 @@ export {
997
1317
  getStoryboardUrl,
998
1318
  getThumbnailUrls,
999
1319
  parseVTTCues,
1320
+ replaceCueText,
1000
1321
  secondsToTimestamp,
1322
+ splitVttPreambleAndCueBlocks,
1001
1323
  vttTimestampToSeconds
1002
1324
  };
1003
1325
  //# sourceMappingURL=index.js.map