@mux/ai 0.30.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://badge.fury.io/js/@mux%2Fai.svg)](https://www.npmjs.com/package/@mux/ai)
4
4
  [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
5
 
6
- Easy to use, purpose-driven, cost effective, configurable **_workflow functions_** in a TypeScript SDK for building AI-powered video and audio workflows on the server, powered by [Mux](https://www.mux.com), with support for popular AI/LLM providers (OpenAI, Anthropic, Google).
6
+ Easy to use, purpose-driven, cost effective, configurable **_workflow functions_** in a TypeScript SDK for building AI-powered video and audio workflows on the server, powered by [Mux](https://www.mux.com), with support for popular AI/LLM providers (OpenAI, Anthropic, Google, Baseten, and any OpenAI-compatible endpoint).
7
7
 
8
8
  - **Examples:** [`getSummaryAndTags`](#video-summarization), [`getModerationScores`](#content-moderation), [`hasBurnedInCaptions`](#burned-in-caption-detection), [`generateChapters`](#chapter-generation), [`generateEmbeddings`](#search-with-embeddings), [`generateEngagementInsights`](#engagement-insights), [`translateCaptions`](#caption-translation), [`editCaptions`](#caption-editing), [`translateAudio`](#audio-dubbing)
9
9
  - Workflows automatically ship with `"use workflow"` [compatability with Workflow DevKit](#compatability-with-workflow-devkit)
@@ -25,7 +25,7 @@ Add your credentials to a `.env` file (we support [dotenv](https://www.npmjs.com
25
25
  ```bash
26
26
  MUX_TOKEN_ID=your_mux_token_id
27
27
  MUX_TOKEN_SECRET=your_mux_token_secret
28
- OPENAI_API_KEY=your_openai_api_key # or ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY
28
+ OPENAI_API_KEY=your_openai_api_key # or ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, BASETEN_API_KEY
29
29
  ```
30
30
 
31
31
  You only need credentials for the AI provider you're using. See the [Credentials guide](./docs/CREDENTIALS.md) for full setup details including signed playback, S3 storage, and all supported providers.
@@ -54,9 +54,9 @@ console.log(result.tags); // ["typescript", "tutorial", "programming"]
54
54
 
55
55
  - **Pre-built workflows for media AI tasks.** Common multi-step operations (transcript access, frame analysis, LLM calls, and structured parsing) are available as high-level functions.
56
56
  - **Support for video and audio assets.** The same workflows work with video and [audio-only assets](./docs/AUDIO-ONLY.md), including summarization, moderation, chaptering, and more.
57
- - **Provider-flexible API.** Choose OpenAI, Anthropic, or Google through workflow options while keeping the same workflow interface.
57
+ - **Provider-flexible API.** Choose OpenAI, Anthropic, Google, Baseten, or any OpenAI-compatible endpoint through workflow options while keeping the same workflow interface.
58
58
  - **Published evaluation coverage.** Workflows include [evals](./docs/EVALS.md) for quality, latency, and cost, with results [published publicly](https://evaluating-mux-ai.vercel.app/) on pushes to `main`.
59
- - **Sensible default models.** Defaults (`gpt-5.6-luna` at medium reasoning, `claude-sonnet-4-5`, `gemini-3-flash-preview`) are selected to balance output quality and runtime cost.
59
+ - **Sensible default models.** Defaults (`gpt-5.6-luna` at medium reasoning, `claude-sonnet-4-5`, `gemini-3-flash-preview`) are selected to balance output quality and runtime cost. Baseten and OpenAI-compatible endpoints serve user-deployed models, so they use an explicit `model` or the `BASETEN_MODEL`/`OPENAI_COMPATIBLE_MODEL` environment variables.
60
60
  - **Typed end-to-end.** Workflow inputs, options, and outputs are fully typed in TypeScript.
61
61
  - **Operational defaults included.** Retry handling, error handling, signed playback support, and [Workflow DevKit](https://useworkflow.dev) compatibility are built in.
62
62
  - **Prompt customization support.** Use `promptOverrides` to adjust sections of workflow prompts for your domain or product requirements.
@@ -68,14 +68,14 @@ Workflows are high-level functions that handle complete media AI tasks end-to-en
68
68
 
69
69
  | Workflow | What it does | Providers | Audio-only |
70
70
  | --- | --- | --- | :---: |
71
- | [`getSummaryAndTags`](./docs/WORKFLOWS.md#video-summarization) | Generate titles, descriptions, and tags | OpenAI, Anthropic, Google | Yes |
71
+ | [`getSummaryAndTags`](./docs/WORKFLOWS.md#video-summarization) | Generate titles, descriptions, and tags | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | Yes |
72
72
  | [`getModerationScores`](./docs/WORKFLOWS.md#content-moderation) | Detect inappropriate content | OpenAI, Hive, Google Vision | Yes |
73
- | [`hasBurnedInCaptions`](./docs/WORKFLOWS.md#burned-in-caption-detection) | Detect hardcoded subtitles in video frames | OpenAI, Anthropic, Google | — |
74
- | [`askQuestions`](./docs/WORKFLOWS.md#ask-questions) | Answer yes/no questions about asset content | OpenAI, Anthropic, Google | Yes |
75
- | [`generateChapters`](./docs/WORKFLOWS.md#chapter-generation) | Create chapter markers from transcripts | OpenAI, Anthropic, Google | Yes |
76
- | [`generateEmbeddings`](./docs/WORKFLOWS.md#embeddings) | Generate vector embeddings for semantic search | OpenAI, Google | Yes |
77
- | [`translateCaptions`](./docs/WORKFLOWS.md#caption-translation) | Translate captions into other languages | OpenAI, Anthropic, Google | Yes |
78
- | [`editCaptions`](./docs/WORKFLOWS.md#caption-editing) | Edit captions: censor profanity and/or apply static replacements | OpenAI, Anthropic, Google | Yes |
73
+ | [`hasBurnedInCaptions`](./docs/WORKFLOWS.md#burned-in-caption-detection) | Detect hardcoded subtitles in video frames | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | — |
74
+ | [`askQuestions`](./docs/WORKFLOWS.md#ask-questions) | Answer yes/no questions about asset content | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | Yes |
75
+ | [`generateChapters`](./docs/WORKFLOWS.md#chapter-generation) | Create chapter markers from transcripts | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | Yes |
76
+ | [`generateEmbeddings`](./docs/WORKFLOWS.md#embeddings) | Generate vector embeddings for semantic search | OpenAI, Google, Baseten, OpenAI-compatible | Yes |
77
+ | [`translateCaptions`](./docs/WORKFLOWS.md#caption-translation) | Translate captions into other languages | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | Yes |
78
+ | [`editCaptions`](./docs/WORKFLOWS.md#caption-editing) | Edit captions: censor profanity and/or apply static replacements | OpenAI, Anthropic, Google, Baseten, OpenAI-compatible | Yes |
79
79
  | [`translateAudio`](./docs/WORKFLOWS.md#audio-dubbing) | Create AI-dubbed audio tracks | ElevenLabs | Yes |
80
80
 
81
81
  See the [Workflows guide](./docs/WORKFLOWS.md) for detailed documentation, options, and examples for each workflow. See the [API Reference](./docs/API.md) for complete parameter and return type details.
@@ -145,6 +145,31 @@ for (const chunk of result.chunks) {
145
145
  }
146
146
  ```
147
147
 
148
+ **Baseten provider:**
149
+
150
+ ```bash
151
+ BASETEN_API_KEY=your_baseten_api_key
152
+ BASETEN_MODEL=your-language-model-id
153
+ BASETEN_URL=https://model-id.api.baseten.co/environments/production/sync/v1
154
+ BASETEN_EMBEDDING_MODEL=your-embedding-model-id
155
+ BASETEN_EMBEDDING_URL=https://model-id.api.baseten.co/environments/production/sync
156
+ ```
157
+
158
+ Omit `BASETEN_URL` to use Baseten's shared [Model APIs](https://docs.baseten.co/development/model-apis/overview); for a dedicated deployment, set it to the deployment's `/sync/v1` URL. Embeddings always run against a dedicated deployment, so `BASETEN_EMBEDDING_URL` (its `/sync` or `/sync/v1` URL) is required.
159
+
160
+ **OpenAI-compatible provider:**
161
+
162
+ ```bash
163
+ OPENAI_COMPATIBLE_BASE_URL=https://my-endpoint.example.com/v1
164
+ OPENAI_COMPATIBLE_API_KEY=optional-api-key
165
+ OPENAI_COMPATIBLE_MODEL=your-language-model-id
166
+ OPENAI_COMPATIBLE_EMBEDDING_MODEL=your-embedding-model-id
167
+ ```
168
+
169
+ Use `provider: "openai-compatible"` with any endpoint that speaks the OpenAI API protocol — vLLM, Ollama, Together AI, Fireworks, OpenRouter, or a self-hosted gateway. `OPENAI_COMPATIBLE_API_KEY` is optional for endpoints that don't require authentication, and `OPENAI_COMPATIBLE_EMBEDDING_BASE_URL` can point embeddings at a separate endpoint (defaults to the shared base URL). Workflows request schema-constrained output (`response_format: json_schema`), so the endpoint must support structured outputs.
170
+
171
+ For both providers, workflows that analyze storyboards or frames (such as `getSummaryAndTags`, `hasBurnedInCaptions`, and `askQuestions`) require the deployed model to be vision-capable. See [Vision-Capable Models](./docs/VISION-MODELS.md) for known-good models and how to verify one.
172
+
148
173
  ## Prompt Customization
149
174
 
150
175
  Every workflow prompt is built from a structured template of named sections. The `promptOverrides` option lets you swap out individual sections with your own instructions while keeping the battle-tested defaults for everything else — no need to rewrite entire prompts.
@@ -164,7 +189,7 @@ This works with `getSummaryAndTags`, `generateChapters`, and `hasBurnedInCaption
164
189
 
165
190
  ## Evaluations
166
191
 
167
- Choosing between OpenAI, Anthropic, and Google for a given workflow isn't guesswork. Every workflow in `@mux/ai` ships with eval coverage that benchmarks providers and models against three dimensions:
192
+ Choosing between OpenAI, Anthropic, and Google for a given workflow isn't guesswork. Every workflow in `@mux/ai` ships with eval coverage that benchmarks those providers and models against three dimensions. Baseten and generic OpenAI-compatible endpoints serve user-deployed models, so they are supported at runtime but intentionally skipped by eval runs.
168
193
 
169
194
  - **Efficacy** — Does it produce accurate, high-quality results?
170
195
  - **Efficiency** — How fast is it and how many tokens does it consume?
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { createAnthropic } from '@ai-sdk/anthropic';
3
3
  import { createGoogleGenerativeAI } from '@ai-sdk/google';
4
4
  import { createOpenAI } from '@ai-sdk/openai';
5
- import { f as ScopedMuxAIOptions, I as ImageSubmissionMode, i as TokenUsage, M as MuxAIOptions, b as ChunkingStrategy, k as VideoEmbeddingsResult, H as Hotspot, v as Shot, j as ToneType, g as StorageAdapter } from './shots-Bh0GrvLx.js';
5
+ import { f as ScopedMuxAIOptions, I as ImageSubmissionMode, i as TokenUsage, M as MuxAIOptions, b as ChunkingStrategy, k as VideoEmbeddingsResult, H as Hotspot, v as Shot, j as ToneType, g as StorageAdapter } from './shots-BMbViFbZ.js';
6
6
 
7
7
  /**
8
8
  * Language Code Conversion Utilities
@@ -232,21 +232,25 @@ interface SafetyReport {
232
232
  scrubbedFields: ScrubbedFieldReport[];
233
233
  }
234
234
 
235
- type SupportedProvider = "openai" | "anthropic" | "google";
236
- type SupportedEmbeddingProvider = "openai" | "google";
235
+ type SupportedProvider = "openai" | "anthropic" | "google" | "baseten" | "openai-compatible";
236
+ type SupportedEmbeddingProvider = "openai" | "google" | "baseten" | "openai-compatible";
237
237
  type OpenAIModelId = Parameters<ReturnType<typeof createOpenAI>["chat"]>[0];
238
238
  type AnthropicModelId = Parameters<ReturnType<typeof createAnthropic>["chat"]>[0];
239
239
  type GoogleModelId = Parameters<ReturnType<typeof createGoogleGenerativeAI>["chat"]>[0];
240
240
  type OpenAIEmbeddingModelId = Parameters<ReturnType<typeof createOpenAI>["embedding"]>[0];
241
241
  type GoogleEmbeddingModelId = Parameters<ReturnType<typeof createGoogleGenerativeAI>["textEmbeddingModel"]>[0];
242
242
  interface ModelIdByProvider {
243
- openai: OpenAIModelId;
244
- anthropic: AnthropicModelId;
245
- google: GoogleModelId;
243
+ "openai": OpenAIModelId;
244
+ "anthropic": AnthropicModelId;
245
+ "google": GoogleModelId;
246
+ "baseten": string;
247
+ "openai-compatible": string;
246
248
  }
247
249
  interface EmbeddingModelIdByProvider {
248
- openai: OpenAIEmbeddingModelId;
249
- google: GoogleEmbeddingModelId;
250
+ "openai": OpenAIEmbeddingModelId;
251
+ "google": GoogleEmbeddingModelId;
252
+ "baseten": string;
253
+ "openai-compatible": string;
250
254
  }
251
255
 
252
256
  /**
@@ -395,16 +399,16 @@ declare const questionAnswerSchema: z.ZodObject<{
395
399
  reasoning: z.ZodString;
396
400
  skipped: z.ZodBoolean;
397
401
  }, "strip", z.ZodTypeAny, {
402
+ reasoning: string;
398
403
  question: string;
399
404
  answer: string | null;
400
405
  confidence: number;
401
- reasoning: string;
402
406
  skipped: boolean;
403
407
  }, {
408
+ reasoning: string;
404
409
  question: string;
405
410
  answer: string | null;
406
411
  confidence: number;
407
- reasoning: string;
408
412
  skipped: boolean;
409
413
  }>;
410
414
  type QuestionAnswerType = z.infer<typeof questionAnswerSchema>;
@@ -422,32 +426,32 @@ declare function createAskQuestionsSchema(answerSchema: z.ZodType<string>): z.Zo
422
426
  } & {
423
427
  answer: z.ZodType<string, z.ZodTypeDef, string>;
424
428
  }, "strip", z.ZodTypeAny, {
429
+ reasoning: string;
425
430
  question: string;
426
431
  answer: string;
427
432
  confidence: number;
428
- reasoning: string;
429
433
  skipped: boolean;
430
434
  }, {
435
+ reasoning: string;
431
436
  question: string;
432
437
  answer: string;
433
438
  confidence: number;
434
- reasoning: string;
435
439
  skipped: boolean;
436
440
  }>, "many">;
437
441
  }, "strip", z.ZodTypeAny, {
438
442
  answers: {
443
+ reasoning: string;
439
444
  question: string;
440
445
  answer: string;
441
446
  confidence: number;
442
- reasoning: string;
443
447
  skipped: boolean;
444
448
  }[];
445
449
  }, {
446
450
  answers: {
451
+ reasoning: string;
447
452
  question: string;
448
453
  answer: string;
449
454
  confidence: number;
450
- reasoning: string;
451
455
  skipped: boolean;
452
456
  }[];
453
457
  }>;
@@ -1255,6 +1259,10 @@ interface AudioTranslationResult {
1255
1259
  dubbingId: string;
1256
1260
  uploadedTrackId?: string;
1257
1261
  presignedUrl?: string;
1262
+ /** Mux text track ID for the dubbed captions, present when `uploadCaptionsToMux` is true and the upload succeeded. */
1263
+ captionsTrackId?: string;
1264
+ /** Presigned URL for the dub's translated transcript (WebVTT) staged to S3. */
1265
+ captionsPresignedUrl?: string;
1258
1266
  /** Workflow usage metadata (asset duration, thumbnails, etc.). */
1259
1267
  usage?: TokenUsage;
1260
1268
  }
@@ -1290,6 +1298,13 @@ interface AudioTranslationOptions extends MuxAIOptions {
1290
1298
  * required for track creation.
1291
1299
  */
1292
1300
  uploadToMux?: boolean;
1301
+ /**
1302
+ * When true the dub's translated transcript (the same translation that was
1303
+ * voiced) is attached as a subtitles text track on the Mux asset. Implies
1304
+ * `uploadToS3: true`. Defaults to false. The SDK does not check for existing
1305
+ * text tracks — callers decide conflict semantics before enabling this.
1306
+ */
1307
+ uploadCaptionsToMux?: boolean;
1293
1308
  /** Optional storage adapter override for upload + presign operations. */
1294
1309
  storageAdapter?: StorageAdapter;
1295
1310
  /** Expiry duration in seconds for S3 presigned GET URLs. Defaults to 86400 (24 hours). */
@@ -1,4 +1,4 @@
1
- import { l as WorkflowCredentialsInput, n as WorkflowScope, A as AssetTextTrack, d as MuxAsset, T as TextChunk, b as ChunkingStrategy, q as CompletedShotsResult, r as ErroredShotsResult, H as Hotspot, s as HotspotOptions, t as HotspotResponse, u as PendingShotsResult, v as Shot, w as ShotRequestOptions, x as ShotsResult, y as WaitForShotsOptions, z as getHotspotsForAsset, B as getHotspotsForPlaybackId, D as getHotspotsForVideo, F as getShotsForAsset, G as requestShotsForAsset, J as waitForShotsForAsset } from './shots-Bh0GrvLx.js';
1
+ import { l as WorkflowCredentialsInput, n as WorkflowScope, A as AssetTextTrack, d as MuxAsset, T as TextChunk, b as ChunkingStrategy, q as CompletedShotsResult, r as ErroredShotsResult, H as Hotspot, s as HotspotOptions, t as HotspotResponse, u as PendingShotsResult, v as Shot, w as ShotRequestOptions, x as ShotsResult, y as WaitForShotsOptions, z as getHotspotsForAsset, B as getHotspotsForPlaybackId, D as getHotspotsForVideo, F as getShotsForAsset, G as requestShotsForAsset, J as waitForShotsForAsset } from './shots-BMbViFbZ.js';
2
2
 
3
3
  interface HeatmapOptions {
4
4
  /** Time window for results, e.g., '7:days' (default: '7:days') */
package/dist/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
- export { I as ISO639_1, a as ISO639_3, L as LanguageCodePair, S as SupportedISO639_1, b as SupportedISO639_3, g as getLanguageCodePair, c as getLanguageName, i as isUndeterminedLanguageCode, d as isValidISO639_1, e as isValidISO639_3, t as toISO639_1, f as toISO639_3, h as workflows } from './index-D3cB2ltG.js';
2
- import { W as WorkflowCredentials, S as StoragePutObjectInput, a as StoragePresignGetObjectInput } from './shots-Bh0GrvLx.js';
3
- export { A as AssetTextTrack, C as ChunkEmbedding, b as ChunkingStrategy, E as Encrypted, c as EncryptedPayload, I as ImageSubmissionMode, M as MuxAIOptions, d as MuxAsset, P as PlaybackAsset, e as PlaybackPolicy, f as ScopedMuxAIOptions, g as StorageAdapter, T as TextChunk, h as TokenChunkingConfig, i as TokenUsage, j as ToneType, U as UsageMetadata, V as VTTChunkingConfig, k as VideoEmbeddingsResult, l as WorkflowCredentialsInput, m as WorkflowMuxClient, n as WorkflowScope, o as decryptFromWorkflow, p as encryptForWorkflow } from './shots-Bh0GrvLx.js';
1
+ export { I as ISO639_1, a as ISO639_3, L as LanguageCodePair, S as SupportedISO639_1, b as SupportedISO639_3, g as getLanguageCodePair, c as getLanguageName, i as isUndeterminedLanguageCode, d as isValidISO639_1, e as isValidISO639_3, t as toISO639_1, f as toISO639_3, h as workflows } from './index-D_nj_Nr4.js';
2
+ import { W as WorkflowCredentials, S as StoragePutObjectInput, a as StoragePresignGetObjectInput } from './shots-BMbViFbZ.js';
3
+ export { A as AssetTextTrack, C as ChunkEmbedding, b as ChunkingStrategy, E as Encrypted, c as EncryptedPayload, I as ImageSubmissionMode, M as MuxAIOptions, d as MuxAsset, P as PlaybackAsset, e as PlaybackPolicy, f as ScopedMuxAIOptions, g as StorageAdapter, T as TextChunk, h as TokenChunkingConfig, i as TokenUsage, j as ToneType, U as UsageMetadata, V as VTTChunkingConfig, k as VideoEmbeddingsResult, l as WorkflowCredentialsInput, m as WorkflowMuxClient, n as WorkflowScope, o as decryptFromWorkflow, p as encryptForWorkflow } from './shots-BMbViFbZ.js';
4
4
  import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
5
- export { i as primitives } from './index-CJtQiGj7.js';
5
+ export { i as primitives } from './index-SjpXUdXl.js';
6
6
  import 'zod';
7
7
  import '@ai-sdk/anthropic';
8
8
  import '@ai-sdk/google';
9
9
  import '@ai-sdk/openai';
10
10
  import '@mux/mux-node';
11
11
 
12
- var version = "0.30.0";
12
+ var version = "0.32.0";
13
13
 
14
14
  type MuxAiErrorType = "validation_error" | "processing_error" | "timeout_error" | "content_policy_error";
15
15
  /**