@mux/ai 0.35.0 → 0.37.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 +3 -0
- package/dist/{index-fU3hmKZu.d.ts → index-BupL84pY.d.ts} +24 -3
- package/dist/{index-SjpXUdXl.d.ts → index-C2Pk7bbF.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +63 -15
- package/dist/index.js.map +1 -1
- package/dist/primitives/index.d.ts +2 -2
- package/dist/primitives/index.js.map +1 -1
- package/dist/{shots-BMbViFbZ.d.ts → shots-CUI09Ohe.d.ts} +6 -0
- package/dist/workflows/index.d.ts +2 -2
- package/dist/workflows/index.js +62 -14
- package/dist/workflows/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -89,6 +89,12 @@ interface WorkflowMuxClient {
|
|
|
89
89
|
interface MuxAIOptions {
|
|
90
90
|
/** Optional timeout (ms) for helper utilities that support request limits. */
|
|
91
91
|
timeout?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Optional asset snapshot to reuse instead of retrieving the asset from Mux.
|
|
94
|
+
* The snapshot must belong to `assetId`; callers should capture it immediately
|
|
95
|
+
* before starting the workflow.
|
|
96
|
+
*/
|
|
97
|
+
assetSnapshot?: MuxAsset;
|
|
92
98
|
/**
|
|
93
99
|
* Optional credentials for workflow execution.
|
|
94
100
|
* Use encryptForWorkflow when running in Workflow Dev Kit environments.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { A as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, j as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, k as ASK_QUESTIONS_MAX_QUESTION_LENGTH, l as AskQuestionsOptions, m as AskQuestionsResult, n as AskQuestionsType, o as AudioTranslationOptions, p as AudioTranslationResult, q as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, r as BurnedInCaptionsOptions, s as BurnedInCaptionsPromptOverrides, u as BurnedInCaptionsPromptSections, v as BurnedInCaptionsResult, C as CaptionReplacement, w as CensorMode, x as Chapter, y as ChapterSystemPromptSections, z as ChaptersOptions, D as ChaptersPromptOverrides, E as ChaptersPromptSections, F as ChaptersResult, G as ChaptersType, H as DEFAULT_DESCRIPTION_LENGTH, J as DEFAULT_SUMMARY_KEYWORD_LIMIT, K as DEFAULT_TITLE_LENGTH, M as EditCaptionsOptions, N as EditCaptionsResult, O as EmbeddingsOptions, P as EmbeddingsResult, Q as EngagementInsightsOptions, R as EngagementInsightsResult, T as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, U as HIVE_SEXUAL_CATEGORIES, V as HIVE_VIOLENCE_CATEGORIES, W as HiveModerationOutput, X as HiveModerationSource, Y as ModerationOptions, Z as ModerationProvider, _ as ModerationResult, $ as MomentInsight, a0 as OverallInsight, a1 as ProfanityDetectionPayload, a2 as Question, a3 as QuestionAnswer, a4 as QuestionAnswerType, a5 as ReplacementRecord, a6 as
|
|
1
|
+
export { A as ASK_QUESTIONS_DEFAULT_MAX_ANSWER_OPTION_LENGTH, j as ASK_QUESTIONS_DEFAULT_MAX_FREE_FORM_ANSWER_LENGTH, k as ASK_QUESTIONS_MAX_QUESTION_LENGTH, l as AskQuestionsOptions, m as AskQuestionsResult, n as AskQuestionsType, o as AudioTranslationOptions, p as AudioTranslationResult, q as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, r as BurnedInCaptionsOptions, s as BurnedInCaptionsPromptOverrides, u as BurnedInCaptionsPromptSections, v as BurnedInCaptionsResult, C as CaptionReplacement, w as CensorMode, x as Chapter, y as ChapterSystemPromptSections, z as ChaptersOptions, D as ChaptersPromptOverrides, E as ChaptersPromptSections, F as ChaptersResult, G as ChaptersType, H as DEFAULT_DESCRIPTION_LENGTH, J as DEFAULT_SUMMARY_KEYWORD_LIMIT, K as DEFAULT_TITLE_LENGTH, M as EditCaptionsOptions, N as EditCaptionsResult, O as EmbeddingsOptions, P as EmbeddingsResult, Q as EngagementInsightsOptions, R as EngagementInsightsResult, T as GOOGLE_VISION_LIKELIHOOD_TO_SCORE, U as HIVE_SEXUAL_CATEGORIES, V as HIVE_VIOLENCE_CATEGORIES, W as HiveModerationOutput, X as HiveModerationSource, Y as ModerationOptions, Z as ModerationProvider, _ as ModerationResult, $ as MomentInsight, a0 as OverallInsight, a1 as ProfanityDetectionPayload, a2 as Question, a3 as QuestionAnswer, a4 as QuestionAnswerType, a5 as ReplacementRecord, a6 as SpeakerReplacement, a7 as StaticRenditionCleanupOutcome, a8 as SummarizationOptions, a9 as SummarizationPromptOverrides, aa as SummarizationPromptSections, ab as SummaryAndTagsResult, ac as SummaryType, ad as ThumbnailModerationScore, ae as TranslationChunkingOptions, af as TranslationOptions, ag as TranslationPayload, ah as TranslationResult, ai as aggregateTokenUsage, aj as applyOverrideLists, ak as applyReplacements, al as applySpeakerReplacements, am as askQuestions, an as buildReplacementRegex, ao as burnedInCaptionsSchema, ap as censorVttContent, aq as chapterSchema, ar as chaptersSchema, as as createReplacer, at as editCaptions, au as extractTranscriptSegmentsForHotspots, av as generateChapters, aw as generateEmbeddings, ax as generateEngagementInsights, ay as generateVideoEmbeddings, az as getModerationScores, aA as getSummaryAndTags, aB as hasBurnedInCaptions, aC as mapShotsToHotspots, aD as normalizeTranslatedVtt, aE as profanityDetectionSchema, aF as questionAnswerSchema, aG as shouldSplitChunkTranslationError, aH as summarySchema, aI as transformCueText, aJ as translateAudio, aK as translateCaptions, aL as translationSchema, aM as validateNeverTranslateTerms, aN as verifyNeverTranslateTerms } from '../index-BupL84pY.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@ai-sdk/anthropic';
|
|
4
4
|
import '@ai-sdk/google';
|
|
5
5
|
import '@ai-sdk/openai';
|
|
6
|
-
import '../shots-
|
|
6
|
+
import '../shots-CUI09Ohe.js';
|
|
7
7
|
import '@mux/mux-node';
|
package/dist/workflows/index.js
CHANGED
|
@@ -1635,9 +1635,12 @@ function toPlaybackAsset(asset) {
|
|
|
1635
1635
|
const { id: playbackId, policy } = getPlaybackId(asset);
|
|
1636
1636
|
return { asset, playbackId, policy };
|
|
1637
1637
|
}
|
|
1638
|
-
async function getPlaybackIdForAsset(assetId, credentials) {
|
|
1638
|
+
async function getPlaybackIdForAsset(assetId, credentials, assetSnapshot) {
|
|
1639
1639
|
"use step";
|
|
1640
|
-
const asset = await getMuxAsset(assetId, credentials);
|
|
1640
|
+
const asset = assetSnapshot ?? await getMuxAsset(assetId, credentials);
|
|
1641
|
+
if (asset.id !== assetId) {
|
|
1642
|
+
throw new MuxAiError("Asset snapshot does not match the requested asset ID.", { type: "validation_error" });
|
|
1643
|
+
}
|
|
1641
1644
|
return toPlaybackAsset(asset);
|
|
1642
1645
|
}
|
|
1643
1646
|
async function getMuxAsset(assetId, credentials) {
|
|
@@ -3023,7 +3026,7 @@ async function askQuestionsInternal(assetId, questions, options, collectedUsage)
|
|
|
3023
3026
|
model,
|
|
3024
3027
|
provider
|
|
3025
3028
|
});
|
|
3026
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
3029
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options?.assetSnapshot);
|
|
3027
3030
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
3028
3031
|
const isAudioOnly = isAudioOnlyAsset(assetData);
|
|
3029
3032
|
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
@@ -3377,7 +3380,7 @@ async function hasBurnedInCaptionsInternal(assetId, options, collectedUsage) {
|
|
|
3377
3380
|
model,
|
|
3378
3381
|
provider
|
|
3379
3382
|
});
|
|
3380
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
3383
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
3381
3384
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
3382
3385
|
const storyboardScope = resolveRenderableVideoScope(
|
|
3383
3386
|
scope,
|
|
@@ -3642,7 +3645,7 @@ async function generateChaptersInternal(assetId, options, collectedUsage) {
|
|
|
3642
3645
|
model,
|
|
3643
3646
|
provider
|
|
3644
3647
|
});
|
|
3645
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
3648
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
3646
3649
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
3647
3650
|
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
3648
3651
|
const resolvedScope = effectiveScope ? resolveWorkflowScope(effectiveScope, assetDurationSeconds) : void 0;
|
|
@@ -4204,6 +4207,27 @@ function applyReplacements(rawVtt, replacements) {
|
|
|
4204
4207
|
});
|
|
4205
4208
|
return { editedVtt, replacements: records };
|
|
4206
4209
|
}
|
|
4210
|
+
function applySpeakerReplacements(rawVtt, speakerReplacements) {
|
|
4211
|
+
const replacementsByLabel = new Map(
|
|
4212
|
+
speakerReplacements.filter((replacement) => replacement.find.length > 0).map((replacement) => [replacement.find, replacement.replace])
|
|
4213
|
+
);
|
|
4214
|
+
if (replacementsByLabel.size === 0) {
|
|
4215
|
+
return { editedVtt: rawVtt, replacements: [] };
|
|
4216
|
+
}
|
|
4217
|
+
const records = [];
|
|
4218
|
+
const editedVtt = transformCueTextBlocks(rawVtt, (cueText, cueStartTime) => {
|
|
4219
|
+
return cueText.replace(/^(\s*)\[([^\]\r\n]+)\](?=\s|$)/, (marker, leadingWhitespace, label) => {
|
|
4220
|
+
const replacement = replacementsByLabel.get(label);
|
|
4221
|
+
if (replacement === void 0)
|
|
4222
|
+
return marker;
|
|
4223
|
+
const before = `[${label}]`;
|
|
4224
|
+
const after = `[${replacement}]`;
|
|
4225
|
+
records.push({ cueStartTime, before, after });
|
|
4226
|
+
return `${leadingWhitespace}${after}`;
|
|
4227
|
+
});
|
|
4228
|
+
});
|
|
4229
|
+
return { editedVtt, replacements: records };
|
|
4230
|
+
}
|
|
4207
4231
|
async function identifyProfanityWithAI({
|
|
4208
4232
|
plainText,
|
|
4209
4233
|
provider,
|
|
@@ -4306,6 +4330,7 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4306
4330
|
model,
|
|
4307
4331
|
autoCensorProfanity: autoCensorOption,
|
|
4308
4332
|
replacements: replacementsOption,
|
|
4333
|
+
speakerReplacements: speakerReplacementsOption,
|
|
4309
4334
|
deleteOriginalTrack,
|
|
4310
4335
|
uploadToS3: uploadToS3Option,
|
|
4311
4336
|
uploadToMux: uploadToMuxOption,
|
|
@@ -4318,8 +4343,9 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4318
4343
|
} = options;
|
|
4319
4344
|
const hasAutoCensor = !!autoCensorOption;
|
|
4320
4345
|
const hasReplacements = !!replacementsOption && replacementsOption.length > 0;
|
|
4321
|
-
|
|
4322
|
-
|
|
4346
|
+
const hasSpeakerReplacements = !!speakerReplacementsOption && speakerReplacementsOption.length > 0;
|
|
4347
|
+
if (!hasAutoCensor && !hasReplacements && !hasSpeakerReplacements) {
|
|
4348
|
+
throw new MuxAiError("At least one of autoCensorProfanity, replacements, or speakerReplacements must be provided.", { type: "validation_error" });
|
|
4323
4349
|
}
|
|
4324
4350
|
if (autoCensorOption && !provider) {
|
|
4325
4351
|
throw new MuxAiError("provider is required when using autoCensorProfanity.", { type: "validation_error" });
|
|
@@ -4327,6 +4353,16 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4327
4353
|
const deleteOriginal = deleteOriginalTrack !== false;
|
|
4328
4354
|
const uploadToMux = uploadToMuxOption !== false;
|
|
4329
4355
|
const uploadToS3 = uploadToS3Option || uploadToMux;
|
|
4356
|
+
for (const replacement of speakerReplacementsOption ?? []) {
|
|
4357
|
+
const hasInvalidFindCharacter = replacement.find.includes("[") || replacement.find.includes("]") || /[\r\n]/.test(replacement.find);
|
|
4358
|
+
const hasInvalidReplaceCharacter = replacement.replace.includes("[") || replacement.replace.includes("]") || /[\r\n]/.test(replacement.replace);
|
|
4359
|
+
if (!replacement.find || !replacement.replace || hasInvalidFindCharacter || hasInvalidReplaceCharacter) {
|
|
4360
|
+
throw new MuxAiError(
|
|
4361
|
+
"Speaker replacement labels must be non-empty and must not contain square brackets or newlines.",
|
|
4362
|
+
{ type: "validation_error" }
|
|
4363
|
+
);
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4330
4366
|
const s3Endpoint = providedS3Endpoint ?? env_default.S3_ENDPOINT;
|
|
4331
4367
|
const s3Region = providedS3Region ?? env_default.S3_REGION ?? "auto";
|
|
4332
4368
|
const s3Bucket = providedS3Bucket ?? env_default.S3_BUCKET;
|
|
@@ -4338,7 +4374,7 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4338
4374
|
{ type: "validation_error" }
|
|
4339
4375
|
);
|
|
4340
4376
|
}
|
|
4341
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
4377
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
4342
4378
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
4343
4379
|
const signingContext = await resolveMuxSigningContext(credentials);
|
|
4344
4380
|
if (policy === "signed" && !signingContext) {
|
|
@@ -4408,6 +4444,16 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4408
4444
|
totalReplacementCount += censorReplacements.length;
|
|
4409
4445
|
autoCensorResult = { replacements: censorReplacements };
|
|
4410
4446
|
}
|
|
4447
|
+
let speakerReplacementsResult;
|
|
4448
|
+
if (speakerReplacementsOption && speakerReplacementsOption.length > 0) {
|
|
4449
|
+
const { editedVtt: afterSpeakerReplacements, replacements: speakerReplacements } = applySpeakerReplacements(
|
|
4450
|
+
editedVtt,
|
|
4451
|
+
speakerReplacementsOption
|
|
4452
|
+
);
|
|
4453
|
+
editedVtt = afterSpeakerReplacements;
|
|
4454
|
+
totalReplacementCount += speakerReplacements.length;
|
|
4455
|
+
speakerReplacementsResult = { replacements: speakerReplacements };
|
|
4456
|
+
}
|
|
4411
4457
|
let replacementsResult;
|
|
4412
4458
|
if (replacementsOption && replacementsOption.length > 0) {
|
|
4413
4459
|
const { editedVtt: afterReplacements, replacements: staticReplacements } = applyReplacements(editedVtt, replacementsOption);
|
|
@@ -4470,6 +4516,7 @@ async function editCaptionsInternal(assetId, trackId, options, collectedUsage) {
|
|
|
4470
4516
|
totalReplacementCount,
|
|
4471
4517
|
autoCensorProfanity: autoCensorResult,
|
|
4472
4518
|
replacements: replacementsResult,
|
|
4519
|
+
speakerReplacements: speakerReplacementsResult,
|
|
4473
4520
|
uploadedTrackId,
|
|
4474
4521
|
presignedUrl,
|
|
4475
4522
|
usage: usageWithMetadata,
|
|
@@ -4774,7 +4821,7 @@ async function generateEmbeddingsInternal(assetId, options, collectedUsage) {
|
|
|
4774
4821
|
scope
|
|
4775
4822
|
} = options;
|
|
4776
4823
|
const embeddingModel = resolveEmbeddingModelConfig({ ...options, provider, model });
|
|
4777
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
4824
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
4778
4825
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
4779
4826
|
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
4780
4827
|
if (effectiveScope) {
|
|
@@ -5394,7 +5441,7 @@ async function generateEngagementInsightsInternal(assetId, options, collectedUsa
|
|
|
5394
5441
|
model,
|
|
5395
5442
|
provider
|
|
5396
5443
|
});
|
|
5397
|
-
const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
5444
|
+
const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
5398
5445
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(asset);
|
|
5399
5446
|
if (!assetDurationSeconds) {
|
|
5400
5447
|
throw new MuxAiError(`Asset ${assetId} has no valid duration.`, { type: "validation_error" });
|
|
@@ -6152,7 +6199,7 @@ async function getModerationScores(assetId, options = {}) {
|
|
|
6152
6199
|
scope
|
|
6153
6200
|
} = options;
|
|
6154
6201
|
const credentials = providedCredentials;
|
|
6155
|
-
const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
6202
|
+
const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
6156
6203
|
const videoTrackDurationSeconds = getVideoTrackDurationSecondsFromAsset(asset);
|
|
6157
6204
|
const videoTrackFps = getVideoTrackMaxFrameRateFromAsset(asset);
|
|
6158
6205
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(asset);
|
|
@@ -6766,7 +6813,7 @@ async function getSummaryAndTagsInternal(assetId, options, collectedUsage) {
|
|
|
6766
6813
|
provider
|
|
6767
6814
|
});
|
|
6768
6815
|
const workflowCredentials = credentials;
|
|
6769
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, workflowCredentials);
|
|
6816
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, workflowCredentials, options?.assetSnapshot);
|
|
6770
6817
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
6771
6818
|
const isAudioOnly = isAudioOnlyAsset(assetData);
|
|
6772
6819
|
const effectiveScope = hasWorkflowScopeBoundaries(scope) ? scope : void 0;
|
|
@@ -7213,7 +7260,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
|
|
|
7213
7260
|
if (uploadToS3 && (!s3Endpoint || !s3Bucket || !effectiveStorageAdapter && (!s3AccessKeyId || !s3SecretAccessKey))) {
|
|
7214
7261
|
throw new MuxAiError("Storage configuration is required for uploading. Provide s3Endpoint and s3Bucket. If no storageAdapter is supplied, also provide s3AccessKeyId and s3SecretAccessKey in options or set S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY environment variables.", { type: "validation_error" });
|
|
7215
7262
|
}
|
|
7216
|
-
const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
7263
|
+
const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
7217
7264
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(initialAsset);
|
|
7218
7265
|
let currentAsset = initialAsset;
|
|
7219
7266
|
let createdStaticRenditionId;
|
|
@@ -8083,7 +8130,7 @@ async function translateCaptionsInternal(assetId, trackId, toLanguageCode, optio
|
|
|
8083
8130
|
if (uploadToS3 && (!s3Endpoint || !s3Bucket || !effectiveStorageAdapter && (!s3AccessKeyId || !s3SecretAccessKey))) {
|
|
8084
8131
|
throw new MuxAiError("Storage configuration is required for uploading. Provide s3Endpoint and s3Bucket. If no storageAdapter is supplied, also provide s3AccessKeyId and s3SecretAccessKey in options or set S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY environment variables.", { type: "validation_error" });
|
|
8085
8132
|
}
|
|
8086
|
-
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials);
|
|
8133
|
+
const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId, credentials, options.assetSnapshot);
|
|
8087
8134
|
const assetDurationSeconds = getAssetDurationSecondsFromAsset(assetData);
|
|
8088
8135
|
const signingContext = await resolveMuxSigningContext(credentials);
|
|
8089
8136
|
if (policy === "signed" && !signingContext) {
|
|
@@ -8236,6 +8283,7 @@ export {
|
|
|
8236
8283
|
aggregateTokenUsage,
|
|
8237
8284
|
applyOverrideLists,
|
|
8238
8285
|
applyReplacements,
|
|
8286
|
+
applySpeakerReplacements,
|
|
8239
8287
|
askQuestions,
|
|
8240
8288
|
buildReplacementRegex,
|
|
8241
8289
|
burnedInCaptionsSchema,
|