@mux/ai 0.2.0 → 0.3.1

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
@@ -1476,9 +1482,10 @@ var summarySchema = z4.object({
1476
1482
  title: z4.string(),
1477
1483
  description: z4.string()
1478
1484
  });
1485
+ var VALID_TONES = ["neutral", "playful", "professional"];
1479
1486
  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!",
1487
+ neutral: "Provide a clear, straightforward analysis.",
1488
+ 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
1489
  professional: "Provide a professional, executive-level analysis suitable for business reporting."
1483
1490
  };
1484
1491
  var summarizationPromptBuilder = createPromptBuilder({
@@ -1594,13 +1601,9 @@ function buildUserPrompt2({
1594
1601
  }
1595
1602
  return summarizationPromptBuilder.buildWithContext(promptOverrides, contextSections);
1596
1603
  }
1597
- async function analyzeStoryboard2(imageDataUrl, workflowConfig, userPrompt, systemPrompt) {
1604
+ async function analyzeStoryboard2(imageDataUrl, provider, modelId, userPrompt, systemPrompt) {
1598
1605
  "use step";
1599
- const model = createLanguageModelFromConfig(
1600
- workflowConfig.provider,
1601
- workflowConfig.modelId,
1602
- workflowConfig.credentials
1603
- );
1606
+ const model = createLanguageModelFromConfig(provider, modelId);
1604
1607
  const response = await generateObject3({
1605
1608
  model,
1606
1609
  schema: summarySchema,
@@ -1657,7 +1660,7 @@ async function getSummaryAndTags(assetId, options) {
1657
1660
  const {
1658
1661
  provider = "openai",
1659
1662
  model,
1660
- tone = "normal",
1663
+ tone = "neutral",
1661
1664
  includeTranscript = true,
1662
1665
  cleanTranscript = true,
1663
1666
  imageSubmissionMode = "url",
@@ -1665,12 +1668,17 @@ async function getSummaryAndTags(assetId, options) {
1665
1668
  abortSignal: _abortSignal,
1666
1669
  promptOverrides
1667
1670
  } = options ?? {};
1671
+ if (!VALID_TONES.includes(tone)) {
1672
+ throw new Error(
1673
+ `Invalid tone "${tone}". Valid tones are: ${VALID_TONES.join(", ")}`
1674
+ );
1675
+ }
1668
1676
  const config = await createWorkflowConfig(
1669
1677
  { ...options, model },
1670
1678
  provider
1671
1679
  );
1672
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
1673
- const signingContext = await resolveSigningContext(options ?? {});
1680
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
1681
+ const signingContext = getMuxSigningContextFromEnv();
1674
1682
  if (policy === "signed" && !signingContext) {
1675
1683
  throw new Error(
1676
1684
  "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 +1686,7 @@ async function getSummaryAndTags(assetId, options) {
1678
1686
  }
1679
1687
  const transcriptText = includeTranscript ? (await fetchTranscriptForAsset(assetData, playbackId, {
1680
1688
  cleanTranscript,
1681
- signingContext: policy === "signed" ? signingContext : void 0
1689
+ shouldSign: policy === "signed"
1682
1690
  })).transcriptText : "";
1683
1691
  const userPrompt = buildUserPrompt2({
1684
1692
  tone,
@@ -1686,19 +1694,20 @@ async function getSummaryAndTags(assetId, options) {
1686
1694
  isCleanTranscript: cleanTranscript,
1687
1695
  promptOverrides
1688
1696
  });
1689
- const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed" ? signingContext : void 0);
1697
+ const imageUrl = await getStoryboardUrl(playbackId, 640, policy === "signed");
1690
1698
  let analysisResponse;
1691
1699
  try {
1692
1700
  if (imageSubmissionMode === "base64") {
1693
1701
  const downloadResult = await downloadImageAsBase64(imageUrl, imageDownloadOptions);
1694
1702
  analysisResponse = await analyzeStoryboard2(
1695
1703
  downloadResult.base64Data,
1696
- config,
1704
+ config.provider,
1705
+ config.modelId,
1697
1706
  userPrompt,
1698
1707
  SYSTEM_PROMPT3
1699
1708
  );
1700
1709
  } else {
1701
- analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config, userPrompt, SYSTEM_PROMPT3));
1710
+ analysisResponse = await withRetry(() => analyzeStoryboard2(imageUrl, config.provider, config.modelId, userPrompt, SYSTEM_PROMPT3));
1702
1711
  }
1703
1712
  } catch (error) {
1704
1713
  throw new Error(
@@ -1903,11 +1912,12 @@ function getReadyAudioStaticRendition(asset) {
1903
1912
  );
1904
1913
  }
1905
1914
  var hasReadyAudioStaticRendition = (asset) => Boolean(getReadyAudioStaticRendition(asset));
1906
- async function requestStaticRenditionCreation(credentials, assetId) {
1915
+ async function requestStaticRenditionCreation(assetId) {
1907
1916
  "use step";
1917
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1908
1918
  const mux = new Mux3({
1909
- tokenId: credentials.muxTokenId,
1910
- tokenSecret: credentials.muxTokenSecret
1919
+ tokenId: muxTokenId,
1920
+ tokenSecret: muxTokenSecret
1911
1921
  });
1912
1922
  try {
1913
1923
  await mux.video.assets.createStaticRendition(assetId, {
@@ -1926,13 +1936,13 @@ async function requestStaticRenditionCreation(credentials, assetId) {
1926
1936
  }
1927
1937
  async function waitForAudioStaticRendition({
1928
1938
  assetId,
1929
- credentials,
1930
1939
  initialAsset
1931
1940
  }) {
1932
1941
  "use step";
1942
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
1933
1943
  const mux = new Mux3({
1934
- tokenId: credentials.muxTokenId,
1935
- tokenSecret: credentials.muxTokenSecret
1944
+ tokenId: muxTokenId,
1945
+ tokenSecret: muxTokenSecret
1936
1946
  });
1937
1947
  let currentAsset = initialAsset;
1938
1948
  if (hasReadyAudioStaticRendition(currentAsset)) {
@@ -1940,9 +1950,9 @@ async function waitForAudioStaticRendition({
1940
1950
  }
1941
1951
  const status = currentAsset.static_renditions?.status ?? "not_requested";
1942
1952
  if (status === "not_requested" || status === void 0) {
1943
- await requestStaticRenditionCreation(credentials, assetId);
1953
+ await requestStaticRenditionCreation(assetId);
1944
1954
  } else if (status === "errored") {
1945
- await requestStaticRenditionCreation(credentials, assetId);
1955
+ await requestStaticRenditionCreation(assetId);
1946
1956
  } else {
1947
1957
  console.warn(`\u2139\uFE0F Static rendition already ${status}. Waiting for it to finish...`);
1948
1958
  }
@@ -1978,10 +1988,10 @@ async function createElevenLabsDubbingJob({
1978
1988
  audioBuffer,
1979
1989
  assetId,
1980
1990
  elevenLabsLangCode,
1981
- elevenLabsApiKey,
1982
1991
  numSpeakers
1983
1992
  }) {
1984
1993
  "use step";
1994
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
1985
1995
  const audioBlob = new Blob([audioBuffer], { type: "audio/mp4" });
1986
1996
  const formData = new FormData();
1987
1997
  formData.append("file", audioBlob);
@@ -2002,10 +2012,10 @@ async function createElevenLabsDubbingJob({
2002
2012
  return dubbingData.dubbing_id;
2003
2013
  }
2004
2014
  async function checkElevenLabsDubbingStatus({
2005
- dubbingId,
2006
- elevenLabsApiKey
2015
+ dubbingId
2007
2016
  }) {
2008
2017
  "use step";
2018
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2009
2019
  const statusResponse = await fetch(`https://api.elevenlabs.io/v1/dubbing/${dubbingId}`, {
2010
2020
  headers: {
2011
2021
  "xi-api-key": elevenLabsApiKey
@@ -2022,10 +2032,10 @@ async function checkElevenLabsDubbingStatus({
2022
2032
  }
2023
2033
  async function downloadDubbedAudioFromElevenLabs({
2024
2034
  dubbingId,
2025
- languageCode,
2026
- elevenLabsApiKey
2035
+ languageCode
2027
2036
  }) {
2028
2037
  "use step";
2038
+ const elevenLabsApiKey = getApiKeyFromEnv("elevenlabs");
2029
2039
  const audioUrl = `https://api.elevenlabs.io/v1/dubbing/${dubbingId}/audio/${languageCode}`;
2030
2040
  const audioResponse = await fetch(audioUrl, {
2031
2041
  headers: {
@@ -2043,14 +2053,14 @@ async function uploadDubbedAudioToS3({
2043
2053
  toLanguageCode,
2044
2054
  s3Endpoint,
2045
2055
  s3Region,
2046
- s3Bucket,
2047
- s3AccessKeyId,
2048
- s3SecretAccessKey
2056
+ s3Bucket
2049
2057
  }) {
2050
2058
  "use step";
2051
2059
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2052
2060
  const { Upload } = await import("@aws-sdk/lib-storage");
2053
2061
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2062
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2063
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2054
2064
  const s3Client = new S3Client({
2055
2065
  region: s3Region,
2056
2066
  endpoint: s3Endpoint,
@@ -2083,11 +2093,12 @@ async function uploadDubbedAudioToS3({
2083
2093
  console.warn(`\u{1F517} Generated presigned URL (expires in 1 hour)`);
2084
2094
  return presignedUrl;
2085
2095
  }
2086
- async function createAudioTrackOnMux(credentials, assetId, languageCode, presignedUrl) {
2096
+ async function createAudioTrackOnMux(assetId, languageCode, presignedUrl) {
2087
2097
  "use step";
2098
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2088
2099
  const mux = new Mux3({
2089
- tokenId: credentials.muxTokenId,
2090
- tokenSecret: credentials.muxTokenSecret
2100
+ tokenId: muxTokenId,
2101
+ tokenSecret: muxTokenSecret
2091
2102
  });
2092
2103
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(languageCode) || languageCode.toUpperCase();
2093
2104
  const trackName = `${languageName} (auto-dubbed)`;
@@ -2114,21 +2125,20 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2114
2125
  if (provider !== "elevenlabs") {
2115
2126
  throw new Error("Only ElevenLabs provider is currently supported for audio translation");
2116
2127
  }
2117
- const credentials = await validateCredentials(options);
2118
2128
  const elevenLabsKey = elevenLabsApiKey ?? env_default.ELEVENLABS_API_KEY;
2119
2129
  const s3Endpoint = options.s3Endpoint ?? env_default.S3_ENDPOINT;
2120
2130
  const s3Region = options.s3Region ?? env_default.S3_REGION ?? "auto";
2121
2131
  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;
2132
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2133
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2124
2134
  if (!elevenLabsKey) {
2125
2135
  throw new Error("ElevenLabs API key is required. Provide elevenLabsApiKey in options or set ELEVENLABS_API_KEY environment variable.");
2126
2136
  }
2127
2137
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2128
2138
  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
2139
  }
2130
- const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(credentials, assetId);
2131
- const signingContext = await resolveSigningContext(options);
2140
+ const { asset: initialAsset, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2141
+ const signingContext = getMuxSigningContextFromEnv();
2132
2142
  if (policy === "signed" && !signingContext) {
2133
2143
  throw new Error(
2134
2144
  "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 +2149,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2139
2149
  console.warn("\u274C No ready audio static rendition found. Requesting one now...");
2140
2150
  currentAsset = await waitForAudioStaticRendition({
2141
2151
  assetId,
2142
- credentials,
2143
2152
  initialAsset: currentAsset
2144
2153
  });
2145
2154
  }
@@ -2169,7 +2178,6 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2169
2178
  audioBuffer,
2170
2179
  assetId,
2171
2180
  elevenLabsLangCode,
2172
- elevenLabsApiKey: elevenLabsKey,
2173
2181
  numSpeakers
2174
2182
  });
2175
2183
  console.warn(`\u2705 Dubbing job created with ID: ${dubbingId}`);
@@ -2186,8 +2194,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2186
2194
  pollAttempts++;
2187
2195
  try {
2188
2196
  const statusResult = await checkElevenLabsDubbingStatus({
2189
- dubbingId,
2190
- elevenLabsApiKey: elevenLabsKey
2197
+ dubbingId
2191
2198
  });
2192
2199
  dubbingStatus = statusResult.status;
2193
2200
  targetLanguages = statusResult.targetLanguages;
@@ -2230,8 +2237,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2230
2237
  }
2231
2238
  dubbedAudioBuffer = await downloadDubbedAudioFromElevenLabs({
2232
2239
  dubbingId,
2233
- languageCode: downloadLangCode,
2234
- elevenLabsApiKey: elevenLabsKey
2240
+ languageCode: downloadLangCode
2235
2241
  });
2236
2242
  console.warn("\u2705 Dubbed audio downloaded successfully!");
2237
2243
  } catch (error) {
@@ -2246,9 +2252,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2246
2252
  toLanguageCode,
2247
2253
  s3Endpoint,
2248
2254
  s3Region,
2249
- s3Bucket,
2250
- s3AccessKeyId,
2251
- s3SecretAccessKey
2255
+ s3Bucket
2252
2256
  });
2253
2257
  } catch (error) {
2254
2258
  throw new Error(`Failed to upload audio to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2257,7 +2261,7 @@ async function translateAudio(assetId, toLanguageCode, options = {}) {
2257
2261
  let uploadedTrackId;
2258
2262
  const muxLangCode = toISO639_1(toLanguageCode);
2259
2263
  try {
2260
- uploadedTrackId = await createAudioTrackOnMux(credentials, assetId, muxLangCode, presignedUrl);
2264
+ uploadedTrackId = await createAudioTrackOnMux(assetId, muxLangCode, presignedUrl);
2261
2265
  const languageName = new Intl.DisplayNames(["en"], { type: "language" }).of(muxLangCode) || muxLangCode.toUpperCase();
2262
2266
  const trackName = `${languageName} (auto-dubbed)`;
2263
2267
  console.warn(`\u2705 Track added to Mux asset with ID: ${uploadedTrackId}`);
@@ -2299,15 +2303,10 @@ async function translateVttWithAI({
2299
2303
  toLanguageCode,
2300
2304
  provider,
2301
2305
  modelId,
2302
- credentials,
2303
2306
  abortSignal
2304
2307
  }) {
2305
2308
  "use step";
2306
- const languageModel = createLanguageModelFromConfig(
2307
- provider,
2308
- modelId,
2309
- credentials
2310
- );
2309
+ const languageModel = createLanguageModelFromConfig(provider, modelId);
2311
2310
  const response = await generateObject4({
2312
2311
  model: languageModel,
2313
2312
  schema: translationSchema,
@@ -2339,14 +2338,14 @@ async function uploadVttToS3({
2339
2338
  toLanguageCode,
2340
2339
  s3Endpoint,
2341
2340
  s3Region,
2342
- s3Bucket,
2343
- s3AccessKeyId,
2344
- s3SecretAccessKey
2341
+ s3Bucket
2345
2342
  }) {
2346
2343
  "use step";
2347
2344
  const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
2348
2345
  const { Upload } = await import("@aws-sdk/lib-storage");
2349
2346
  const { getSignedUrl } = await import("@aws-sdk/s3-request-presigner");
2347
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2348
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2350
2349
  const s3Client = new S3Client({
2351
2350
  region: s3Region,
2352
2351
  endpoint: s3Endpoint,
@@ -2377,11 +2376,12 @@ async function uploadVttToS3({
2377
2376
  });
2378
2377
  return presignedUrl;
2379
2378
  }
2380
- async function createTextTrackOnMux(credentials, assetId, languageCode, trackName, presignedUrl) {
2379
+ async function createTextTrackOnMux(assetId, languageCode, trackName, presignedUrl) {
2381
2380
  "use step";
2381
+ const { muxTokenId, muxTokenSecret } = getMuxCredentialsFromEnv();
2382
2382
  const mux = new Mux4({
2383
- tokenId: credentials.muxTokenId,
2384
- tokenSecret: credentials.muxTokenSecret
2383
+ tokenId: muxTokenId,
2384
+ tokenSecret: muxTokenSecret
2385
2385
  });
2386
2386
  const trackResponse = await mux.video.assets.createTrack(assetId, {
2387
2387
  type: "text",
@@ -2403,15 +2403,13 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2403
2403
  s3Endpoint: providedS3Endpoint,
2404
2404
  s3Region: providedS3Region,
2405
2405
  s3Bucket: providedS3Bucket,
2406
- s3AccessKeyId: providedS3AccessKeyId,
2407
- s3SecretAccessKey: providedS3SecretAccessKey,
2408
2406
  uploadToMux: uploadToMuxOption
2409
2407
  } = options;
2410
2408
  const s3Endpoint = providedS3Endpoint ?? env_default.S3_ENDPOINT;
2411
2409
  const s3Region = providedS3Region ?? env_default.S3_REGION ?? "auto";
2412
2410
  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;
2411
+ const s3AccessKeyId = env_default.S3_ACCESS_KEY_ID;
2412
+ const s3SecretAccessKey = env_default.S3_SECRET_ACCESS_KEY;
2415
2413
  const uploadToMux = uploadToMuxOption !== false;
2416
2414
  const config = await createWorkflowConfig(
2417
2415
  { ...options, model },
@@ -2420,8 +2418,8 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2420
2418
  if (uploadToMux && (!s3Endpoint || !s3Bucket || !s3AccessKeyId || !s3SecretAccessKey)) {
2421
2419
  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
2420
  }
2423
- const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(config.credentials, assetId);
2424
- const signingContext = await resolveSigningContext(options);
2421
+ const { asset: assetData, playbackId, policy } = await getPlaybackIdForAsset(assetId);
2422
+ const signingContext = getMuxSigningContextFromEnv();
2425
2423
  if (policy === "signed" && !signingContext) {
2426
2424
  throw new Error(
2427
2425
  "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 +2453,6 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2455
2453
  toLanguageCode,
2456
2454
  provider: config.provider,
2457
2455
  modelId: config.modelId,
2458
- credentials: config.credentials,
2459
2456
  abortSignal: options.abortSignal
2460
2457
  });
2461
2458
  translatedVtt = result.translatedVtt;
@@ -2486,9 +2483,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2486
2483
  toLanguageCode,
2487
2484
  s3Endpoint,
2488
2485
  s3Region,
2489
- s3Bucket,
2490
- s3AccessKeyId,
2491
- s3SecretAccessKey
2486
+ s3Bucket
2492
2487
  });
2493
2488
  } catch (error) {
2494
2489
  throw new Error(`Failed to upload VTT to S3: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -2497,7 +2492,7 @@ async function translateCaptions(assetId, fromLanguageCode, toLanguageCode, opti
2497
2492
  try {
2498
2493
  const languageName = getLanguageName(toLanguageCode);
2499
2494
  const trackName = `${languageName} (auto-translated)`;
2500
- uploadedTrackId = await createTextTrackOnMux(config.credentials, assetId, toLanguageCode, trackName, presignedUrl);
2495
+ uploadedTrackId = await createTextTrackOnMux(assetId, toLanguageCode, trackName, presignedUrl);
2501
2496
  } catch (error) {
2502
2497
  console.warn(`Failed to add track to Mux asset: ${error instanceof Error ? error.message : "Unknown error"}`);
2503
2498
  }