Package Exports
- @mux/ai
Readme
@mux/ai
AI-powered video analysis library for Mux, built in TypeScript.
Available Tools
| Function | Description | Providers | Default Models | Input | Output |
|---|---|---|---|---|---|
getSummaryAndTags |
Generate titles, descriptions, and tags from a Mux video asset | OpenAI, Anthropic | gpt-4o-mini, claude-3-5-haiku-20241022 |
Asset ID + options | Title, description, tags, storyboard URL |
getModerationScores |
Analyze video thumbnails for inappropriate content | OpenAI, Hive | omni-moderation-latest, Hive Visual API |
Asset ID + thresholds | Sexual/violence scores, flagged status |
hasBurnedInCaptions |
Detect burned-in captions (hardcoded subtitles) in video frames | OpenAI, Anthropic | gpt-4o-mini, claude-3-5-haiku-20241022 |
Asset ID + options | Boolean result, confidence, language |
generateChapters |
Generate AI-powered chapter markers from video captions | OpenAI, Anthropic | gpt-4o-mini, claude-3-5-haiku-20241022 |
Asset ID + language + options | Timestamped chapter list |
translateCaptions |
Translate video captions to different languages | Anthropic only | claude-sonnet-4-20250514 |
Asset ID + languages + S3 config | Translated VTT + Mux track ID |
translateAudio |
Create AI-dubbed audio tracks in different languages | ElevenLabs only | ElevenLabs Dubbing API | Asset ID + languages + S3 config | Dubbed audio + Mux track ID |
Features
- Cost-Effective by Default: Uses affordable models like
gpt-4o-miniandclaude-3-5-haikuto keep analysis costs low while maintaining high quality results - Multi-modal Analysis: Combines storyboard images with video transcripts
- Tone Control: Normal, sassy, or professional analysis styles (summarization only)
- Configurable Thresholds: Custom sensitivity levels for content moderation
- TypeScript: Fully typed for excellent developer experience
- Provider Choice: Switch between OpenAI and Anthropic for different perspectives
- Universal Language Support: Automatic language name detection using
Intl.DisplayNamesfor all ISO 639-1 codes
Installation
npm install @mux/aiQuick Start
Video Summarization
import { getSummaryAndTags } from '@mux/ai';
// Uses built-in optimized prompt
const result = await getSummaryAndTags('your-mux-asset-id', {
tone: 'professional'
});
console.log(result.title); // Short, descriptive title
console.log(result.description); // Detailed description
console.log(result.tags); // Array of relevant keywords
console.log(result.storyboardUrl); // URL to Mux storyboard
// Use base64 mode for improved reliability (works with both OpenAI and Anthropic)
const reliableResult = await getSummaryAndTags('your-mux-asset-id', {
provider: 'anthropic',
imageSubmissionMode: 'base64', // Uses Files API for Anthropic, base64 for OpenAI
imageDownloadOptions: {
timeout: 15000,
retries: 2,
retryDelay: 1000
},
tone: 'professional'
});Content Moderation
import { getModerationScores } from '@mux/ai';
// Analyze Mux video asset for inappropriate content (OpenAI default)
const result = await getModerationScores('your-mux-asset-id', {
thresholds: { sexual: 0.7, violence: 0.8 }
});
console.log(result.maxScores); // Highest scores across all thumbnails
console.log(result.exceedsThreshold); // true if content should be flagged
console.log(result.thumbnailScores); // Individual thumbnail results
// Or use Hive for moderation
const hiveResult = await getModerationScores('your-mux-asset-id', {
provider: 'hive',
thresholds: { sexual: 0.7, violence: 0.8 }
});
// Use base64 submission for improved reliability (downloads images locally)
const reliableResult = await getModerationScores('your-mux-asset-id', {
provider: 'openai',
imageSubmissionMode: 'base64',
imageDownloadOptions: {
timeout: 15000,
retries: 3,
retryDelay: 1000
}
});
// Hive also supports base64 mode (uses multipart upload)
const hiveReliableResult = await getModerationScores('your-mux-asset-id', {
provider: 'hive',
imageSubmissionMode: 'base64',
imageDownloadOptions: {
timeout: 15000,
retries: 2,
retryDelay: 1000
}
});Burned-in Caption Detection
import { hasBurnedInCaptions } from '@mux/ai';
// Detect burned-in captions (hardcoded subtitles) in video frames
const result = await hasBurnedInCaptions('your-mux-asset-id', {
provider: 'openai'
});
console.log(result.hasBurnedInCaptions); // true/false
console.log(result.confidence); // 0.0-1.0 confidence score
console.log(result.detectedLanguage); // Language if captions detected
console.log(result.storyboardUrl); // Video storyboard analyzed
// Compare providers
const anthropicResult = await hasBurnedInCaptions('your-mux-asset-id', {
provider: 'anthropic',
model: 'claude-3-5-haiku-20241022'
});
// Use base64 mode for improved reliability
const reliableResult = await hasBurnedInCaptions('your-mux-asset-id', {
provider: 'openai',
imageSubmissionMode: 'base64',
imageDownloadOptions: {
timeout: 15000,
retries: 3,
retryDelay: 1000
}
});Image Submission Modes
Choose between two methods for submitting images to AI providers:
URL Mode (Default):
- Fast initial response
- Lower bandwidth usage
- Relies on AI provider's image downloading
- May encounter timeouts with slow/unreliable image sources
Base64 Mode (Recommended for Production):
- Downloads images locally with robust retry logic
- Eliminates AI provider timeout issues
- Better control over slow TTFB and network issues
- Slightly higher bandwidth usage but more reliable results
- For OpenAI: submits images as base64 data URIs
- For Hive: uploads images via multipart/form-data (Hive doesn't support base64 data URIs)
- For Anthropic (summarization): uploads to Files API then references by file_id (no size limit)
// High reliability mode - recommended for production
const result = await getModerationScores(assetId, {
imageSubmissionMode: 'base64',
imageDownloadOptions: {
timeout: 15000, // 15s timeout per image
retries: 3, // Retry failed downloads 3x
retryDelay: 1000, // 1s base delay with exponential backoff
exponentialBackoff: true
}
});Caption Translation
import { translateCaptions } from '@mux/ai';
// Translate existing captions to Spanish and add as new track
const result = await translateCaptions(
'your-mux-asset-id',
'en', // from language
'es', // to language
{
provider: 'anthropic',
model: 'claude-sonnet-4-20250514'
}
);
console.log(result.uploadedTrackId); // New Mux track ID
console.log(result.presignedUrl); // S3 file URL
console.log(result.translatedVtt); // Translated VTT contentVideo Chapters
import { generateChapters } from '@mux/ai';
// Generate AI-powered chapters from video captions
const result = await generateChapters('your-mux-asset-id', 'en', {
provider: 'openai'
});
console.log(result.chapters); // Array of {startTime: number, title: string}
// Use with Mux Player
const player = document.querySelector('mux-player');
player.addChapters(result.chapters);
// Compare providers
const anthropicResult = await generateChapters('your-mux-asset-id', 'en', {
provider: 'anthropic',
model: 'claude-3-5-haiku-20241022'
});Audio Dubbing
import { translateAudio } from '@mux/ai';
// Create AI-dubbed audio track and add to Mux asset
// Uses the default audio track on your asset, language is auto-detected
const result = await translateAudio(
'your-mux-asset-id',
'es', // target language
{
provider: 'elevenlabs',
numSpeakers: 0 // Auto-detect speakers
}
);
console.log(result.dubbingId); // ElevenLabs dubbing job ID
console.log(result.uploadedTrackId); // New Mux audio track ID
console.log(result.presignedUrl); // S3 audio file URLCompare Summarization from Providers
import { getSummaryAndTags } from '@mux/ai';
// Compare different AI providers analyzing the same Mux video asset
const assetId = 'your-mux-asset-id';
// OpenAI analysis (default: gpt-4o-mini)
const openaiResult = await getSummaryAndTags(assetId, {
provider: 'openai',
tone: 'professional'
});
// Anthropic analysis (default: claude-3-5-haiku-20241022)
const anthropicResult = await getSummaryAndTags(assetId, {
provider: 'anthropic',
tone: 'professional'
});
// Compare results
console.log('OpenAI:', openaiResult.title);
console.log('Anthropic:', anthropicResult.title);Configuration
Set environment variables:
MUX_TOKEN_ID=your_mux_token_id
MUX_TOKEN_SECRET=your_mux_token_secret
OPENAI_API_KEY=your_openai_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key
ELEVENLABS_API_KEY=your_elevenlabs_api_key
HIVE_API_KEY=your_hive_api_key
# S3-Compatible Storage (required for translation & audio dubbing)
S3_ENDPOINT=https://your-s3-endpoint.com
S3_REGION=auto
S3_BUCKET=your-bucket-name
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-keyOr pass credentials directly:
const result = await getSummaryAndTags(assetId, {
muxTokenId: 'your-token-id',
muxTokenSecret: 'your-token-secret',
openaiApiKey: 'your-openai-key'
});API Reference
getSummaryAndTags(assetId, options?)
Analyzes a Mux video asset and returns AI-generated metadata.
Parameters:
assetId(string) - Mux video asset IDoptions(optional) - Configuration options
Options:
provider?: 'openai' | 'anthropic'- AI provider (default: 'openai')tone?: 'normal' | 'sassy' | 'professional'- Analysis tone (default: 'normal')model?: string- AI model to use (default: 'gpt-4o-mini' for OpenAI, 'claude-3-5-haiku-20241022' for Anthropic)includeTranscript?: boolean- Include video transcript in analysis (default: true)cleanTranscript?: boolean- Remove VTT timestamps and formatting from transcript (default: true)imageSubmissionMode?: 'url' | 'base64'- How to submit storyboard to AI providers (default: 'url')imageDownloadOptions?: object- Options for image download when using base64 modetimeout?: number- Request timeout in milliseconds (default: 10000)retries?: number- Maximum retry attempts (default: 3)retryDelay?: number- Base delay between retries in milliseconds (default: 1000)maxRetryDelay?: number- Maximum delay between retries in milliseconds (default: 10000)exponentialBackoff?: boolean- Whether to use exponential backoff (default: true)
muxTokenId?: string- Mux API token IDmuxTokenSecret?: string- Mux API token secretopenaiApiKey?: string- OpenAI API keyanthropicApiKey?: string- Anthropic API key
Returns:
{
assetId: string;
title: string; // Short title (max 100 chars)
description: string; // Detailed description
tags: string[]; // Relevant keywords
storyboardUrl: string; // Video storyboard URL
}getModerationScores(assetId, options?)
Analyzes video thumbnails for inappropriate content using OpenAI's moderation API or Hive's Visual Moderation API.
Parameters:
assetId(string) - Mux video asset IDoptions(optional) - Configuration options
Options:
provider?: 'openai' | 'hive'- Moderation provider (default: 'openai')model?: string- OpenAI model to use (default: 'omni-moderation-latest')thresholds?: { sexual?: number; violence?: number }- Custom thresholds (default: {sexual: 0.7, violence: 0.8})thumbnailInterval?: number- Seconds between thumbnails for long videos (default: 10)thumbnailWidth?: number- Thumbnail width in pixels (default: 640)maxConcurrent?: number- Maximum concurrent API requests (default: 5)imageSubmissionMode?: 'url' | 'base64'- How to submit images to AI providers (default: 'url')imageDownloadOptions?: object- Options for image download when using base64 modetimeout?: number- Request timeout in milliseconds (default: 10000)retries?: number- Maximum retry attempts (default: 3)retryDelay?: number- Base delay between retries in milliseconds (default: 1000)maxRetryDelay?: number- Maximum delay between retries in milliseconds (default: 10000)exponentialBackoff?: boolean- Whether to use exponential backoff (default: true)
muxTokenId/muxTokenSecret/openaiApiKey?: string- API credentialshiveApiKey?: string- Hive API key (required for Hive provider)
Returns:
{
assetId: string;
thumbnailScores: Array<{ // Individual thumbnail results
url: string;
sexual: number; // 0-1 score
violence: number; // 0-1 score
error: boolean;
}>;
maxScores: { // Highest scores across all thumbnails
sexual: number;
violence: number;
};
exceedsThreshold: boolean; // true if content should be flagged
thresholds: { // Threshold values used
sexual: number;
violence: number;
};
}hasBurnedInCaptions(assetId, options?)
Analyzes video frames to detect burned-in captions (hardcoded subtitles) that are permanently embedded in the video image.
Parameters:
assetId(string) - Mux video asset IDoptions(optional) - Configuration options
Options:
provider?: 'openai' | 'anthropic'- AI provider (default: 'openai')model?: string- AI model to use (default: 'gpt-4o-mini' for OpenAI, 'claude-3-5-haiku-20241022' for Anthropic)imageSubmissionMode?: 'url' | 'base64'- How to submit storyboard to AI providers (default: 'url')imageDownloadOptions?: object- Options for image download when using base64 modetimeout?: number- Request timeout in milliseconds (default: 10000)retries?: number- Maximum retry attempts (default: 3)retryDelay?: number- Base delay between retries in milliseconds (default: 1000)maxRetryDelay?: number- Maximum delay between retries in milliseconds (default: 10000)exponentialBackoff?: boolean- Whether to use exponential backoff (default: true)
muxTokenId?: string- Mux API token IDmuxTokenSecret?: string- Mux API token secretopenaiApiKey?: string- OpenAI API keyanthropicApiKey?: string- Anthropic API key
Returns:
{
assetId: string;
hasBurnedInCaptions: boolean; // Whether burned-in captions were detected
confidence: number; // Confidence score (0.0-1.0)
detectedLanguage: string | null; // Language of detected captions, or null
storyboardUrl: string; // URL to analyzed storyboard
}Detection Logic:
- Analyzes video storyboard frames to identify text overlays
- Distinguishes between actual captions and marketing/end-card text
- Text appearing only in final 1-2 frames is classified as marketing copy
- Caption text must appear across multiple frames throughout the timeline
- Both providers use optimized prompts to minimize false positives
translateCaptions(assetId, fromLanguageCode, toLanguageCode, options?)
Translates existing captions from one language to another and optionally adds them as a new track to the Mux asset.
Parameters:
assetId(string) - Mux video asset IDfromLanguageCode(string) - Source language code (e.g., 'en', 'es', 'fr')toLanguageCode(string) - Target language code (e.g., 'es', 'fr', 'de')options(optional) - Configuration options
Options:
provider?: 'anthropic'- AI provider (default: 'anthropic')model?: string- Model to use (default: 'claude-sonnet-4-20250514')uploadToMux?: boolean- Whether to upload translated track to Mux (default: true)s3Endpoint?: string- S3-compatible storage endpoints3Region?: string- S3 region (default: 'auto')s3Bucket?: string- S3 bucket names3AccessKeyId?: string- S3 access key IDs3SecretAccessKey?: string- S3 secret access keymuxTokenId/muxTokenSecret/anthropicApiKey?: string- API credentials
Returns:
{
assetId: string;
sourceLanguageCode: string;
targetLanguageCode: string;
originalVtt: string; // Original VTT content
translatedVtt: string; // Translated VTT content
uploadedTrackId?: string; // Mux track ID (if uploaded)
presignedUrl?: string; // S3 presigned URL (expires in 1 hour)
}Supported Languages:
All ISO 639-1 language codes are automatically supported using Intl.DisplayNames. Examples: Spanish (es), French (fr), German (de), Italian (it), Portuguese (pt), Polish (pl), Japanese (ja), Korean (ko), Chinese (zh), Russian (ru), Arabic (ar), Hindi (hi), Thai (th), Swahili (sw), and many more.
generateChapters(assetId, languageCode, options?)
Generates AI-powered chapter markers by analyzing video captions. Creates logical chapter breaks based on topic changes and content transitions.
Parameters:
assetId(string) - Mux video asset IDlanguageCode(string) - Language code for captions (e.g., 'en', 'es', 'fr')options(optional) - Configuration options
Options:
provider?: 'openai' | 'anthropic'- AI provider (default: 'openai')model?: string- AI model to use (default: 'gpt-4o-mini' for OpenAI, 'claude-3-5-haiku-20241022' for Anthropic)muxTokenId?: string- Mux API token IDmuxTokenSecret?: string- Mux API token secretopenaiApiKey?: string- OpenAI API keyanthropicApiKey?: string- Anthropic API key
Returns:
{
assetId: string;
languageCode: string;
chapters: Array<{
startTime: number; // Chapter start time in seconds
title: string; // Descriptive chapter title
}>;
}Requirements:
- Asset must have caption track in the specified language
- Caption track must be in 'ready' status
- Uses existing auto-generated or uploaded captions
Example Output:
// Perfect format for Mux Player
player.addChapters([
{startTime: 0, title: 'Introduction and Setup'},
{startTime: 45, title: 'Main Content Discussion'},
{startTime: 120, title: 'Conclusion'}
]);translateAudio(assetId, toLanguageCode, options?)
Creates AI-dubbed audio tracks from existing video content using ElevenLabs voice cloning and translation. Uses the default audio track on your asset, language is auto-detected.
Parameters:
assetId(string) - Mux video asset ID (must have audio.m4a static rendition)toLanguageCode(string) - Target language code (e.g., 'es', 'fr', 'de')options(optional) - Configuration options
Options:
provider?: 'elevenlabs'- AI provider (default: 'elevenlabs')numSpeakers?: number- Number of speakers (default: 0 for auto-detect)uploadToMux?: boolean- Whether to upload dubbed track to Mux (default: true)s3Endpoint?: string- S3-compatible storage endpoints3Region?: string- S3 region (default: 'auto')s3Bucket?: string- S3 bucket names3AccessKeyId?: string- S3 access key IDs3SecretAccessKey?: string- S3 secret access keyelevenLabsApiKey?: string- ElevenLabs API keymuxTokenId/muxTokenSecret?: string- API credentials
Returns:
{
assetId: string;
targetLanguageCode: string;
dubbingId: string; // ElevenLabs dubbing job ID
uploadedTrackId?: string; // Mux audio track ID (if uploaded)
presignedUrl?: string; // S3 presigned URL (expires in 1 hour)
}Requirements:
- Asset must have an
audio.m4astatic rendition - ElevenLabs API key with Creator plan or higher
- S3-compatible storage for Mux ingestion
Supported Languages:
ElevenLabs supports 32+ languages with automatic language name detection via Intl.DisplayNames. Supported languages include English, Spanish, French, German, Italian, Portuguese, Polish, Japanese, Korean, Chinese, Russian, Arabic, Hindi, Thai, and many more. Track names are automatically generated (e.g., "Polish (auto-dubbed)").
Custom Prompts
Override the default summarization prompt:
const result = await getSummaryAndTags(
assetId,
'Custom analysis prompt here',
{ tone: 'professional' }
);Examples
See the examples/ directory for complete working examples:
Summarization Examples
- Basic Usage: Default prompt with different tones
- Custom Prompts: Override default behavior
- Tone Variations: Compare analysis styles
cd examples/summarization
npm install
npm run basic <your-asset-id>
npm run tones <your-asset-id>
npm run customModeration Examples
- Basic Moderation: Analyze content with default thresholds
- Custom Thresholds: Compare strict/default/permissive settings
- Hive Provider: Use Hive's Visual Moderation API
- Provider Comparison: Compare OpenAI vs Hive results side-by-side
cd examples/moderation
npm install
npm run basic <your-asset-id>
npm run thresholds <your-asset-id>
npm run hive <your-asset-id>
npm run compare <your-asset-id>Burned-in Caption Examples
- Basic Detection: Detect burned-in captions with different AI providers
- Provider Comparison: Compare OpenAI vs Anthropic detection accuracy
cd examples/burned-in-captions
npm install
npm run burned-in:basic <your-asset-id> [provider]
npm run compare <your-asset-id>Chapter Generation Examples
- Basic Chapters: Generate chapters with different AI providers
- Provider Comparison: Compare OpenAI vs Anthropic chapter generation
cd examples/chapters
npm install
npm run chapters:basic <your-asset-id> [language-code] [provider]
npm run compare <your-asset-id> [language-code]Translation Examples
- Basic Translation: Translate captions and upload to Mux
- Translation Only: Translate without uploading to Mux
cd examples/translation
npm install
npm run basic <your-asset-id> en es
npm run translation-only <your-asset-id> en frTranslation Workflow:
- Fetches existing captions from Mux asset
- Translates VTT content using Anthropic Claude
- Uploads translated VTT to S3-compatible storage
- Generates presigned URL (1-hour expiry)
- Adds new subtitle track to Mux asset
- Track name: "{Language} (auto-translated)"
Audio Dubbing Examples
- Basic Dubbing: Create AI-dubbed audio and upload to Mux
- Dubbing Only: Create dubbed audio without uploading to Mux
cd examples/audio-translation
npm install
npm run basic <your-asset-id> es
npm run dubbing-only <your-asset-id> frAudio Dubbing Workflow:
- Checks asset has audio.m4a static rendition
- Downloads default audio track from Mux
- Creates ElevenLabs dubbing job with automatic language detection
- Polls for completion (up to 30 minutes)
- Downloads dubbed audio file
- Uploads to S3-compatible storage
- Generates presigned URL (1-hour expiry)
- Adds new audio track to Mux asset
- Track name: "{Language} (auto-dubbed)"
S3-Compatible Storage
The translation feature requires S3-compatible storage to temporarily host VTT files for Mux ingestion. Supported providers include:
- AWS S3 - Amazon's object storage
- DigitalOcean Spaces - S3-compatible with CDN
- Cloudflare R2 - Zero egress fees
- MinIO - Self-hosted S3 alternative
- Backblaze B2 - Cost-effective storage
- Wasabi - Hot cloud storage
Why S3 Storage? Mux requires a publicly accessible URL to ingest subtitle tracks. The translation workflow:
- Uploads translated VTT to your S3 storage
- Generates a presigned URL for secure access
- Mux fetches the file using the presigned URL
- File remains in your storage for future use
Planned Features
- Additional Translation Providers: OpenAI GPT-4 support
- Batch Translation: Translate multiple assets at once
- Custom Translation Prompts: Override default translation behavior
License
MIT © Mux, Inc.