@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.
@@ -66,22 +66,22 @@ function requireEnv(value, name) {
66
66
  }
67
67
  return value;
68
68
  }
69
- function createLanguageModelFromConfig(provider, modelId, credentials) {
69
+ function createLanguageModelFromConfig(provider, modelId) {
70
70
  switch (provider) {
71
71
  case "openai": {
72
- const apiKey = credentials.openaiApiKey;
72
+ const apiKey = env_default.OPENAI_API_KEY;
73
73
  requireEnv(apiKey, "OPENAI_API_KEY");
74
74
  const openai = createOpenAI({ apiKey });
75
75
  return openai(modelId);
76
76
  }
77
77
  case "anthropic": {
78
- const apiKey = credentials.anthropicApiKey;
78
+ const apiKey = env_default.ANTHROPIC_API_KEY;
79
79
  requireEnv(apiKey, "ANTHROPIC_API_KEY");
80
80
  const anthropic = createAnthropic({ apiKey });
81
81
  return anthropic(modelId);
82
82
  }
83
83
  case "google": {
84
- const apiKey = credentials.googleApiKey;
84
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
85
85
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
86
86
  const google = createGoogleGenerativeAI({ apiKey });
87
87
  return google(modelId);
@@ -92,16 +92,16 @@ function createLanguageModelFromConfig(provider, modelId, credentials) {
92
92
  }
93
93
  }
94
94
  }
95
- function createEmbeddingModelFromConfig(provider, modelId, credentials) {
95
+ function createEmbeddingModelFromConfig(provider, modelId) {
96
96
  switch (provider) {
97
97
  case "openai": {
98
- const apiKey = credentials.openaiApiKey;
98
+ const apiKey = env_default.OPENAI_API_KEY;
99
99
  requireEnv(apiKey, "OPENAI_API_KEY");
100
100
  const openai = createOpenAI({ apiKey });
101
101
  return openai.embedding(modelId);
102
102
  }
103
103
  case "google": {
104
- const apiKey = credentials.googleApiKey;
104
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
105
105
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
106
106
  const google = createGoogleGenerativeAI({ apiKey });
107
107
  return google.textEmbeddingModel(modelId);
@@ -117,7 +117,7 @@ function resolveLanguageModel(options = {}) {
117
117
  const modelId = options.model || DEFAULT_LANGUAGE_MODELS[provider];
118
118
  switch (provider) {
119
119
  case "openai": {
120
- const apiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
120
+ const apiKey = env_default.OPENAI_API_KEY;
121
121
  requireEnv(apiKey, "OPENAI_API_KEY");
122
122
  const openai = createOpenAI({
123
123
  apiKey
@@ -129,7 +129,7 @@ function resolveLanguageModel(options = {}) {
129
129
  };
130
130
  }
131
131
  case "anthropic": {
132
- const apiKey = options.anthropicApiKey ?? env_default.ANTHROPIC_API_KEY;
132
+ const apiKey = env_default.ANTHROPIC_API_KEY;
133
133
  requireEnv(apiKey, "ANTHROPIC_API_KEY");
134
134
  const anthropic = createAnthropic({
135
135
  apiKey
@@ -141,7 +141,7 @@ function resolveLanguageModel(options = {}) {
141
141
  };
142
142
  }
143
143
  case "google": {
144
- const apiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
144
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
145
145
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
146
146
  const google = createGoogleGenerativeAI({
147
147
  apiKey
@@ -163,7 +163,7 @@ function resolveEmbeddingModel(options = {}) {
163
163
  const modelId = options.model || DEFAULT_EMBEDDING_MODELS[provider];
164
164
  switch (provider) {
165
165
  case "openai": {
166
- const apiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
166
+ const apiKey = env_default.OPENAI_API_KEY;
167
167
  requireEnv(apiKey, "OPENAI_API_KEY");
168
168
  const openai = createOpenAI({
169
169
  apiKey
@@ -175,7 +175,7 @@ function resolveEmbeddingModel(options = {}) {
175
175
  };
176
176
  }
177
177
  case "google": {
178
- const apiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
178
+ const apiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
179
179
  requireEnv(apiKey, "GOOGLE_GENERATIVE_AI_API_KEY");
180
180
  const google = createGoogleGenerativeAI({
181
181
  apiKey
@@ -194,13 +194,45 @@ function resolveEmbeddingModel(options = {}) {
194
194
  }
195
195
 
196
196
  // src/lib/client-factory.ts
197
- async function validateCredentials(options, requiredProvider) {
198
- "use step";
199
- const muxTokenId = options.muxTokenId ?? env_default.MUX_TOKEN_ID;
200
- const muxTokenSecret = options.muxTokenSecret ?? env_default.MUX_TOKEN_SECRET;
201
- const openaiApiKey = options.openaiApiKey ?? env_default.OPENAI_API_KEY;
202
- const anthropicApiKey = options.anthropicApiKey ?? env_default.ANTHROPIC_API_KEY;
203
- const googleApiKey = options.googleApiKey ?? env_default.GOOGLE_GENERATIVE_AI_API_KEY;
197
+ function getMuxCredentialsFromEnv() {
198
+ const muxTokenId = env_default.MUX_TOKEN_ID;
199
+ const muxTokenSecret = env_default.MUX_TOKEN_SECRET;
200
+ if (!muxTokenId || !muxTokenSecret) {
201
+ throw new Error(
202
+ "Mux credentials are required. Set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables."
203
+ );
204
+ }
205
+ return { muxTokenId, muxTokenSecret };
206
+ }
207
+ function getApiKeyFromEnv(provider) {
208
+ const envVarMap = {
209
+ openai: env_default.OPENAI_API_KEY,
210
+ anthropic: env_default.ANTHROPIC_API_KEY,
211
+ google: env_default.GOOGLE_GENERATIVE_AI_API_KEY,
212
+ hive: env_default.HIVE_API_KEY,
213
+ elevenlabs: env_default.ELEVENLABS_API_KEY
214
+ };
215
+ const apiKey = envVarMap[provider];
216
+ if (!apiKey) {
217
+ const envVarNames = {
218
+ openai: "OPENAI_API_KEY",
219
+ anthropic: "ANTHROPIC_API_KEY",
220
+ google: "GOOGLE_GENERATIVE_AI_API_KEY",
221
+ hive: "HIVE_API_KEY",
222
+ elevenlabs: "ELEVENLABS_API_KEY"
223
+ };
224
+ throw new Error(
225
+ `${provider} API key is required. Set ${envVarNames[provider]} environment variable.`
226
+ );
227
+ }
228
+ return apiKey;
229
+ }
230
+ async function validateCredentials(requiredProvider) {
231
+ const muxTokenId = env_default.MUX_TOKEN_ID;
232
+ const muxTokenSecret = env_default.MUX_TOKEN_SECRET;
233
+ const openaiApiKey = env_default.OPENAI_API_KEY;
234
+ const anthropicApiKey = env_default.ANTHROPIC_API_KEY;
235
+ const googleApiKey = env_default.GOOGLE_GENERATIVE_AI_API_KEY;
204
236
  if (!muxTokenId || !muxTokenSecret) {
205
237
  throw new Error(
206
238
  "Mux credentials are required. Provide muxTokenId and muxTokenSecret in options or set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables."
@@ -230,9 +262,8 @@ async function validateCredentials(options, requiredProvider) {
230
262
  };
231
263
  }
232
264
  async function createWorkflowConfig(options, provider) {
233
- "use step";
234
265
  const providerToUse = provider || options.provider || "openai";
235
- const credentials = await validateCredentials(options, providerToUse);
266
+ const credentials = await validateCredentials(providerToUse);
236
267
  const resolved = resolveLanguageModel({
237
268
  ...options,
238
269
  provider: providerToUse
@@ -353,11 +384,12 @@ function getPlaybackId(asset) {
353
384
  "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."
354
385
  );
355
386
  }
356
- async function getPlaybackIdForAsset(credentials, assetId) {
387
+ async function getPlaybackIdForAsset(assetId) {
357
388
  "use step";
389
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
358
390
  const mux = new Mux({
359
- tokenId: credentials.muxTokenId,
360
- tokenSecret: credentials.muxTokenSecret
391
+ tokenId: muxTokenId,
392
+ tokenSecret: muxTokenSecret
361
393
  });
362
394
  const asset = await mux.video.assets.retrieve(assetId);
363
395
  const { id: playbackId, policy } = getPlaybackId(asset);
@@ -440,10 +472,9 @@ function createToneSection(instruction) {
440
472
 
441
473
  // src/lib/url-signing.ts
442
474
  import Mux2 from "@mux/mux-node";
443
- async function resolveSigningContext(config) {
444
- "use step";
445
- const keyId = config.muxSigningKey ?? env_default.MUX_SIGNING_KEY;
446
- const keySecret = config.muxPrivateKey ?? env_default.MUX_PRIVATE_KEY;
475
+ function getMuxSigningContextFromEnv() {
476
+ const keyId = env_default.MUX_SIGNING_KEY;
477
+ const keySecret = env_default.MUX_PRIVATE_KEY;
447
478
  if (!keyId || !keySecret) {
448
479
  return void 0;
449
480
  }
@@ -480,10 +511,11 @@ async function signUrl(url, playbackId, context, type = "video", params) {
480
511
 
481
512
  // src/primitives/storyboards.ts
482
513
  var DEFAULT_STORYBOARD_WIDTH = 640;
483
- async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, signingContext) {
514
+ async function getStoryboardUrl(playbackId, width = DEFAULT_STORYBOARD_WIDTH, shouldSign = false) {
484
515
  "use step";
485
516
  const baseUrl = `https://image.mux.com/${playbackId}/storyboard.png`;
486
- if (signingContext) {
517
+ if (shouldSign) {
518
+ const signingContext = getMuxSigningContextFromEnv();
487
519
  return signUrl(baseUrl, playbackId, signingContext, "storyboard", { width });
488
520
  }
489
521
  return `${baseUrl}?width=${width}`;
@@ -587,16 +619,11 @@ async function analyzeStoryboard({
587
619
  imageDataUrl,
588
620
  provider,
589
621
  modelId,
590
- credentials,
591
622
  userPrompt,
592
623
  systemPrompt
593
624
  }) {
594
625
  "use step";
595
- const model = createLanguageModelFromConfig(
596
- provider,
597
- modelId,
598
- credentials
599
- );
626
+ const model = createLanguageModelFromConfig(provider, modelId);
600
627
  const response = await generateObject({
601
628
  model,
602
629
  schema: burnedInCaptionsSchema,
@@ -641,14 +668,14 @@ async function hasBurnedInCaptions(assetId, options = {}) {
641
668
  { ...config, model },
642
669
  provider
643
670
  );
644
- const { playbackId, policy } = await getPlaybackIdForAsset(workflowConfig.credentials, assetId);
645
- const signingContext = await resolveSigningContext(options);
671
+ const { playbackId, policy } = await getPlaybackIdForAsset(assetId);
672
+ const signingContext = getMuxSigningContextFromEnv();
646
673
  if (policy === "signed" && !signingContext) {
647
674
  throw new Error(
648
675
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
649
676
  );
650
677
  }
651
- const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed" ? signingContext : void 0);
678
+ const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed");
652
679
  let analysisResponse;
653
680
  if (imageSubmissionMode === "base64") {
654
681
  const base64Data = await fetchImageAsBase64(imageUrl, imageDownloadOptions);
@@ -656,7 +683,6 @@ async function hasBurnedInCaptions(assetId, options = {}) {
656
683
  imageDataUrl: base64Data,
657
684
  provider: workflowConfig.provider,
658
685
  modelId: workflowConfig.modelId,
659
- credentials: workflowConfig.credentials,
660
686
  userPrompt,
661
687
  systemPrompt: SYSTEM_PROMPT
662
688
  });
@@ -665,7 +691,6 @@ async function hasBurnedInCaptions(assetId, options = {}) {
665
691
  imageDataUrl: imageUrl,
666
692
  provider: workflowConfig.provider,
667
693
  modelId: workflowConfig.modelId,
668
- credentials: workflowConfig.credentials,
669
694
  userPrompt,
670
695
  systemPrompt: SYSTEM_PROMPT
671
696
  });
@@ -835,17 +860,18 @@ function parseVTTCues(vttContent) {
835
860
  }
836
861
  return cues;
837
862
  }
838
- async function buildTranscriptUrl(playbackId, trackId, signingContext) {
863
+ async function buildTranscriptUrl(playbackId, trackId, shouldSign = false) {
839
864
  "use step";
840
865
  const baseUrl = `https://stream.mux.com/${playbackId}/text/${trackId}.vtt`;
841
- if (signingContext) {
866
+ if (shouldSign) {
867
+ const signingContext = getMuxSigningContextFromEnv();
842
868
  return signUrl(baseUrl, playbackId, signingContext, "video");
843
869
  }
844
870
  return baseUrl;
845
871
  }
846
872
  async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
847
873
  "use step";
848
- const { languageCode, cleanTranscript = true, signingContext } = options;
874
+ const { languageCode, cleanTranscript = true, shouldSign } = options;
849
875
  const track = findCaptionTrack(asset, languageCode);
850
876
  if (!track) {
851
877
  return { transcriptText: "" };
@@ -853,7 +879,7 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
853
879
  if (!track.id) {
854
880
  return { transcriptText: "", track };
855
881
  }
856
- const transcriptUrl = await buildTranscriptUrl(playbackId, track.id, signingContext);
882
+ const transcriptUrl = await buildTranscriptUrl(playbackId, track.id, shouldSign);
857
883
  try {
858
884
  const response = await fetch(transcriptUrl);
859
885
  if (!response.ok) {
@@ -879,16 +905,11 @@ var chaptersSchema = z3.object({
879
905
  async function generateChaptersWithAI({
880
906
  provider,
881
907
  modelId,
882
- credentials,
883
908
  timestampedTranscript,
884
909
  systemPrompt
885
910
  }) {
886
911
  "use step";
887
- const model = createLanguageModelFromConfig(
888
- provider,
889
- modelId,
890
- credentials
891
- );
912
+ const model = createLanguageModelFromConfig(provider, modelId);
892
913
  const response = await withRetry(
893
914
  () => generateObject2({
894
915
  model,
@@ -931,8 +952,8 @@ async function generateChapters(assetId, languageCode, options = {}) {
931
952
  "use workflow";
932
953
  const { provider = "openai", model } = options;
933
954
  const config = await createWorkflowConfig({ ...options, model }, provider);
934
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
935
- const signingContext = await resolveSigningContext(options);
955
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
956
+ const signingContext = getMuxSigningContextFromEnv();
936
957
  if (policy === "signed" && !signingContext) {
937
958
  throw new Error(
938
959
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -942,7 +963,7 @@ async function generateChapters(assetId, languageCode, options = {}) {
942
963
  languageCode,
943
964
  cleanTranscript: false,
944
965
  // keep timestamps for chapter segmentation
945
- signingContext: policy === "signed" ? signingContext : void 0
966
+ shouldSign: policy === "signed"
946
967
  });
947
968
  if (!transcriptResult.track || !transcriptResult.transcriptText) {
948
969
  const availableLanguages = getReadyTextTracks(assetData).map((t) => t.language_code).filter(Boolean).join(", ");
@@ -959,7 +980,6 @@ async function generateChapters(assetId, languageCode, options = {}) {
959
980
  chaptersData = await generateChaptersWithAI({
960
981
  provider: config.provider,
961
982
  modelId: config.modelId,
962
- credentials: config.credentials,
963
983
  timestampedTranscript,
964
984
  systemPrompt: SYSTEM_PROMPT2
965
985
  });
@@ -1093,11 +1113,10 @@ function averageEmbeddings(embeddings) {
1093
1113
  async function generateSingleChunkEmbedding({
1094
1114
  chunk,
1095
1115
  provider,
1096
- modelId,
1097
- credentials
1116
+ modelId
1098
1117
  }) {
1099
1118
  "use step";
1100
- const model = createEmbeddingModelFromConfig(provider, modelId, credentials);
1119
+ const model = createEmbeddingModelFromConfig(provider, modelId);
1101
1120
  const response = await withRetry(
1102
1121
  () => embed({
1103
1122
  model,
@@ -1123,13 +1142,9 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1123
1142
  chunkingStrategy = { type: "token", maxTokens: 500, overlap: 100 },
1124
1143
  batchSize = 5
1125
1144
  } = options;
1126
- const credentials = await validateCredentials(options, provider === "google" ? "google" : "openai");
1127
1145
  const embeddingModel = resolveEmbeddingModel({ ...options, provider, model });
1128
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(
1129
- credentials,
1130
- assetId
1131
- );
1132
- const signingContext = await resolveSigningContext(options);
1146
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1147
+ const signingContext = getMuxSigningContextFromEnv();
1133
1148
  if (policy === "signed" && !signingContext) {
1134
1149
  throw new Error(
1135
1150
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1139,7 +1154,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1139
1154
  const transcriptResult = await fetchTranscriptForAsset(assetData, playbackId, {
1140
1155
  languageCode,
1141
1156
  cleanTranscript: !useVttChunking,
1142
- signingContext: policy === "signed" ? signingContext : void 0
1157
+ shouldSign: policy === "signed"
1143
1158
  });
1144
1159
  if (!transcriptResult.track || !transcriptResult.transcriptText) {
1145
1160
  const availableLanguages = getReadyTextTracks(assetData).map((t) => t.language_code).filter(Boolean).join(", ");
@@ -1168,8 +1183,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1168
1183
  (chunk) => generateSingleChunkEmbedding({
1169
1184
  chunk,
1170
1185
  provider: embeddingModel.provider,
1171
- modelId: embeddingModel.modelId,
1172
- credentials
1186
+ modelId: embeddingModel.modelId
1173
1187
  })
1174
1188
  )
1175
1189
  );
@@ -1204,7 +1218,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
1204
1218
  // src/primitives/thumbnails.ts
1205
1219
  async function getThumbnailUrls(playbackId, duration, options = {}) {
1206
1220
  "use step";
1207
- const { interval = 10, width = 640, signingContext } = options;
1221
+ const { interval = 10, width = 640, shouldSign = false } = options;
1208
1222
  const timestamps = [];
1209
1223
  if (duration <= 50) {
1210
1224
  const spacing = duration / 6;
@@ -1218,7 +1232,8 @@ async function getThumbnailUrls(playbackId, duration, options = {}) {
1218
1232
  }
1219
1233
  const baseUrl = `https://image.mux.com/${playbackId}/thumbnail.png`;
1220
1234
  const urlPromises = timestamps.map(async (time) => {
1221
- if (signingContext) {
1235
+ if (shouldSign) {
1236
+ const signingContext = getMuxSigningContextFromEnv();
1222
1237
  return signUrl(baseUrl, playbackId, signingContext, "thumbnail", { time, width });
1223
1238
  }
1224
1239
  return `${baseUrl}?time=${time}&width=${width}`;
@@ -1279,19 +1294,20 @@ async function processConcurrently(items, processor, maxConcurrent = 5) {
1279
1294
  }
1280
1295
  return results;
1281
1296
  }
1282
- async function requestOpenAIModeration(imageUrls, apiKey, model, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1297
+ async function requestOpenAIModeration(imageUrls, model, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1283
1298
  "use step";
1284
1299
  const targetUrls = submissionMode === "base64" ? (await downloadImagesAsBase64(imageUrls, downloadOptions, maxConcurrent)).map(
1285
- (img) => ({ url: img.url, image: img.base64Data, apiKey, model })
1286
- ) : imageUrls.map((url) => ({ url, image: url, apiKey, model }));
1300
+ (img) => ({ url: img.url, image: img.base64Data, model })
1301
+ ) : imageUrls.map((url) => ({ url, image: url, model }));
1287
1302
  const moderate = async (entry) => {
1288
1303
  "use step";
1304
+ const apiKey = getApiKeyFromEnv("openai");
1289
1305
  try {
1290
1306
  const res = await fetch("https://api.openai.com/v1/moderations", {
1291
1307
  method: "POST",
1292
1308
  headers: {
1293
1309
  "Content-Type": "application/json",
1294
- "Authorization": `Bearer ${entry.apiKey}`
1310
+ "Authorization": `Bearer ${apiKey}`
1295
1311
  },
1296
1312
  body: JSON.stringify({
1297
1313
  model: entry.model,
@@ -1337,7 +1353,7 @@ function getHiveCategoryScores(classes, categoryNames) {
1337
1353
  const scores = categoryNames.map((category) => scoreMap[category] || 0);
1338
1354
  return Math.max(...scores, 0);
1339
1355
  }
1340
- async function requestHiveModeration(imageUrls, apiKey, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1356
+ async function requestHiveModeration(imageUrls, maxConcurrent = 5, submissionMode = "url", downloadOptions) {
1341
1357
  "use step";
1342
1358
  const targets = submissionMode === "base64" ? (await downloadImagesAsBase64(imageUrls, downloadOptions, maxConcurrent)).map((img) => ({
1343
1359
  url: img.url,
@@ -1352,6 +1368,7 @@ async function requestHiveModeration(imageUrls, apiKey, maxConcurrent = 5, submi
1352
1368
  }));
1353
1369
  const moderate = async (entry) => {
1354
1370
  "use step";
1371
+ const apiKey = getApiKeyFromEnv("hive");
1355
1372
  try {
1356
1373
  const formData = new FormData();
1357
1374
  if (entry.source.kind === "url") {
@@ -1408,10 +1425,9 @@ async function getModerationScores(assetId, options = {}) {
1408
1425
  imageSubmissionMode = "url",
1409
1426
  imageDownloadOptions
1410
1427
  } = options;
1411
- const credentials = await validateCredentials(options, provider === "openai" ? "openai" : void 0);
1412
- const { asset, playbackId, policy } = await getPlaybackIdForAsset(credentials, assetId);
1428
+ const { asset, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1413
1429
  const duration = asset.duration || 0;
1414
- const signingContext = await resolveSigningContext(options);
1430
+ const signingContext = getMuxSigningContextFromEnv();
1415
1431
  if (policy === "signed" && !signingContext) {
1416
1432
  throw new Error(
1417
1433
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1420,30 +1436,20 @@ async function getModerationScores(assetId, options = {}) {
1420
1436
  const thumbnailUrls = await getThumbnailUrls(playbackId, duration, {
1421
1437
  interval: thumbnailInterval,
1422
1438
  width: thumbnailWidth,
1423
- signingContext: policy === "signed" ? signingContext : void 0
1439
+ shouldSign: policy === "signed"
1424
1440
  });
1425
1441
  let thumbnailScores;
1426
1442
  if (provider === "openai") {
1427
- const apiKey = credentials.openaiApiKey;
1428
- if (!apiKey) {
1429
- throw new Error("OpenAI API key is required for moderation. Set OPENAI_API_KEY or pass openaiApiKey.");
1430
- }
1431
1443
  thumbnailScores = await requestOpenAIModeration(
1432
1444
  thumbnailUrls,
1433
- apiKey,
1434
1445
  model || "omni-moderation-latest",
1435
1446
  maxConcurrent,
1436
1447
  imageSubmissionMode,
1437
1448
  imageDownloadOptions
1438
1449
  );
1439
1450
  } else if (provider === "hive") {
1440
- const hiveApiKey = options.hiveApiKey || env_default.HIVE_API_KEY;
1441
- if (!hiveApiKey) {
1442
- throw new Error("Hive API key is required for moderation. Set HIVE_API_KEY or pass hiveApiKey.");
1443
- }
1444
1451
  thumbnailScores = await requestHiveModeration(
1445
1452
  thumbnailUrls,
1446
- hiveApiKey,
1447
1453
  maxConcurrent,
1448
1454
  imageSubmissionMode,
1449
1455
  imageDownloadOptions
@@ -1477,8 +1483,8 @@ var summarySchema = z4.object({
1477
1483
  description: z4.string()
1478
1484
  });
1479
1485
  var TONE_INSTRUCTIONS = {
1480
- normal: "Provide a clear, straightforward analysis.",
1481
- 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!",
1486
+ neutral: "Provide a clear, straightforward analysis.",
1487
+ 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!",
1482
1488
  professional: "Provide a professional, executive-level analysis suitable for business reporting."
1483
1489
  };
1484
1490
  var summarizationPromptBuilder = createPromptBuilder({
@@ -1594,13 +1600,9 @@ function buildUserPrompt2({
1594
1600
  }
1595
1601
  return summarizationPromptBuilder.buildWithContext(promptOverrides, contextSections);
1596
1602
  }
1597
- async function analyzeStoryboard2(imageDataUrl, workflowConfig, userPrompt, systemPrompt) {
1603
+ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, systemPrompt) {
1598
1604
  "use step";
1599
- const model = createLanguageModelFromConfig(
1600
- workflowConfig.provider,
1601
- workflowConfig.modelId,
1602
- workflowConfig.credentials
1603
- );
1605
+ const model = createLanguageModelFromConfig(provider, modelId);
1604
1606
  const response = await generateObject3({
1605
1607
  model,
1606
1608
  schema: summarySchema,
@@ -1657,7 +1659,7 @@ async function getSummaryAndTags(assetId, options) {
1657
1659
  const {
1658
1660
  provider = "openai",
1659
1661
  model,
1660
- tone = "normal",
1662
+ tone = "neutral",
1661
1663
  includeTranscript = true,
1662
1664
  cleanTranscript = true,
1663
1665
  imageSubmissionMode = "url",
@@ -1669,8 +1671,8 @@ async function getSummaryAndTags(assetId, options) {
1669
1671
  { ...options, model },
1670
1672
  provider
1671
1673
  );
1672
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
1673
- const signingContext = await resolveSigningContext(options ?? {});
1674
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1675
+ const signingContext = getMuxSigningContextFromEnv();
1674
1676
  if (policy === "signed" && !signingContext) {
1675
1677
  throw new Error(
1676
1678
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -1678,7 +1680,7 @@ async function getSummaryAndTags(assetId, options) {
1678
1680
  }
1679
1681
  const transcriptText = includeTranscript ? (await fetchTranscriptForAsset(assetData, playbackId, {
1680
1682
  cleanTranscript,
1681
- signingContext: policy === "signed" ? signingContext : void 0
1683
+ shouldSign: policy === "signed"
1682
1684
  })).transcriptText : "";
1683
1685
  const userPrompt = buildUserPrompt2({
1684
1686
  tone,
@@ -1686,19 +1688,20 @@ async function getSummaryAndTags(assetId, options) {
1686
1688
  isCleanTranscript: cleanTranscript,
1687
1689
  promptOverrides
1688
1690
  });
1689
- const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed" ? signingContext : void 0);
1691
+ const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed");
1690
1692
  let analysisResponse;
1691
1693
  try {
1692
1694
  if (imageSubmissionMode === "base64") {
1693
1695
  const downloadResult = await downloadImageAsBase64(imageUrl, imageDownloadOptions);
1694
1696
  analysisResponse = await analyzeStoryboard2(
1695
1697
  downloadResult.base64Data,
1696
- config,
1698
+ config.provider,
1699
+ config.modelId,
1697
1700
  userPrompt,
1698
1701
  SYSTEM_PROMPT3
1699
1702
  );
1700
1703
  } else {
1701
- analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config, userPrompt, SYSTEM_PROMPT3));
1704
+ analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config.provider, config.modelId, userPrompt, SYSTEM_PROMPT3));
1702
1705
  }
1703
1706
  } catch (error) {
1704
1707
  throw new Error(
@@ -1903,11 +1906,12 @@ function getReadyAudioStaticRendition(asset) {
1903
1906
  );
1904
1907
  }
1905
1908
  var hasReadyAudioStaticRendition = (asset) => Boolean(getReadyAudioStaticRendition(asset));
1906
- async function requestStaticRenditionCreation(credentials, assetId) {
1909
+ async function requestStaticRenditionCreation(assetId) {
1907
1910
  "use step";
1911
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1908
1912
  const mux = new Mux3({
1909
- tokenId: credentials.muxTokenId,
1910
- tokenSecret: credentials.muxTokenSecret
1913
+ tokenId: muxTokenId,
1914
+ tokenSecret: muxTokenSecret
1911
1915
  });
1912
1916
  try {
1913
1917
  await mux.video.assets.createStaticRendition(assetId, {
@@ -1926,13 +1930,13 @@ async function requestStaticRenditionCreation(credentials, assetId) {
1926
1930
  }
1927
1931
  async function waitForAudioStaticRendition({
1928
1932
  assetId,
1929
- credentials,
1930
1933
  initialAsset
1931
1934
  }) {
1932
1935
  "use step";
1936
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1933
1937
  const mux = new Mux3({
1934
- tokenId: credentials.muxTokenId,
1935
- tokenSecret: credentials.muxTokenSecret
1938
+ tokenId: muxTokenId,
1939
+ tokenSecret: muxTokenSecret
1936
1940
  });
1937
1941
  let currentAsset = initialAsset;
1938
1942
  if (hasReadyAudioStaticRendition(currentAsset)) {
@@ -1940,9 +1944,9 @@ async function waitForAudioStaticRendition({
1940
1944
  }
1941
1945
  const status = currentAsset.static_renditions?.status ?? "not_requested";
1942
1946
  if (status === "not_requested" || status === void 0) {
1943
- await requestStaticRenditionCreation(credentials, assetId);
1947
+ await requestStaticRenditionCreation(assetId);
1944
1948
  } else if (status === "errored") {
1945
- await requestStaticRenditionCreation(credentials, assetId);
1949
+ await requestStaticRenditionCreation(assetId);
1946
1950
  } else {
1947
1951
  console.warn(`\u2139\uFE0F Static rendition already ${status}. Waiting for it to finish...`);
1948
1952
  }
@@ -1978,10 +1982,10 @@ async function createElevenLabsDubbingJob({
1978
1982
  audioBuffer,
1979
1983
  assetId,
1980
1984
  elevenLabsLangCode,
1981
- elevenLabsApiKey,
1982
1985
  numSpeakers
1983
1986
  }) {
1984
1987
  "use step";
1988
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
1985
1989
  const audioBlob = new Blob([audioBuffer], { type: "audio/mp4" });
1986
1990
  const formData = new FormData();
1987
1991
  formData.append("file", audioBlob);
@@ -2002,10 +2006,10 @@ async function createElevenLabsDubbingJob({
2002
2006
  return dubbingData.dubbing_id;
2003
2007
  }
2004
2008
  async function checkElevenLabsDubbingStatus({
2005
- dubbingId,
2006
- elevenLabsApiKey
2009
+ dubbingId
2007
2010
  }) {
2008
2011
  "use step";
2012
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2009
2013
  const statusResponse = await fetch(`https://api.elevenlabs.io/v1/dubbing/${dubbingId}`, {
2010
2014
  headers: {
2011
2015
  "xi-api-key": elevenLabsApiKey
@@ -2022,10 +2026,10 @@ async function checkElevenLabsDubbingStatus({
2022
2026
  }
2023
2027
  async function downloadDubbedAudioFromElevenLabs({
2024
2028
  dubbingId,
2025
- languageCode,
2026
- elevenLabsApiKey
2029
+ languageCode
2027
2030
  }) {
2028
2031
  "use step";
2032
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2029
2033
  const audioUrl = `https://api.elevenlabs.io/v1/dubbing/${dubbingId}/audio/${languageCode}`;
2030
2034
  const audioResponse = await fetch(audioUrl, {
2031
2035
  headers: {
@@ -2043,14 +2047,14 @@ async function uploadDubbedAudioToS3({
2043
2047
  toLanguageCode,
2044
2048
  s3Endpoint,
2045
2049
  s3Region,
2046
- s3Bucket,
2047
- s3AccessKeyId,
2048
- s3SecretAccessKey
2050
+ s3Bucket
2049
2051
  }) {
2050
2052
  "use step";
2051
2053
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2052
2054
  const { Upload } = await import("@aws-sdk/lib-storage");
2053
2055
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2056
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2057
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2054
2058
  const s3Client = new S3Client({
2055
2059
  region: s3Region,
2056
2060
  endpoint: s3Endpoint,
@@ -2083,11 +2087,12 @@ async function uploadDubbedAudioToS3({
2083
2087
  console.warn(`\u{1F517} Generated presigned URL (expires in 1 hour)`);
2084
2088
  return presignedUrl;
2085
2089
  }
2086
- async function createAudioTrackOnMux(credentials, assetId, languageCode, presignedUrl) {
2090
+ async function createAudioTrackOnMux(assetId, languageCode, presignedUrl) {
2087
2091
  "use step";
2092
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2088
2093
  const mux = new Mux3({
2089
- tokenId: credentials.muxTokenId,
2090
- tokenSecret: credentials.muxTokenSecret
2094
+ tokenId: muxTokenId,
2095
+ tokenSecret: muxTokenSecret
2091
2096
  });
2092
2097
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(languageCode) || languageCode.toUpperCase();
2093
2098
  const trackName = `${languageName} (auto-dubbed)`;
@@ -2114,21 +2119,20 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2114
2119
  if (provider !== "elevenlabs") {
2115
2120
  throw new Error("Only ElevenLabs provider is currently supported for audio translation");
2116
2121
  }
2117
- const credentials = await validateCredentials(options);
2118
2122
  const elevenLabsKey = elevenLabsApiKey ?? env_default.ELEVENLABS_API_KEY;
2119
2123
  const s3Endpoint = options.s3Endpoint ?? env_default.S3_ENDPOINT;
2120
2124
  const s3Region = options.s3Region ?? env_default.S3_REGION ?? "auto";
2121
2125
  const s3Bucket = options.s3Bucket ?? env_default.S3_BUCKET;
2122
- const s3AccessKeyId = options.s3AccessKeyId ?? env_default.S3_ACCESS_KEY_ID;
2123
- const s3SecretAccessKey = options.s3SecretAccessKey ?? env_default.S3_SECRET_ACCESS_KEY;
2126
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2127
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2124
2128
  if (!elevenLabsKey) {
2125
2129
  throw new Error("ElevenLabs API key is required. Provide elevenLabsApiKey in options or set ELEVENLABS_API_KEY environment variable.");
2126
2130
  }
2127
2131
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2128
2132
  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.");
2129
2133
  }
2130
- const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(credentials, assetId);
2131
- const signingContext = await resolveSigningContext(options);
2134
+ const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2135
+ const signingContext = getMuxSigningContextFromEnv();
2132
2136
  if (policy === "signed" && !signingContext) {
2133
2137
  throw new Error(
2134
2138
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -2139,7 +2143,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2139
2143
  console.warn("\u274C No ready audio static rendition found. Requesting one now...");
2140
2144
  currentAsset = await waitForAudioStaticRendition({
2141
2145
  assetId,
2142
- credentials,
2143
2146
  initialAsset: currentAsset
2144
2147
  });
2145
2148
  }
@@ -2169,7 +2172,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2169
2172
  audioBuffer,
2170
2173
  assetId,
2171
2174
  elevenLabsLangCode,
2172
- elevenLabsApiKey: elevenLabsKey,
2173
2175
  numSpeakers
2174
2176
  });
2175
2177
  console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
@@ -2186,8 +2188,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2186
2188
  pollAttempts++;
2187
2189
  try {
2188
2190
  const statusResult = await checkElevenLabsDubbingStatus({
2189
- dubbingId,
2190
- elevenLabsApiKey: elevenLabsKey
2191
+ dubbingId
2191
2192
  });
2192
2193
  dubbingStatus = statusResult.status;
2193
2194
  targetLanguages = statusResult.targetLanguages;
@@ -2230,8 +2231,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2230
2231
  }
2231
2232
  dubbedAudioBuffer = await downloadDubbedAudioFromElevenLabs({
2232
2233
  dubbingId,
2233
- languageCode: downloadLangCode,
2234
- elevenLabsApiKey: elevenLabsKey
2234
+ languageCode: downloadLangCode
2235
2235
  });
2236
2236
  console.warn("\u2705 Dubbed audio downloaded successfully!");
2237
2237
  } catch (error) {
@@ -2246,9 +2246,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2246
2246
  toLanguageCode,
2247
2247
  s3Endpoint,
2248
2248
  s3Region,
2249
- s3Bucket,
2250
- s3AccessKeyId,
2251
- s3SecretAccessKey
2249
+ s3Bucket
2252
2250
  });
2253
2251
  } catch (error) {
2254
2252
  throw new Error(`Failed to upload audio to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2257,7 +2255,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2257
2255
  let uploadedTrackId;
2258
2256
  const muxLangCode = toISO639_1(toLanguageCode);
2259
2257
  try {
2260
- uploadedTrackId = await createAudioTrackOnMux(credentials, assetId, muxLangCode, presignedUrl);
2258
+ uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl);
2261
2259
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
2262
2260
  const trackName = `${languageName} (auto-dubbed)`;
2263
2261
  console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
@@ -2299,15 +2297,10 @@ async function translateVttWithAI({
2299
2297
  toLanguageCode,
2300
2298
  provider,
2301
2299
  modelId,
2302
- credentials,
2303
2300
  abortSignal
2304
2301
  }) {
2305
2302
  "use step";
2306
- const languageModel = createLanguageModelFromConfig(
2307
- provider,
2308
- modelId,
2309
- credentials
2310
- );
2303
+ const languageModel = createLanguageModelFromConfig(provider, modelId);
2311
2304
  const response = await generateObject4({
2312
2305
  model: languageModel,
2313
2306
  schema: translationSchema,
@@ -2339,14 +2332,14 @@ async function uploadVttToS3({
2339
2332
  toLanguageCode,
2340
2333
  s3Endpoint,
2341
2334
  s3Region,
2342
- s3Bucket,
2343
- s3AccessKeyId,
2344
- s3SecretAccessKey
2335
+ s3Bucket
2345
2336
  }) {
2346
2337
  "use step";
2347
2338
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2348
2339
  const { Upload } = await import("@aws-sdk/lib-storage");
2349
2340
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2341
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2342
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2350
2343
  const s3Client = new S3Client({
2351
2344
  region: s3Region,
2352
2345
  endpoint: s3Endpoint,
@@ -2377,11 +2370,12 @@ async function uploadVttToS3({
2377
2370
  });
2378
2371
  return presignedUrl;
2379
2372
  }
2380
- async function createTextTrackOnMux(credentials, assetId, languageCode, trackName, presignedUrl) {
2373
+ async function createTextTrackOnMux(assetId, languageCode, trackName, presignedUrl) {
2381
2374
  "use step";
2375
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2382
2376
  const mux = new Mux4({
2383
- tokenId: credentials.muxTokenId,
2384
- tokenSecret: credentials.muxTokenSecret
2377
+ tokenId: muxTokenId,
2378
+ tokenSecret: muxTokenSecret
2385
2379
  });
2386
2380
  const trackResponse = await mux.video.assets.createTrack(assetId, {
2387
2381
  type: "text",
@@ -2403,15 +2397,13 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2403
2397
  s3Endpoint: providedS3Endpoint,
2404
2398
  s3Region: providedS3Region,
2405
2399
  s3Bucket: providedS3Bucket,
2406
- s3AccessKeyId: providedS3AccessKeyId,
2407
- s3SecretAccessKey: providedS3SecretAccessKey,
2408
2400
  uploadToMux: uploadToMuxOption
2409
2401
  } = options;
2410
2402
  const s3Endpoint = providedS3Endpoint ?? env_default.S3_ENDPOINT;
2411
2403
  const s3Region = providedS3Region ?? env_default.S3_REGION ?? "auto";
2412
2404
  const s3Bucket = providedS3Bucket ?? env_default.S3_BUCKET;
2413
- const s3AccessKeyId = providedS3AccessKeyId ?? env_default.S3_ACCESS_KEY_ID;
2414
- const s3SecretAccessKey = providedS3SecretAccessKey ?? env_default.S3_SECRET_ACCESS_KEY;
2405
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2406
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2415
2407
  const uploadToMux = uploadToMuxOption !== false;
2416
2408
  const config = await createWorkflowConfig(
2417
2409
  { ...options, model },
@@ -2420,8 +2412,8 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2420
2412
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2421
2413
  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.");
2422
2414
  }
2423
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
2424
- const signingContext = await resolveSigningContext(options);
2415
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2416
+ const signingContext = getMuxSigningContextFromEnv();
2425
2417
  if (policy === "signed" && !signingContext) {
2426
2418
  throw new Error(
2427
2419
  "Signed playback ID requires signing credentials. Provide muxSigningKey and muxPrivateKey in options or set MUX_SIGNING_KEY and MUX_PRIVATE_KEY environment variables."
@@ -2455,7 +2447,6 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2455
2447
  toLanguageCode,
2456
2448
  provider: config.provider,
2457
2449
  modelId: config.modelId,
2458
- credentials: config.credentials,
2459
2450
  abortSignal: options.abortSignal
2460
2451
  });
2461
2452
  translatedVtt = result.translatedVtt;
@@ -2486,9 +2477,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2486
2477
  toLanguageCode,
2487
2478
  s3Endpoint,
2488
2479
  s3Region,
2489
- s3Bucket,
2490
- s3AccessKeyId,
2491
- s3SecretAccessKey
2480
+ s3Bucket
2492
2481
  });
2493
2482
  } catch (error) {
2494
2483
  throw new Error(`Failed to upload VTT to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2497,7 +2486,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2497
2486
  try {
2498
2487
  const languageName = getLanguageName(toLanguageCode);
2499
2488
  const trackName = `${languageName} (auto-translated)`;
2500
- uploadedTrackId = await createTextTrackOnMux(config.credentials, assetId, toLanguageCode, trackName, presignedUrl);
2489
+ uploadedTrackId = await createTextTrackOnMux(assetId, toLanguageCode, trackName, presignedUrl);
2501
2490
  } catch (error) {
2502
2491
  console.warn(`Failed to add track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
2503
2492
  }