@mux/ai 0.2.0 → 0.3.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/dist/index.js CHANGED
@@ -72,10 +72,9 @@ var env = parseEnv();
72
72
  var env_default = env;
73
73
 
74
74
  // src/lib/url-signing.ts
75
- async function resolveSigningContext(config) {
76
- "use step";
77
- const keyId = config.muxSigningKey ?? env_default.MUX_SIGNING_KEY;
78
- const keySecret = config.muxPrivateKey ?? env_default.MUX_PRIVATE_KEY;
75
+ function getMuxSigningContextFromEnv() {
76
+ const keyId = env_default.MUX_SIGNING_KEY;
77
+ const keySecret = env_default.MUX_PRIVATE_KEY;
79
78
  if (!keyId || !keySecret) {
80
79
  return void 0;
81
80
  }
@@ -112,10 +111,11 @@ async function signUrl(url, playbackId, context, type = "video", params) {
112
111
 
113
112
  // src/primitives/storyboards.ts
114
113
  var DEFAULT_STORYBOARD_WIDTH = 640;
115
- async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, signingContext) {
114
+ async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, shouldSign = false) {
116
115
  "use step";
117
116
  const baseUrl = `https://image.mux.com/${playbackId}/storyboard.png`;
118
- if (signingContext) {
117
+ if (shouldSign) {
118
+ const signingContext = getMuxSigningContextFromEnv();
119
119
  return signUrl(baseUrl, playbackId, signingContext, "storyboard", { width });
120
120
  }
121
121
  return `${baseUrl}?width=${width}`;
@@ -209,7 +209,7 @@ function chunkText(text, strategy) {
209
209
  // src/primitives/thumbnails.ts
210
210
  async function getThumbnailUrls(playbackId, duration, options = {}) {
211
211
  "use step";
212
- const { interval = 10, width = 640, signingContext } = options;
212
+ const { interval = 10, width = 640, shouldSign = false } = options;
213
213
  const timestamps = [];
214
214
  if (duration <= 50) {
215
215
  const spacing = duration / 6;
@@ -223,7 +223,8 @@ async function getThumbnailUrls(playbackId, duration, options = {}) {
223
223
  }
224
224
  const baseUrl = `https://image.mux.com/${playbackId}/thumbnail.png`;
225
225
  const urlPromises = timestamps.map(async (time) => {
226
- if (signingContext) {
226
+ if (shouldSign) {
227
+ const signingContext = getMuxSigningContextFromEnv();
227
228
  return signUrl(baseUrl, playbackId, signingContext, "thumbnail", { time, width });
228
229
  }
229
230
  return `${baseUrl}?time=${time}&width=${width}`;
@@ -339,17 +340,18 @@ function parseVTTCues(vttContent) {
339
340
  }
340
341
  return cues;
341
342
  }
342
- async function buildTranscriptUrl(playbackId, trackId, signingContext) {
343
+ async function buildTranscriptUrl(playbackId, trackId, shouldSign = false) {
343
344
  "use step";
344
345
  const baseUrl = `https://stream.mux.com/${playbackId}/text/${trackId}.vtt`;
345
- if (signingContext) {
346
+ if (shouldSign) {
347
+ const signingContext = getMuxSigningContextFromEnv();
346
348
  return signUrl(baseUrl, playbackId, signingContext, "video");
347
349
  }
348
350
  return baseUrl;
349
351
  }
350
352
  async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
351
353
  "use step";
352
- const { languageCode, cleanTranscript = true, signingContext } = options;
354
+ const { languageCode, cleanTranscript = true, shouldSign } = options;
353
355
  const track = findCaptionTrack(asset, languageCode);
354
356
  if (!track) {
355
357
  return { transcriptText: "" };
@@ -357,7 +359,7 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
357
359
  if (!track.id) {
358
360
  return { transcriptText: "", track };
359
361
  }
360
- const transcriptUrl = await buildTranscriptUrl(playbackId, track.id, signingContext);
362
+ const transcriptUrl = await buildTranscriptUrl(playbackId, track.id, shouldSign);
361
363
  try {
362
364
  const response = await fetch(transcriptUrl);
363
365
  if (!response.ok) {
@@ -414,22 +416,22 @@ function requireEnv(value, name) {
414
416
  }
415
417
  return value;
416
418
  }
417
- function createLanguageModelFromConfig(provider, modelId, credentials) {
419
+ function createLanguageModelFromConfig(provider, modelId) {
418
420
  switch (provider) {
419
421
  case "openai": {
420
- const apiKey = credentials.openaiApiKey;
422
+ const apiKey = env_default.OPENAI_API_KEY;
421
423
  requireEnv(apiKey, "OPENAI_API_KEY");
422
424
  const openai = createOpenAI({ apiKey });
423
425
  return openai(modelId);
424
426
  }
425
427
  case "anthropic": {
426
- const apiKey = credentials.anthropicApiKey;
428
+ const apiKey = env_default.ANTHROPIC_API_KEY;
427
429
  requireEnv(apiKey, "ANTHROPIC_API_KEY");
428
430
  const anthropic = createAnthropic({ apiKey });
429
431
  return anthropic(modelId);
430
432
  }
431
433
  case "google": {
432
- const apiKey = credentials.googleApiKey;
434
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
433
435
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
434
436
  const google = createGoogleGenerativeAI({ apiKey });
435
437
  return google(modelId);
@@ -440,16 +442,16 @@ function createLanguageModelFromConfig(provider, modelId, credentials) {
440
442
  }
441
443
  }
442
444
  }
443
- function createEmbeddingModelFromConfig(provider, modelId, credentials) {
445
+ function createEmbeddingModelFromConfig(provider, modelId) {
444
446
  switch (provider) {
445
447
  case "openai": {
446
- const apiKey = credentials.openaiApiKey;
448
+ const apiKey = env_default.OPENAI_API_KEY;
447
449
  requireEnv(apiKey, "OPENAI_API_KEY");
448
450
  const openai = createOpenAI({ apiKey });
449
451
  return openai.embedding(modelId);
450
452
  }
451
453
  case "google": {
452
- const apiKey = credentials.googleApiKey;
454
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
453
455
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
454
456
  const google = createGoogleGenerativeAI({ apiKey });
455
457
  return google.textEmbeddingModel(modelId);
@@ -465,7 +467,7 @@ function resolveLanguageModel(options = {}) {
465
467
  const modelId = options.model || DEFAULT_LANGUAGE_MODELS[provider];
466
468
  switch (provider) {
467
469
  case "openai": {
468
- const apiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
470
+ const apiKey = env_default.OPENAI_API_KEY;
469
471
  requireEnv(apiKey, "OPENAI_API_KEY");
470
472
  const openai = createOpenAI({
471
473
  apiKey
@@ -477,7 +479,7 @@ function resolveLanguageModel(options = {}) {
477
479
  };
478
480
  }
479
481
  case "anthropic": {
480
- const apiKey = options.anthropicApiKey ?? env_default.ANTHROPIC_API_KEY;
482
+ const apiKey = env_default.ANTHROPIC_API_KEY;
481
483
  requireEnv(apiKey, "ANTHROPIC_API_KEY");
482
484
  const anthropic = createAnthropic({
483
485
  apiKey
@@ -489,7 +491,7 @@ function resolveLanguageModel(options = {}) {
489
491
  };
490
492
  }
491
493
  case "google": {
492
- const apiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
494
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
493
495
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
494
496
  const google = createGoogleGenerativeAI({
495
497
  apiKey
@@ -511,7 +513,7 @@ function resolveEmbeddingModel(options = {}) {
511
513
  const modelId = options.model || DEFAULT_EMBEDDING_MODELS[provider];
512
514
  switch (provider) {
513
515
  case "openai": {
514
- const apiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
516
+ const apiKey = env_default.OPENAI_API_KEY;
515
517
  requireEnv(apiKey, "OPENAI_API_KEY");
516
518
  const openai = createOpenAI({
517
519
  apiKey
@@ -523,7 +525,7 @@ function resolveEmbeddingModel(options = {}) {
523
525
  };
524
526
  }
525
527
  case "google": {
526
- const apiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
528
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
527
529
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
528
530
  const google = createGoogleGenerativeAI({
529
531
  apiKey
@@ -542,13 +544,45 @@ function resolveEmbeddingModel(options = {}) {
542
544
  }
543
545
 
544
546
  // src/lib/client-factory.ts
545
- async function validateCredentials(options, requiredProvider) {
546
- "use step";
547
- const muxTokenId = options.muxTokenId ?? env_default.MUX_TOKEN_ID;
548
- const muxTokenSecret = options.muxTokenSecret ?? env_default.MUX_TOKEN_SECRET;
549
- const openaiApiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
550
- const anthropicApiKey = options.anthropicApiKey ?? env_default.ANTHROPIC_API_KEY;
551
- const googleApiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
547
+ function getMuxCredentialsFromEnv() {
548
+ const muxTokenId = env_default.MUX_TOKEN_ID;
549
+ const muxTokenSecret = env_default.MUX_TOKEN_SECRET;
550
+ if (!muxTokenId || !muxTokenSecret) {
551
+ throw new Error(
552
+ "Mux credentials are required. Set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables."
553
+ );
554
+ }
555
+ return { muxTokenId, muxTokenSecret };
556
+ }
557
+ function getApiKeyFromEnv(provider) {
558
+ const envVarMap = {
559
+ openai: env_default.OPENAI_API_KEY,
560
+ anthropic: env_default.ANTHROPIC_API_KEY,
561
+ google: env_default.GOOGLE_GENERATIVE_AI_API_KEY,
562
+ hive: env_default.HIVE_API_KEY,
563
+ elevenlabs: env_default.ELEVENLABS_API_KEY
564
+ };
565
+ const apiKey = envVarMap[provider];
566
+ if (!apiKey) {
567
+ const envVarNames = {
568
+ openai: "OPENAI_API_KEY",
569
+ anthropic: "ANTHROPIC_API_KEY",
570
+ google: "GOOGLE_GENERATIVE_AI_API_KEY",
571
+ hive: "HIVE_API_KEY",
572
+ elevenlabs: "ELEVENLABS_API_KEY"
573
+ };
574
+ throw new Error(
575
+ `${provider} API key is required. Set ${envVarNames[provider]} environment variable.`
576
+ );
577
+ }
578
+ return apiKey;
579
+ }
580
+ async function validateCredentials(requiredProvider) {
581
+ const muxTokenId = env_default.MUX_TOKEN_ID;
582
+ const muxTokenSecret = env_default.MUX_TOKEN_SECRET;
583
+ const openaiApiKey = env_default.OPENAI_API_KEY;
584
+ const anthropicApiKey = env_default.ANTHROPIC_API_KEY;
585
+ const googleApiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
552
586
  if (!muxTokenId || !muxTokenSecret) {
553
587
  throw new Error(
554
588
  "Mux credentials are required. Provide muxTokenId and muxTokenSecret in options or set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables."
@@ -578,9 +612,8 @@ async function validateCredentials(options, requiredProvider) {
578
612
  };
579
613
  }
580
614
  async function createWorkflowConfig(options, provider) {
581
- "use step";
582
615
  const providerToUse = provider || options.provider || "openai";
583
- const credentials = await validateCredentials(options, providerToUse);
616
+ const credentials = await validateCredentials(providerToUse);
584
617
  const resolved = resolveLanguageModel({
585
618
  ...options,
586
619
  provider: providerToUse
@@ -701,11 +734,12 @@ function getPlaybackId(asset) {
701
734
  "No public or signed playback ID found for this asset. A public or signed playback ID is required. DRM playback IDs are not currently supported."
702
735
  );
703
736
  }
704
- async function getPlaybackIdForAsset(credentials, assetId) {
737
+ async function getPlaybackIdForAsset(assetId) {
705
738
  "use step";
739
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
706
740
  const mux = new Mux2({
707
- tokenId: credentials.muxTokenId,
708
- tokenSecret: credentials.muxTokenSecret
741
+ tokenId: muxTokenId,
742
+ tokenSecret: muxTokenSecret
709
743
  });
710
744
  const asset = await mux.video.assets.retrieve(assetId);
711
745
  const { id: playbackId, policy } = getPlaybackId(asset);
@@ -884,16 +918,11 @@ async function analyzeStoryboard({
884
918
  imageDataUrl,
885
919
  provider,
886
920
  modelId,
887
- credentials,
888
921
  userPrompt,
889
922
  systemPrompt
890
923
  }) {
891
924
  "use step";
892
- const model = createLanguageModelFromConfig(
893
- provider,
894
- modelId,
895
- credentials
896
- );
925
+ const model = createLanguageModelFromConfig(provider, modelId);
897
926
  const response = await generateObject({
898
927
  model,
899
928
  schema: burnedInCaptionsSchema,
@@ -938,14 +967,14 @@ async function hasBurnedInCaptions(assetId, options = {}) {
938
967
  { ...config, model },
939
968
  provider
940
969
  );
941
- const { playbackId, policy } = await getPlaybackIdForAsset(workflowConfig.credentials, assetId);
942
- const signingContext = await resolveSigningContext(options);
970
+ const { playbackId, policy } = await getPlaybackIdForAsset(assetId);
971
+ const signingContext = getMuxSigningContextFromEnv();
943
972
  if (policy === "signed" && !signingContext) {
944
973
  throw new Error(
945
974
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
946
975
  );
947
976
  }
948
- const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed" ? signingContext : void 0);
977
+ const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed");
949
978
  let analysisResponse;
950
979
  if (imageSubmissionMode === "base64") {
951
980
  const base64Data = await fetchImageAsBase64(imageUrl, imageDownloadOptions);
@@ -953,7 +982,6 @@ async function hasBurnedInCaptions(assetId, options = {}) {
953
982
  imageDataUrl: base64Data,
954
983
  provider: workflowConfig.provider,
955
984
  modelId: workflowConfig.modelId,
956
- credentials: workflowConfig.credentials,
957
985
  userPrompt,
958
986
  systemPrompt: SYSTEM_PROMPT
959
987
  });
@@ -962,7 +990,6 @@ async function hasBurnedInCaptions(assetId, options = {}) {
962
990
  imageDataUrl: imageUrl,
963
991
  provider: workflowConfig.provider,
964
992
  modelId: workflowConfig.modelId,
965
- credentials: workflowConfig.credentials,
966
993
  userPrompt,
967
994
  systemPrompt: SYSTEM_PROMPT
968
995
  });
@@ -1035,16 +1062,11 @@ var chaptersSchema = z3.object({
1035
1062
  async function generateChaptersWithAI({
1036
1063
  provider,
1037
1064
  modelId,
1038
- credentials,
1039
1065
  timestampedTranscript,
1040
1066
  systemPrompt
1041
1067
  }) {
1042
1068
  "use step";
1043
- const model = createLanguageModelFromConfig(
1044
- provider,
1045
- modelId,
1046
- credentials
1047
- );
1069
+ const model = createLanguageModelFromConfig(provider, modelId);
1048
1070
  const response = await withRetry(
1049
1071
  () => generateObject2({
1050
1072
  model,
@@ -1087,8 +1109,8 @@ async function generateChapters(assetId, languageCode, options = {}) {
1087
1109
  "use workflow";
1088
1110
  const { provider = "openai", model } = options;
1089
1111
  const config = await createWorkflowConfig({ ...options, model }, provider);
1090
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
1091
- const signingContext = await resolveSigningContext(options);
1112
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1113
+ const signingContext = getMuxSigningContextFromEnv();
1092
1114
  if (policy === "signed" && !signingContext) {
1093
1115
  throw new Error(
1094
1116
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1098,7 +1120,7 @@ async function generateChapters(assetId, languageCode, options = {}) {
1098
1120
  languageCode,
1099
1121
  cleanTranscript: false,
1100
1122
  // keep timestamps for chapter segmentation
1101
- signingContext: policy === "signed" ? signingContext : void 0
1123
+ shouldSign: policy === "signed"
1102
1124
  });
1103
1125
  if (!transcriptResult.track || !transcriptResult.transcriptText) {
1104
1126
  const availableLanguages = getReadyTextTracks(assetData).map((t) => t.language_code).filter(Boolean).join(", ");
@@ -1115,7 +1137,6 @@ async function generateChapters(assetId, languageCode, options = {}) {
1115
1137
  chaptersData = await generateChaptersWithAI({
1116
1138
  provider: config.provider,
1117
1139
  modelId: config.modelId,
1118
- credentials: config.credentials,
1119
1140
  timestampedTranscript,
1120
1141
  systemPrompt: SYSTEM_PROMPT2
1121
1142
  });
@@ -1162,11 +1183,10 @@ function averageEmbeddings(embeddings) {
1162
1183
  async function generateSingleChunkEmbedding({
1163
1184
  chunk,
1164
1185
  provider,
1165
- modelId,
1166
- credentials
1186
+ modelId
1167
1187
  }) {
1168
1188
  "use step";
1169
- const model = createEmbeddingModelFromConfig(provider, modelId, credentials);
1189
+ const model = createEmbeddingModelFromConfig(provider, modelId);
1170
1190
  const response = await withRetry(
1171
1191
  () => embed({
1172
1192
  model,
@@ -1192,13 +1212,9 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1192
1212
  chunkingStrategy = { type: "token", maxTokens: 500, overlap: 100 },
1193
1213
  batchSize = 5
1194
1214
  } = options;
1195
- const credentials = await validateCredentials(options, provider === "google" ? "google" : "openai");
1196
1215
  const embeddingModel = resolveEmbeddingModel({ ...options, provider, model });
1197
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(
1198
- credentials,
1199
- assetId
1200
- );
1201
- const signingContext = await resolveSigningContext(options);
1216
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1217
+ const signingContext = getMuxSigningContextFromEnv();
1202
1218
  if (policy === "signed" && !signingContext) {
1203
1219
  throw new Error(
1204
1220
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1208,7 +1224,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1208
1224
  const transcriptResult = await fetchTranscriptForAsset(assetData, playbackId, {
1209
1225
  languageCode,
1210
1226
  cleanTranscript: !useVttChunking,
1211
- signingContext: policy === "signed" ? signingContext : void 0
1227
+ shouldSign: policy === "signed"
1212
1228
  });
1213
1229
  if (!transcriptResult.track || !transcriptResult.transcriptText) {
1214
1230
  const availableLanguages = getReadyTextTracks(assetData).map((t) => t.language_code).filter(Boolean).join(", ");
@@ -1237,8 +1253,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1237
1253
  (chunk) => generateSingleChunkEmbedding({
1238
1254
  chunk,
1239
1255
  provider: embeddingModel.provider,
1240
- modelId: embeddingModel.modelId,
1241
- credentials
1256
+ modelId: embeddingModel.modelId
1242
1257
  })
1243
1258
  )
1244
1259
  );
@@ -1323,19 +1338,20 @@ async function processConcurrently(items, processor, maxConcurrent = 5) {
1323
1338
  }
1324
1339
  return results;
1325
1340
  }
1326
- async function requestOpenAIModeration(imageUrls, apiKey, model, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1341
+ async function requestOpenAIModeration(imageUrls, model, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1327
1342
  "use step";
1328
1343
  const targetUrls = submissionMode === "base64" ? (await downloadImagesAsBase64(imageUrls, downloadOptions, maxConcurrent)).map(
1329
- (img) => ({ url: img.url, image: img.base64Data, apiKey, model })
1330
- ) : imageUrls.map((url) => ({ url, image: url, apiKey, model }));
1344
+ (img) => ({ url: img.url, image: img.base64Data, model })
1345
+ ) : imageUrls.map((url) => ({ url, image: url, model }));
1331
1346
  const moderate = async (entry) => {
1332
1347
  "use step";
1348
+ const apiKey = getApiKeyFromEnv("openai");
1333
1349
  try {
1334
1350
  const res = await fetch("https://api.openai.com/v1/moderations", {
1335
1351
  method: "POST",
1336
1352
  headers: {
1337
1353
  "Content-Type": "application/json",
1338
- "Authorization": `Bearer ${entry.apiKey}`
1354
+ "Authorization": `Bearer ${apiKey}`
1339
1355
  },
1340
1356
  body: JSON.stringify({
1341
1357
  model: entry.model,
@@ -1381,7 +1397,7 @@ function getHiveCategoryScores(classes, categoryNames) {
1381
1397
  const scores = categoryNames.map((category) => scoreMap[category] || 0);
1382
1398
  return Math.max(...scores, 0);
1383
1399
  }
1384
- async function requestHiveModeration(imageUrls, apiKey, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1400
+ async function requestHiveModeration(imageUrls, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1385
1401
  "use step";
1386
1402
  const targets = submissionMode === "base64" ? (await downloadImagesAsBase64(imageUrls, downloadOptions, maxConcurrent)).map((img) => ({
1387
1403
  url: img.url,
@@ -1396,6 +1412,7 @@ async function requestHiveModeration(imageUrls, apiKey, maxConcurrent = 5, submi
1396
1412
  }));
1397
1413
  const moderate = async (entry) => {
1398
1414
  "use step";
1415
+ const apiKey = getApiKeyFromEnv("hive");
1399
1416
  try {
1400
1417
  const formData = new FormData();
1401
1418
  if (entry.source.kind === "url") {
@@ -1452,10 +1469,9 @@ async function getModerationScores(assetId, options = {}) {
1452
1469
  imageSubmissionMode = "url",
1453
1470
  imageDownloadOptions
1454
1471
  } = options;
1455
- const credentials = await validateCredentials(options, provider === "openai" ? "openai" : void 0);
1456
- const { asset, playbackId, policy } = await getPlaybackIdForAsset(credentials, assetId);
1472
+ const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1457
1473
  const duration = asset.duration || 0;
1458
- const signingContext = await resolveSigningContext(options);
1474
+ const signingContext = getMuxSigningContextFromEnv();
1459
1475
  if (policy === "signed" && !signingContext) {
1460
1476
  throw new Error(
1461
1477
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1464,30 +1480,20 @@ async function getModerationScores(assetId, options = {}) {
1464
1480
  const thumbnailUrls = await getThumbnailUrls(playbackId, duration, {
1465
1481
  interval: thumbnailInterval,
1466
1482
  width: thumbnailWidth,
1467
- signingContext: policy === "signed" ? signingContext : void 0
1483
+ shouldSign: policy === "signed"
1468
1484
  });
1469
1485
  let thumbnailScores;
1470
1486
  if (provider === "openai") {
1471
- const apiKey = credentials.openaiApiKey;
1472
- if (!apiKey) {
1473
- throw new Error("OpenAI API key is required for moderation. Set OPENAI_API_KEY or pass openaiApiKey.");
1474
- }
1475
1487
  thumbnailScores = await requestOpenAIModeration(
1476
1488
  thumbnailUrls,
1477
- apiKey,
1478
1489
  model || "omni-moderation-latest",
1479
1490
  maxConcurrent,
1480
1491
  imageSubmissionMode,
1481
1492
  imageDownloadOptions
1482
1493
  );
1483
1494
  } else if (provider === "hive") {
1484
- const hiveApiKey = options.hiveApiKey || env_default.HIVE_API_KEY;
1485
- if (!hiveApiKey) {
1486
- throw new Error("Hive API key is required for moderation. Set HIVE_API_KEY or pass hiveApiKey.");
1487
- }
1488
1495
  thumbnailScores = await requestHiveModeration(
1489
1496
  thumbnailUrls,
1490
- hiveApiKey,
1491
1497
  maxConcurrent,
1492
1498
  imageSubmissionMode,
1493
1499
  imageDownloadOptions
@@ -1521,8 +1527,8 @@ var summarySchema = z4.object({
1521
1527
  description: z4.string()
1522
1528
  });
1523
1529
  var TONE_INSTRUCTIONS = {
1524
- normal: "Provide a clear, straightforward analysis.",
1525
- sassy: "Channel your inner diva! Answer with maximum sass, wit, and playful attitude. Don't hold back - be cheeky, clever, and delightfully snarky. Make it pop!",
1530
+ neutral: "Provide a clear, straightforward analysis.",
1531
+ playful: "Channel your inner diva! Answer with maximum sass, wit, and playful attitude. Don't hold back - be cheeky, clever, and delightfully snarky. Make it pop!",
1526
1532
  professional: "Provide a professional, executive-level analysis suitable for business reporting."
1527
1533
  };
1528
1534
  var summarizationPromptBuilder = createPromptBuilder({
@@ -1638,13 +1644,9 @@ function buildUserPrompt2({
1638
1644
  }
1639
1645
  return summarizationPromptBuilder.buildWithContext(promptOverrides, contextSections);
1640
1646
  }
1641
- async function analyzeStoryboard2(imageDataUrl, workflowConfig, userPrompt, systemPrompt) {
1647
+ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, systemPrompt) {
1642
1648
  "use step";
1643
- const model = createLanguageModelFromConfig(
1644
- workflowConfig.provider,
1645
- workflowConfig.modelId,
1646
- workflowConfig.credentials
1647
- );
1649
+ const model = createLanguageModelFromConfig(provider, modelId);
1648
1650
  const response = await generateObject3({
1649
1651
  model,
1650
1652
  schema: summarySchema,
@@ -1701,7 +1703,7 @@ async function getSummaryAndTags(assetId, options) {
1701
1703
  const {
1702
1704
  provider = "openai",
1703
1705
  model,
1704
- tone = "normal",
1706
+ tone = "neutral",
1705
1707
  includeTranscript = true,
1706
1708
  cleanTranscript = true,
1707
1709
  imageSubmissionMode = "url",
@@ -1713,8 +1715,8 @@ async function getSummaryAndTags(assetId, options) {
1713
1715
  { ...options, model },
1714
1716
  provider
1715
1717
  );
1716
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
1717
- const signingContext = await resolveSigningContext(options ?? {});
1718
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1719
+ const signingContext = getMuxSigningContextFromEnv();
1718
1720
  if (policy === "signed" && !signingContext) {
1719
1721
  throw new Error(
1720
1722
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1722,7 +1724,7 @@ async function getSummaryAndTags(assetId, options) {
1722
1724
  }
1723
1725
  const transcriptText = includeTranscript ? (await fetchTranscriptForAsset(assetData, playbackId, {
1724
1726
  cleanTranscript,
1725
- signingContext: policy === "signed" ? signingContext : void 0
1727
+ shouldSign: policy === "signed"
1726
1728
  })).transcriptText : "";
1727
1729
  const userPrompt = buildUserPrompt2({
1728
1730
  tone,
@@ -1730,19 +1732,20 @@ async function getSummaryAndTags(assetId, options) {
1730
1732
  isCleanTranscript: cleanTranscript,
1731
1733
  promptOverrides
1732
1734
  });
1733
- const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed" ? signingContext : void 0);
1735
+ const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed");
1734
1736
  let analysisResponse;
1735
1737
  try {
1736
1738
  if (imageSubmissionMode === "base64") {
1737
1739
  const downloadResult = await downloadImageAsBase64(imageUrl, imageDownloadOptions);
1738
1740
  analysisResponse = await analyzeStoryboard2(
1739
1741
  downloadResult.base64Data,
1740
- config,
1742
+ config.provider,
1743
+ config.modelId,
1741
1744
  userPrompt,
1742
1745
  SYSTEM_PROMPT3
1743
1746
  );
1744
1747
  } else {
1745
- analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config, userPrompt, SYSTEM_PROMPT3));
1748
+ analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config.provider, config.modelId, userPrompt, SYSTEM_PROMPT3));
1746
1749
  }
1747
1750
  } catch (error) {
1748
1751
  throw new Error(
@@ -1947,11 +1950,12 @@ function getReadyAudioStaticRendition(asset) {
1947
1950
  );
1948
1951
  }
1949
1952
  var hasReadyAudioStaticRendition = (asset) => Boolean(getReadyAudioStaticRendition(asset));
1950
- async function requestStaticRenditionCreation(credentials, assetId) {
1953
+ async function requestStaticRenditionCreation(assetId) {
1951
1954
  "use step";
1955
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1952
1956
  const mux = new Mux3({
1953
- tokenId: credentials.muxTokenId,
1954
- tokenSecret: credentials.muxTokenSecret
1957
+ tokenId: muxTokenId,
1958
+ tokenSecret: muxTokenSecret
1955
1959
  });
1956
1960
  try {
1957
1961
  await mux.video.assets.createStaticRendition(assetId, {
@@ -1970,13 +1974,13 @@ async function requestStaticRenditionCreation(credentials, assetId) {
1970
1974
  }
1971
1975
  async function waitForAudioStaticRendition({
1972
1976
  assetId,
1973
- credentials,
1974
1977
  initialAsset
1975
1978
  }) {
1976
1979
  "use step";
1980
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1977
1981
  const mux = new Mux3({
1978
- tokenId: credentials.muxTokenId,
1979
- tokenSecret: credentials.muxTokenSecret
1982
+ tokenId: muxTokenId,
1983
+ tokenSecret: muxTokenSecret
1980
1984
  });
1981
1985
  let currentAsset = initialAsset;
1982
1986
  if (hasReadyAudioStaticRendition(currentAsset)) {
@@ -1984,9 +1988,9 @@ async function waitForAudioStaticRendition({
1984
1988
  }
1985
1989
  const status = currentAsset.static_renditions?.status ?? "not_requested";
1986
1990
  if (status === "not_requested" || status === void 0) {
1987
- await requestStaticRenditionCreation(credentials, assetId);
1991
+ await requestStaticRenditionCreation(assetId);
1988
1992
  } else if (status === "errored") {
1989
- await requestStaticRenditionCreation(credentials, assetId);
1993
+ await requestStaticRenditionCreation(assetId);
1990
1994
  } else {
1991
1995
  console.warn(`\u2139\uFE0F Static rendition already ${status}. Waiting for it to finish...`);
1992
1996
  }
@@ -2022,10 +2026,10 @@ async function createElevenLabsDubbingJob({
2022
2026
  audioBuffer,
2023
2027
  assetId,
2024
2028
  elevenLabsLangCode,
2025
- elevenLabsApiKey,
2026
2029
  numSpeakers
2027
2030
  }) {
2028
2031
  "use step";
2032
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2029
2033
  const audioBlob = new Blob([audioBuffer], { type: "audio/mp4" });
2030
2034
  const formData = new FormData();
2031
2035
  formData.append("file", audioBlob);
@@ -2046,10 +2050,10 @@ async function createElevenLabsDubbingJob({
2046
2050
  return dubbingData.dubbing_id;
2047
2051
  }
2048
2052
  async function checkElevenLabsDubbingStatus({
2049
- dubbingId,
2050
- elevenLabsApiKey
2053
+ dubbingId
2051
2054
  }) {
2052
2055
  "use step";
2056
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2053
2057
  const statusResponse = await fetch(`https://api.elevenlabs.io/v1/dubbing/${dubbingId}`, {
2054
2058
  headers: {
2055
2059
  "xi-api-key": elevenLabsApiKey
@@ -2066,10 +2070,10 @@ async function checkElevenLabsDubbingStatus({
2066
2070
  }
2067
2071
  async function downloadDubbedAudioFromElevenLabs({
2068
2072
  dubbingId,
2069
- languageCode,
2070
- elevenLabsApiKey
2073
+ languageCode
2071
2074
  }) {
2072
2075
  "use step";
2076
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2073
2077
  const audioUrl = `https://api.elevenlabs.io/v1/dubbing/${dubbingId}/audio/${languageCode}`;
2074
2078
  const audioResponse = await fetch(audioUrl, {
2075
2079
  headers: {
@@ -2087,14 +2091,14 @@ async function uploadDubbedAudioToS3({
2087
2091
  toLanguageCode,
2088
2092
  s3Endpoint,
2089
2093
  s3Region,
2090
- s3Bucket,
2091
- s3AccessKeyId,
2092
- s3SecretAccessKey
2094
+ s3Bucket
2093
2095
  }) {
2094
2096
  "use step";
2095
2097
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2096
2098
  const { Upload } = await import("@aws-sdk/lib-storage");
2097
2099
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2100
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2101
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2098
2102
  const s3Client = new S3Client({
2099
2103
  region: s3Region,
2100
2104
  endpoint: s3Endpoint,
@@ -2127,11 +2131,12 @@ async function uploadDubbedAudioToS3({
2127
2131
  console.warn(`\u{1F517} Generated presigned URL (expires in 1 hour)`);
2128
2132
  return presignedUrl;
2129
2133
  }
2130
- async function createAudioTrackOnMux(credentials, assetId, languageCode, presignedUrl) {
2134
+ async function createAudioTrackOnMux(assetId, languageCode, presignedUrl) {
2131
2135
  "use step";
2136
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2132
2137
  const mux = new Mux3({
2133
- tokenId: credentials.muxTokenId,
2134
- tokenSecret: credentials.muxTokenSecret
2138
+ tokenId: muxTokenId,
2139
+ tokenSecret: muxTokenSecret
2135
2140
  });
2136
2141
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(languageCode) || languageCode.toUpperCase();
2137
2142
  const trackName = `${languageName} (auto-dubbed)`;
@@ -2158,21 +2163,20 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2158
2163
  if (provider !== "elevenlabs") {
2159
2164
  throw new Error("Only ElevenLabs provider is currently supported for audio translation");
2160
2165
  }
2161
- const credentials = await validateCredentials(options);
2162
2166
  const elevenLabsKey = elevenLabsApiKey ?? env_default.ELEVENLABS_API_KEY;
2163
2167
  const s3Endpoint = options.s3Endpoint ?? env_default.S3_ENDPOINT;
2164
2168
  const s3Region = options.s3Region ?? env_default.S3_REGION ?? "auto";
2165
2169
  const s3Bucket = options.s3Bucket ?? env_default.S3_BUCKET;
2166
- const s3AccessKeyId = options.s3AccessKeyId ?? env_default.S3_ACCESS_KEY_ID;
2167
- const s3SecretAccessKey = options.s3SecretAccessKey ?? env_default.S3_SECRET_ACCESS_KEY;
2170
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2171
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2168
2172
  if (!elevenLabsKey) {
2169
2173
  throw new Error("ElevenLabs API key is required. Provide elevenLabsApiKey in options or set ELEVENLABS_API_KEY environment variable.");
2170
2174
  }
2171
2175
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2172
2176
  throw new Error("S3 configuration is required for uploading to Mux. Provide s3Endpoint, s3Bucket, s3AccessKeyId, and s3SecretAccessKey in options or set S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY environment variables.");
2173
2177
  }
2174
- const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(credentials, assetId);
2175
- const signingContext = await resolveSigningContext(options);
2178
+ const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2179
+ const signingContext = getMuxSigningContextFromEnv();
2176
2180
  if (policy === "signed" && !signingContext) {
2177
2181
  throw new Error(
2178
2182
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -2183,7 +2187,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2183
2187
  console.warn("\u274C No ready audio static rendition found. Requesting one now...");
2184
2188
  currentAsset = await waitForAudioStaticRendition({
2185
2189
  assetId,
2186
- credentials,
2187
2190
  initialAsset: currentAsset
2188
2191
  });
2189
2192
  }
@@ -2213,7 +2216,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2213
2216
  audioBuffer,
2214
2217
  assetId,
2215
2218
  elevenLabsLangCode,
2216
- elevenLabsApiKey: elevenLabsKey,
2217
2219
  numSpeakers
2218
2220
  });
2219
2221
  console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
@@ -2230,8 +2232,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2230
2232
  pollAttempts++;
2231
2233
  try {
2232
2234
  const statusResult = await checkElevenLabsDubbingStatus({
2233
- dubbingId,
2234
- elevenLabsApiKey: elevenLabsKey
2235
+ dubbingId
2235
2236
  });
2236
2237
  dubbingStatus = statusResult.status;
2237
2238
  targetLanguages = statusResult.targetLanguages;
@@ -2274,8 +2275,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2274
2275
  }
2275
2276
  dubbedAudioBuffer = await downloadDubbedAudioFromElevenLabs({
2276
2277
  dubbingId,
2277
- languageCode: downloadLangCode,
2278
- elevenLabsApiKey: elevenLabsKey
2278
+ languageCode: downloadLangCode
2279
2279
  });
2280
2280
  console.warn("\u2705 Dubbed audio downloaded successfully!");
2281
2281
  } catch (error) {
@@ -2290,9 +2290,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2290
2290
  toLanguageCode,
2291
2291
  s3Endpoint,
2292
2292
  s3Region,
2293
- s3Bucket,
2294
- s3AccessKeyId,
2295
- s3SecretAccessKey
2293
+ s3Bucket
2296
2294
  });
2297
2295
  } catch (error) {
2298
2296
  throw new Error(`Failed to upload audio to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2301,7 +2299,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2301
2299
  let uploadedTrackId;
2302
2300
  const muxLangCode = toISO639_1(toLanguageCode);
2303
2301
  try {
2304
- uploadedTrackId = await createAudioTrackOnMux(credentials, assetId, muxLangCode, presignedUrl);
2302
+ uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl);
2305
2303
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
2306
2304
  const trackName = `${languageName} (auto-dubbed)`;
2307
2305
  console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
@@ -2343,15 +2341,10 @@ async function translateVttWithAI({
2343
2341
  toLanguageCode,
2344
2342
  provider,
2345
2343
  modelId,
2346
- credentials,
2347
2344
  abortSignal
2348
2345
  }) {
2349
2346
  "use step";
2350
- const languageModel = createLanguageModelFromConfig(
2351
- provider,
2352
- modelId,
2353
- credentials
2354
- );
2347
+ const languageModel = createLanguageModelFromConfig(provider, modelId);
2355
2348
  const response = await generateObject4({
2356
2349
  model: languageModel,
2357
2350
  schema: translationSchema,
@@ -2383,14 +2376,14 @@ async function uploadVttToS3({
2383
2376
  toLanguageCode,
2384
2377
  s3Endpoint,
2385
2378
  s3Region,
2386
- s3Bucket,
2387
- s3AccessKeyId,
2388
- s3SecretAccessKey
2379
+ s3Bucket
2389
2380
  }) {
2390
2381
  "use step";
2391
2382
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2392
2383
  const { Upload } = await import("@aws-sdk/lib-storage");
2393
2384
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2385
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2386
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2394
2387
  const s3Client = new S3Client({
2395
2388
  region: s3Region,
2396
2389
  endpoint: s3Endpoint,
@@ -2421,11 +2414,12 @@ async function uploadVttToS3({
2421
2414
  });
2422
2415
  return presignedUrl;
2423
2416
  }
2424
- async function createTextTrackOnMux(credentials, assetId, languageCode, trackName, presignedUrl) {
2417
+ async function createTextTrackOnMux(assetId, languageCode, trackName, presignedUrl) {
2425
2418
  "use step";
2419
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2426
2420
  const mux = new Mux4({
2427
- tokenId: credentials.muxTokenId,
2428
- tokenSecret: credentials.muxTokenSecret
2421
+ tokenId: muxTokenId,
2422
+ tokenSecret: muxTokenSecret
2429
2423
  });
2430
2424
  const trackResponse = await mux.video.assets.createTrack(assetId, {
2431
2425
  type: "text",
@@ -2447,15 +2441,13 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2447
2441
  s3Endpoint: providedS3Endpoint,
2448
2442
  s3Region: providedS3Region,
2449
2443
  s3Bucket: providedS3Bucket,
2450
- s3AccessKeyId: providedS3AccessKeyId,
2451
- s3SecretAccessKey: providedS3SecretAccessKey,
2452
2444
  uploadToMux: uploadToMuxOption
2453
2445
  } = options;
2454
2446
  const s3Endpoint = providedS3Endpoint ?? env_default.S3_ENDPOINT;
2455
2447
  const s3Region = providedS3Region ?? env_default.S3_REGION ?? "auto";
2456
2448
  const s3Bucket = providedS3Bucket ?? env_default.S3_BUCKET;
2457
- const s3AccessKeyId = providedS3AccessKeyId ?? env_default.S3_ACCESS_KEY_ID;
2458
- const s3SecretAccessKey = providedS3SecretAccessKey ?? env_default.S3_SECRET_ACCESS_KEY;
2449
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2450
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2459
2451
  const uploadToMux = uploadToMuxOption !== false;
2460
2452
  const config = await createWorkflowConfig(
2461
2453
  { ...options, model },
@@ -2464,8 +2456,8 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2464
2456
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2465
2457
  throw new Error("S3 configuration is required for uploading to Mux. Provide s3Endpoint, s3Bucket, s3AccessKeyId, and s3SecretAccessKey in options or set S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY environment variables.");
2466
2458
  }
2467
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
2468
- const signingContext = await resolveSigningContext(options);
2459
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2460
+ const signingContext = getMuxSigningContextFromEnv();
2469
2461
  if (policy === "signed" && !signingContext) {
2470
2462
  throw new Error(
2471
2463
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -2499,7 +2491,6 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2499
2491
  toLanguageCode,
2500
2492
  provider: config.provider,
2501
2493
  modelId: config.modelId,
2502
- credentials: config.credentials,
2503
2494
  abortSignal: options.abortSignal
2504
2495
  });
2505
2496
  translatedVtt = result.translatedVtt;
@@ -2530,9 +2521,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2530
2521
  toLanguageCode,
2531
2522
  s3Endpoint,
2532
2523
  s3Region,
2533
- s3Bucket,
2534
- s3AccessKeyId,
2535
- s3SecretAccessKey
2524
+ s3Bucket
2536
2525
  });
2537
2526
  } catch (error) {
2538
2527
  throw new Error(`Failed to upload VTT to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2541,7 +2530,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2541
2530
  try {
2542
2531
  const languageName = getLanguageName(toLanguageCode);
2543
2532
  const trackName = `${languageName} (auto-translated)`;
2544
- uploadedTrackId = await createTextTrackOnMux(config.credentials, assetId, toLanguageCode, trackName, presignedUrl);
2533
+ uploadedTrackId = await createTextTrackOnMux(assetId, toLanguageCode, trackName, presignedUrl);
2545
2534
  } catch (error) {
2546
2535
  console.warn(`Failed to add track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
2547
2536
  }