@mux/ai 0.28.1 → 0.30.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.
- package/README.md +1 -1
- package/dist/{index-bjQi1ZCj.d.ts → index-CJtQiGj7.d.ts} +18 -4
- package/dist/{index-DUVBpnj5.d.ts → index-D3cB2ltG.d.ts} +47 -15
- package/dist/index.d.ts +7 -6
- package/dist/index.js +571 -189
- package/dist/index.js.map +1 -1
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.js +122 -21
- package/dist/primitives/index.js.map +1 -1
- package/dist/{shots-mGJfYGiO.d.ts → shots-Bh0GrvLx.d.ts} +21 -1
- package/dist/workflows/index.d.ts +2 -2
- package/dist/workflows/index.js +678 -295
- package/dist/workflows/index.js.map +1 -1
- package/package.json +7 -1
|
@@ -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
|
|
2
|
-
export {
|
|
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-CJtQiGj7.js';
|
|
2
|
+
export { q as CompletedShotsResult, 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 WaitForShotsOptions, z as getHotspotsForAsset, B as getHotspotsForPlaybackId, D as getHotspotsForVideo, F as getShotsForAsset, G as requestShotsForAsset, J as waitForShotsForAsset } from '../shots-Bh0GrvLx.js';
|
|
3
3
|
import '@mux/mux-node';
|
package/dist/primitives/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var EnvSchema = z.object({
|
|
|
69
69
|
MUX_TEST_ASSET_ID_VIOLENT_AUDIO_ONLY: optionalString("Mux test asset ID for audio-only assets with violent content.", "Mux test asset id for audio-only assets with violent content for testing"),
|
|
70
70
|
// Eval config
|
|
71
71
|
MUX_AI_EVAL_MODEL_SET: optionalString("Eval model selection mode.", "Choose between 'default' (provider defaults only) or 'all' (all configured models)"),
|
|
72
|
-
MUX_AI_EVAL_MODELS: optionalString("Comma-separated eval model pairs.", "Comma-separated provider:model pairs (e.g. 'openai:gpt-5.
|
|
72
|
+
MUX_AI_EVAL_MODELS: optionalString("Comma-separated eval model pairs.", "Comma-separated provider:model pairs (e.g. 'openai:gpt-5.6-luna,anthropic:claude-sonnet-4-5,google:gemini-3-flash-preview')"),
|
|
73
73
|
// AI Providers
|
|
74
74
|
OPENAI_API_KEY: optionalString("OpenAI API key for OpenAI-backed workflows.", "OpenAI API key"),
|
|
75
75
|
ANTHROPIC_API_KEY: optionalString("Anthropic API key for Claude-backed workflows.", "Anthropic API key"),
|
|
@@ -407,16 +407,26 @@ async function resolveMuxSigningContext(credentials) {
|
|
|
407
407
|
|
|
408
408
|
// src/lib/providers.ts
|
|
409
409
|
var DEFAULT_LANGUAGE_MODELS = {
|
|
410
|
-
|
|
410
|
+
// GPT-5.6 models default to medium reasoning when no effort is specified.
|
|
411
|
+
openai: "gpt-5.6-luna",
|
|
411
412
|
anthropic: "claude-sonnet-4-5",
|
|
412
413
|
google: "gemini-3-flash-preview"
|
|
413
414
|
};
|
|
414
415
|
var LANGUAGE_MODELS = {
|
|
415
|
-
openai: ["gpt-5.1", "gpt-5-mini"],
|
|
416
|
+
openai: ["gpt-5.6-luna", "gpt-5.1", "gpt-5-mini"],
|
|
416
417
|
anthropic: ["claude-sonnet-4-5"],
|
|
417
418
|
google: ["gemini-3-flash-preview", "gemini-3.1-flash-lite", "gemini-2.5-flash"]
|
|
418
419
|
};
|
|
419
420
|
var LANGUAGE_MODEL_DEPRECATIONS = [
|
|
421
|
+
{
|
|
422
|
+
provider: "openai",
|
|
423
|
+
modelId: "gpt-5.1",
|
|
424
|
+
replacementModelId: "gpt-5.6-luna",
|
|
425
|
+
phase: "warn",
|
|
426
|
+
deprecatedOn: "2026-08-01",
|
|
427
|
+
sunsetOn: "2026-10-01",
|
|
428
|
+
reason: "GPT-5.6 Luna with its default medium reasoning effort is the new OpenAI default."
|
|
429
|
+
},
|
|
420
430
|
{
|
|
421
431
|
provider: "google",
|
|
422
432
|
modelId: "gemini-2.5-flash",
|
|
@@ -477,7 +487,7 @@ function parseEvalModelPair(value) {
|
|
|
477
487
|
const modelId = modelIdRaw?.trim();
|
|
478
488
|
if (!provider || !modelId) {
|
|
479
489
|
throw new Error(
|
|
480
|
-
`Invalid eval model pair "${value}". Use "provider:model" (example: "openai:gpt-5.
|
|
490
|
+
`Invalid eval model pair "${value}". Use "provider:model" (example: "openai:gpt-5.6-luna").`
|
|
481
491
|
);
|
|
482
492
|
}
|
|
483
493
|
if (!isSupportedProvider(provider)) {
|
|
@@ -798,7 +808,8 @@ var TOKEN_USAGE_FIELDS = [
|
|
|
798
808
|
"outputTokens",
|
|
799
809
|
"totalTokens",
|
|
800
810
|
"reasoningTokens",
|
|
801
|
-
"cachedInputTokens"
|
|
811
|
+
"cachedInputTokens",
|
|
812
|
+
"cacheWriteTokens"
|
|
802
813
|
];
|
|
803
814
|
function getErrorTokenUsage(error) {
|
|
804
815
|
if (typeof error !== "object" || error === null) {
|
|
@@ -828,6 +839,12 @@ function getErrorTokenUsage(error) {
|
|
|
828
839
|
extracted.cachedInputTokens = cacheReadTokens;
|
|
829
840
|
}
|
|
830
841
|
}
|
|
842
|
+
if (extracted.cacheWriteTokens === void 0) {
|
|
843
|
+
const cacheWriteTokens = source.inputTokenDetails?.cacheWriteTokens;
|
|
844
|
+
if (typeof cacheWriteTokens === "number") {
|
|
845
|
+
extracted.cacheWriteTokens = cacheWriteTokens;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
831
848
|
return Object.keys(extracted).length > 0 ? extracted : void 0;
|
|
832
849
|
}
|
|
833
850
|
|
|
@@ -842,6 +859,9 @@ var MuxAiError = class extends Error {
|
|
|
842
859
|
this.publicMessage = message;
|
|
843
860
|
this.retryable = opts?.retryable ?? false;
|
|
844
861
|
}
|
|
862
|
+
static is(value) {
|
|
863
|
+
return typeof value === "object" && value !== null && "__robots_error" in value && value.__robots_error === true;
|
|
864
|
+
}
|
|
845
865
|
};
|
|
846
866
|
function extractErrorDetail(error) {
|
|
847
867
|
if (error instanceof Error && error.message) {
|
|
@@ -859,7 +879,7 @@ function extractErrorDetail(error) {
|
|
|
859
879
|
return "Unknown error";
|
|
860
880
|
}
|
|
861
881
|
function wrapError(error, message) {
|
|
862
|
-
if (error
|
|
882
|
+
if (MuxAiError.is(error)) {
|
|
863
883
|
throw error;
|
|
864
884
|
}
|
|
865
885
|
const rawDetail = extractErrorDetail(error);
|
|
@@ -1111,13 +1131,22 @@ async function signUrl(url, playbackId, type = "video", params, credentials) {
|
|
|
1111
1131
|
|
|
1112
1132
|
// src/primitives/storyboards.ts
|
|
1113
1133
|
var DEFAULT_STORYBOARD_WIDTH = 640;
|
|
1114
|
-
async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, shouldSign = false, credentials) {
|
|
1134
|
+
async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, shouldSign = false, credentials, scope) {
|
|
1115
1135
|
"use step";
|
|
1116
1136
|
const baseUrl = getMuxStoryboardBaseUrl(playbackId);
|
|
1137
|
+
const params = { width };
|
|
1138
|
+
if (scope?.startTime !== void 0) {
|
|
1139
|
+
params.asset_start_time = scope.startTime;
|
|
1140
|
+
}
|
|
1141
|
+
if (scope?.endTime !== void 0) {
|
|
1142
|
+
params.asset_end_time = scope.endTime;
|
|
1143
|
+
}
|
|
1117
1144
|
if (shouldSign) {
|
|
1118
|
-
return signUrl(baseUrl, playbackId, "storyboard",
|
|
1145
|
+
return signUrl(baseUrl, playbackId, "storyboard", params, credentials);
|
|
1119
1146
|
}
|
|
1120
|
-
return `${baseUrl}
|
|
1147
|
+
return `${baseUrl}?${new URLSearchParams(
|
|
1148
|
+
Object.entries(params).map(([key, value]) => [key, String(value)])
|
|
1149
|
+
).toString()}`;
|
|
1121
1150
|
}
|
|
1122
1151
|
|
|
1123
1152
|
// src/primitives/text-chunking.ts
|
|
@@ -1358,30 +1387,77 @@ function chunkText(text, strategy) {
|
|
|
1358
1387
|
}
|
|
1359
1388
|
}
|
|
1360
1389
|
|
|
1390
|
+
// src/lib/workflow-scope.ts
|
|
1391
|
+
function hasWorkflowScopeBoundaries(scope) {
|
|
1392
|
+
return scope?.startTime !== void 0 || scope?.endTime !== void 0;
|
|
1393
|
+
}
|
|
1394
|
+
function resolveWorkflowScope(scope, assetDurationSeconds) {
|
|
1395
|
+
if (assetDurationSeconds === void 0 || !Number.isFinite(assetDurationSeconds) || assetDurationSeconds <= 0) {
|
|
1396
|
+
throw new MuxAiError("Asset has no valid duration.", { type: "validation_error" });
|
|
1397
|
+
}
|
|
1398
|
+
const startTime = scope?.startTime ?? 0;
|
|
1399
|
+
const endTime = scope?.endTime ?? assetDurationSeconds;
|
|
1400
|
+
if (!Number.isFinite(startTime) || startTime < 0) {
|
|
1401
|
+
throw new MuxAiError(
|
|
1402
|
+
`scope.startTime must be a finite, non-negative number (received ${startTime}).`,
|
|
1403
|
+
{ type: "validation_error" }
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
if (!Number.isFinite(endTime) || endTime < 0) {
|
|
1407
|
+
throw new MuxAiError(
|
|
1408
|
+
`scope.endTime must be a finite, non-negative number (received ${endTime}).`,
|
|
1409
|
+
{ type: "validation_error" }
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
if (endTime > assetDurationSeconds) {
|
|
1413
|
+
throw new MuxAiError(
|
|
1414
|
+
`scope.endTime (${endTime}) cannot exceed the asset duration (${assetDurationSeconds}).`,
|
|
1415
|
+
{ type: "validation_error" }
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
if (startTime >= endTime) {
|
|
1419
|
+
throw new MuxAiError(
|
|
1420
|
+
`scope.startTime (${startTime}) must be less than scope.endTime (${endTime}).`,
|
|
1421
|
+
{ type: "validation_error" }
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
return { startTime, endTime };
|
|
1425
|
+
}
|
|
1426
|
+
function timeRangesOverlap(firstStart, firstEnd, second) {
|
|
1427
|
+
const secondStart = second.startTime ?? 0;
|
|
1428
|
+
const secondEnd = second.endTime ?? Number.POSITIVE_INFINITY;
|
|
1429
|
+
return firstStart < secondEnd && firstEnd > secondStart;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1361
1432
|
// src/primitives/thumbnails.ts
|
|
1362
1433
|
async function getThumbnailUrls(playbackId, duration, options = {}) {
|
|
1363
1434
|
"use step";
|
|
1364
|
-
const { interval = 10, width = 640, shouldSign = false, maxSamples, credentials } = options;
|
|
1435
|
+
const { interval = 10, width = 640, shouldSign = false, maxSamples, credentials, scope } = options;
|
|
1436
|
+
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
1437
|
+
const resolvedScope = effectiveScope ? resolveWorkflowScope(effectiveScope, duration) : { startTime: 0, endTime: duration };
|
|
1438
|
+
const rangeDuration = resolvedScope.endTime - resolvedScope.startTime;
|
|
1365
1439
|
let timestamps = [];
|
|
1366
|
-
if (
|
|
1367
|
-
const spacing =
|
|
1440
|
+
if (rangeDuration <= 50) {
|
|
1441
|
+
const spacing = rangeDuration / 6;
|
|
1368
1442
|
for (let i = 1; i <= 5; i++) {
|
|
1369
|
-
|
|
1443
|
+
const time = resolvedScope.startTime + i * spacing;
|
|
1444
|
+
timestamps.push(effectiveScope ? Number(time.toFixed(3)) : Math.round(time));
|
|
1370
1445
|
}
|
|
1371
1446
|
} else {
|
|
1372
|
-
for (let time =
|
|
1447
|
+
for (let time = resolvedScope.startTime; time < resolvedScope.endTime; time += interval) {
|
|
1373
1448
|
timestamps.push(time);
|
|
1374
1449
|
}
|
|
1375
1450
|
}
|
|
1376
1451
|
if (maxSamples !== void 0 && timestamps.length > maxSamples) {
|
|
1377
1452
|
const newTimestamps = [];
|
|
1378
|
-
newTimestamps.push(
|
|
1453
|
+
newTimestamps.push(resolvedScope.startTime);
|
|
1379
1454
|
if (maxSamples >= 2) {
|
|
1380
|
-
const
|
|
1455
|
+
const lastTime = effectiveScope ? Math.max(resolvedScope.startTime, resolvedScope.endTime - 1e-3) : resolvedScope.endTime;
|
|
1456
|
+
const spacing = (lastTime - resolvedScope.startTime) / (maxSamples - 1);
|
|
1381
1457
|
for (let i = 1; i < maxSamples - 1; i++) {
|
|
1382
|
-
newTimestamps.push(spacing * i);
|
|
1458
|
+
newTimestamps.push(resolvedScope.startTime + spacing * i);
|
|
1383
1459
|
}
|
|
1384
|
-
newTimestamps.push(
|
|
1460
|
+
newTimestamps.push(lastTime);
|
|
1385
1461
|
}
|
|
1386
1462
|
timestamps = newTimestamps;
|
|
1387
1463
|
}
|
|
@@ -1792,6 +1868,23 @@ function parseVTTCues(vttContent) {
|
|
|
1792
1868
|
}
|
|
1793
1869
|
return cues;
|
|
1794
1870
|
}
|
|
1871
|
+
function filterVttByScope(vttContent, scope) {
|
|
1872
|
+
if (!scope || scope.startTime === void 0 && scope.endTime === void 0) {
|
|
1873
|
+
return vttContent;
|
|
1874
|
+
}
|
|
1875
|
+
const { preamble, cueBlocks } = splitVttPreambleAndCueBlocks(vttContent);
|
|
1876
|
+
const scopedCueBlocks = cueBlocks.filter((cueBlock) => {
|
|
1877
|
+
const cue = parseVTTCues(cueBlock)[0];
|
|
1878
|
+
return cue ? timeRangesOverlap(cue.startTime, cue.endTime, scope) : false;
|
|
1879
|
+
}).map((cueBlock, index) => {
|
|
1880
|
+
const lines = cueBlock.split("\n");
|
|
1881
|
+
if (/^\d+$/.test(lines[0]?.trim()) && lines[1]?.includes("-->")) {
|
|
1882
|
+
lines[0] = String(index + 1);
|
|
1883
|
+
}
|
|
1884
|
+
return lines.join("\n");
|
|
1885
|
+
});
|
|
1886
|
+
return buildVttFromCueBlocks(scopedCueBlocks, preamble);
|
|
1887
|
+
}
|
|
1795
1888
|
function splitVttPreambleAndCueBlocks(vttContent) {
|
|
1796
1889
|
const normalizedContent = normalizeLineEndings(vttContent).trim();
|
|
1797
1890
|
if (!normalizedContent) {
|
|
@@ -1896,6 +1989,7 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
|
|
|
1896
1989
|
const {
|
|
1897
1990
|
languageCode,
|
|
1898
1991
|
cleanTranscript = true,
|
|
1992
|
+
scope,
|
|
1899
1993
|
shouldSign,
|
|
1900
1994
|
credentials,
|
|
1901
1995
|
required = false
|
|
@@ -1927,9 +2021,15 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
|
|
|
1927
2021
|
return { transcriptText: "", transcriptUrl, track };
|
|
1928
2022
|
}
|
|
1929
2023
|
const rawVtt = await response.text();
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
|
|
2024
|
+
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
2025
|
+
const scopedVtt = filterVttByScope(rawVtt, effectiveScope);
|
|
2026
|
+
const transcriptText = cleanTranscript ? extractTextFromVTT(scopedVtt) : scopedVtt;
|
|
2027
|
+
const hasScopedCues = !effectiveScope || parseVTTCues(scopedVtt).length > 0;
|
|
2028
|
+
if (required && (!transcriptText.trim() || !hasScopedCues)) {
|
|
2029
|
+
throw new MuxAiError(
|
|
2030
|
+
effectiveScope ? "Transcript has no cues in the requested scope." : "Transcript is empty.",
|
|
2031
|
+
{ type: "validation_error" }
|
|
2032
|
+
);
|
|
1933
2033
|
}
|
|
1934
2034
|
return { transcriptText, transcriptUrl, track };
|
|
1935
2035
|
} catch (error) {
|
|
@@ -1957,6 +2057,7 @@ export {
|
|
|
1957
2057
|
extractTextFromVTT,
|
|
1958
2058
|
extractTimestampedTranscript,
|
|
1959
2059
|
fetchTranscriptForAsset,
|
|
2060
|
+
filterVttByScope,
|
|
1960
2061
|
findCaptionTrack,
|
|
1961
2062
|
getHeatmapForAsset,
|
|
1962
2063
|
getHeatmapForPlaybackId,
|