Official TypeScript library providing comprehensive client access to Mux's video infrastructure API including asset management, live streaming, analytics, and webhook handling
The JWT module provides JWT token signing utilities for secure playback, DRM license acquisition, and signed statistics requests. JWT tokens enable access control for video content and analytics data.
import Mux from '@mux/mux-node';
const client = new Mux({
tokenId: 'YOUR_TOKEN_ID',
tokenSecret: 'YOUR_TOKEN_SECRET',
jwtSigningKey: 'YOUR_SIGNING_KEY_ID',
jwtPrivateKey: 'YOUR_PRIVATE_KEY',
});
// Access JWT functionality
const jwt = client.jwt;Create a JWT token for signed playback ID access.
interface Jwt {
/**
* Create a JWT token for signed playback ID
* @param playbackId Playback ID to sign
* @param config JWT signing options
* @returns JWT token string
*/
signPlaybackId(
playbackId: string,
config?: MuxJWTSignOptions<TypeClaim>
): Promise<string>;
}
interface MuxJWTSignOptions<T> {
/** Token type (e.g., 'video', 'thumbnail', 'gif', 'storyboard', 'drm_license') */
type?: T;
/** Token expiration (e.g., '7d', '1h', '30m') - default: '7d' */
expiration?: string;
/** Additional JWT claims */
params?: Record<string, any>;
/** Signing key ID (overrides client.jwtSigningKey) */
keyId?: string;
/** Private key (overrides client.jwtPrivateKey) */
keySecret?: string;
/** Path to private key file (overrides client.jwtPrivateKey) */
keyFilePath?: string;
}
enum TypeClaim {
video = 'v',
thumbnail = 't',
gif = 'g',
storyboard = 's',
stats = 'playback_id',
drm_license = 'd',
}Usage Example:
// Sign a playback ID for video playback
const token = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: 'video',
expiration: '1h',
params: {
aud: 'v', // Audience claim
},
});
// Use in playback URL
const playbackUrl = `https://stream.mux.com/PLAYBACK_ID.m3u8?token=${token}`;Create multiple JWT tokens for different media types in one call.
interface Jwt {
/**
* Create multiple JWT tokens for different media types
* @param playbackId Playback ID to sign
* @param config JWT signing options with multiple types
* @returns Object containing tokens for each type
*/
signPlaybackId(
playbackId: string,
config?: MuxJWTSignOptionsMultiple<TypeClaim>
): Promise<Tokens>;
}
interface MuxJWTSignOptionsMultiple<T> {
/**
* Array of token types or [type, params] tuples
* @example ['video', 'thumbnail', 'storyboard']
* @example [['video', { time: '10' }], 'thumbnail']
*/
type?: Array<T | [T, Record<string, any>]>;
/** Token expiration (e.g., '7d', '1h', '30m') - default: '7d' */
expiration?: string;
/** Base JWT claims applied to all tokens */
params?: Record<string, any>;
/** Signing key ID (overrides client.jwtSigningKey) */
keyId?: string;
/** Private key (overrides client.jwtPrivateKey) */
keySecret?: string;
/** Path to private key file (overrides client.jwtPrivateKey) */
keyFilePath?: string;
}
interface Tokens {
'playback-token'?: string;
'thumbnail-token'?: string;
'gif-token'?: string;
'storyboard-token'?: string;
'drm-token'?: string;
'stats-token'?: string;
}Usage Example:
// Create tokens for video, thumbnail, and storyboard
const tokens = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: [
'video',
['thumbnail', { time: '10' }], // Thumbnail at 10 seconds
'storyboard',
],
expiration: '1h',
});
// Use different tokens for different purposes
const videoUrl = `https://stream.mux.com/PLAYBACK_ID.m3u8?token=${tokens.video}`;
const thumbnailUrl = `https://image.mux.com/PLAYBACK_ID/thumbnail.jpg?token=${tokens.thumbnail}`;
const storyboardUrl = `https://image.mux.com/PLAYBACK_ID/storyboard.jpg?token=${tokens.storyboard}`;Create a JWT token for DRM license acquisition.
interface Jwt {
/**
* Create a JWT token for DRM license acquisition
* @param playbackId Playback ID with DRM policy
* @param config JWT signing options
* @returns JWT token for DRM license requests
*/
signDrmLicense(
playbackId: string,
config?: MuxJWTSignOptions<TypeClaim>
): Promise<string>;
}Usage Example:
// Create DRM license token
const drmToken = await client.jwt.signDrmLicense('PLAYBACK_ID', {
expiration: '24h',
});
// Use with DRM-protected content
// The player will automatically request a license using this tokenCreate a JWT token for signed statistics requests.
interface Jwt {
/**
* Create a JWT token for signed statistics request
* @param id Asset or live stream ID
* @param config JWT signing options
* @returns JWT token for viewer count requests
*/
signViewerCounts(
id: string,
config?: MuxJWTSignOptions<DataTypeClaim>
): Promise<string>;
}
enum DataTypeClaim {
video = 'video_id',
asset = 'asset_id',
playback = 'playback_id',
live_stream = 'live_stream_id',
}Usage Example:
// Create token for video viewer counts
const viewerToken = await client.jwt.signViewerCounts('ASSET_ID', {
type: 'video',
expiration: '7d',
});
// Use to access viewer statisticsCreate a JWT token for Mux Real-Time Video spaces (deprecated).
interface Jwt {
/**
* Create a JWT token for Mux Real-Time Video spaces
* @deprecated Mux Real-Time Video has been shut down
* @param spaceId Space ID to sign
* @param config JWT signing options
* @returns JWT token
*/
signSpaceId(
spaceId: string,
config?: MuxJWTSignOptions<never>
): Promise<string>;
}Note: This method is deprecated as Mux Real-Time Video has been shut down. It will be removed in the next major version.
Different token types use different audience claims:
/** Audience claims for playback tokens */
enum TypeClaim {
/** Video playback */
video = 'v',
/** Thumbnail images */
thumbnail = 't',
/** Animated GIFs */
gif = 'g',
/** Storyboard images */
storyboard = 's',
/** Statistics (not supported by Mux Player) */
stats = 'playback_id',
/** DRM license */
drm_license = 'd',
}
/** Audience claims for data/statistics tokens */
enum DataTypeClaim {
/** Video data */
video = 'video_id',
/** Asset data */
asset = 'asset_id',
/** Playback data */
playback = 'playback_id',
/** Live stream data */
live_stream = 'live_stream_id',
}// Step 1: Create an asset with signed playback policy
const asset = await client.video.assets.create({
inputs: [{ url: 'https://example.com/video.mp4' }],
playback_policies: ['signed'],
});
// Step 2: Create a playback ID (if needed)
const playbackId = await client.video.assets.createPlaybackId(asset.id, {
policy: 'signed',
});
// Step 3: Sign the playback ID
const token = await client.jwt.signPlaybackId(playbackId.id, {
type: 'video',
expiration: '1h',
});
// Step 4: Use in playback URL
const url = `https://stream.mux.com/${playbackId.id}.m3u8?token=${token}`;Add custom claims to JWT tokens:
const token = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: 'video',
expiration: '2h',
params: {
aud: 'v', // Audience
sub: 'user-123', // Subject (user ID)
custom_claim: 'custom_value', // Custom claim
},
});Control when content can be accessed:
const token = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: 'video',
params: {
// Content not valid before this time
nbf: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
// Content expires at this time
exp: Math.floor(Date.now() / 1000) + 7200, // 2 hours from now
},
});Limit playback to specific domains:
const token = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: 'video',
expiration: '1h',
params: {
// Only allow playback from these domains
aud: 'v',
// Custom domain restriction (requires server-side validation)
allowed_domains: ['example.com', 'www.example.com'],
},
});Override the default signing key for specific tokens:
const token = await client.jwt.signPlaybackId('PLAYBACK_ID', {
type: 'video',
expiration: '1h',
keyId: 'DIFFERENT_KEY_ID',
keySecret: 'DIFFERENT_PRIVATE_KEY',
});The expiration parameter accepts various time formats:
'7d' - 7 days'24h' - 24 hours'30m' - 30 minutes'1h30m' - 1 hour 30 minutes'1w' - 1 weekDefault expiration is '7d' (7 days) if not specified.
Keep private keys secure: Never expose private keys in client-side code or version control.
Use short expirations: For sensitive content, use shorter token expiration times (e.g., 1-2 hours).
Rotate signing keys: Periodically rotate signing keys for enhanced security.
Use HTTPS: Always serve signed content over HTTPS to prevent token interception.
Combine with other restrictions: Use JWT tokens alongside playback restrictions for defense in depth.
Don't embed tokens in URLs for public content: URLs can be logged and shared. For sensitive content, deliver tokens dynamically.
Validate custom claims server-side: Custom claims should be validated by your application logic.
Complete workflow for signed playback:
// 1. Create asset with signed policy
const asset = await client.video.assets.create({
inputs: [{ url: 'https://example.com/video.mp4' }],
playback_policies: ['signed'],
});
// 2. Wait for asset to be ready
let readyAsset;
do {
await new Promise((resolve) => setTimeout(resolve, 5000));
readyAsset = await client.video.assets.retrieve(asset.id);
} while (readyAsset.status !== 'ready');
// 3. Get playback ID
const playbackId = readyAsset.playback_ids[0].id;
// 4. Generate token (on-demand, per user/session)
const token = await client.jwt.signPlaybackId(playbackId, {
type: 'video',
expiration: '1h',
params: {
sub: 'user-123', // User identifier
},
});
// 5. Return playback URL to client
return {
url: `https://stream.mux.com/${playbackId}.m3u8?token=${token}`,
expiresIn: 3600, // 1 hour in seconds
};Complete workflow for DRM-protected content:
// 1. Create asset with DRM policy
const asset = await client.video.assets.create({
inputs: [{ url: 'https://example.com/video.mp4' }],
playback_policies: ['drm'],
});
// 2. Create DRM playback ID
const playbackId = await client.video.assets.createPlaybackId(asset.id, {
policy: 'drm',
drm_configuration_id: 'DRM_CONFIG_ID',
});
// 3. Generate DRM license token
const drmToken = await client.jwt.signDrmLicense(playbackId.id, {
expiration: '24h',
});
// 4. Return playback info to client
return {
playbackId: playbackId.id,
drmToken: drmToken,
// Client player will use drmToken to acquire DRM license
};Install with Tessl CLI
npx tessl i tessl/npm-mux--mux-nodedocs