HTML5 video and audio player with unified cross-browser interface and extensive customization options
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
MediaElement.js uses a pluggable renderer architecture that allows support for multiple media formats and streaming protocols beyond native HTML5 capabilities.
All renderers implement a standardized interface for media format support and playback.
interface Renderer {
/** Unique name identifying the renderer */
name: string;
/** Renderer-specific configuration options */
options: RendererOptions;
/** Check if renderer can play a specific media type */
canPlayType(type: string): '' | 'maybe' | 'probably';
/** Create renderer instance for media playback */
create(mediaElement: MediaElement, options: any, mediaFiles: MediaFile[]): RendererInstance;
}
interface RendererOptions {
/** Renderer priority (higher = preferred) */
priority?: number;
/** Additional renderer-specific options */
[key: string]: any;
}
interface MediaFile {
src: string;
type?: string;
}
interface RendererInstance {
/** Start media playback */
play(): void;
/** Pause media playback */
pause(): void;
/** Load media source */
load(): void;
/** Set current playback time */
setCurrentTime(time: number): void;
/** Set volume level */
setVolume(volume: number): void;
/** Set mute state */
setMuted(muted: boolean): void;
/** Destroy renderer instance */
destroy(): void;
}MediaElement.js includes several built-in renderers for common media formats.
/** Available built-in renderers */
const builtInRenderers = [
'html5', // Native HTML5 audio/video
'hls', // HTTP Live Streaming (requires hls.js)
'dash', // MPEG-DASH (requires dash.js)
'youtube', // YouTube videos
'vimeo', // Vimeo videos
'dailymotion', // Dailymotion videos
'soundcloud', // SoundCloud audio
'facebook', // Facebook videos
'twitch' // Twitch streams
];The default renderer using native HTML5 audio/video elements.
interface Html5Renderer extends Renderer {
name: 'html5';
/** Native HTML5 media types supported */
supportedTypes: string[];
}
// Supported media types
const html5SupportedTypes = [
'audio/mp3', 'audio/ogg', 'audio/oga', 'audio/wav', 'audio/x-wav',
'audio/wave', 'audio/x-pn-wav', 'audio/mpeg', 'audio/mp4',
'video/mp4', 'video/webm', 'video/ogg', 'video/ogv'
];Usage Examples:
// HTML5 renderer is used automatically for supported formats
const player = new MediaElementPlayer('video', {
renderers: ['html5'] // Explicit HTML5 only
});
// Check HTML5 support
const canPlay = player.media.canPlayType('video/mp4');
console.log('MP4 support:', canPlay); // '', 'maybe', or 'probably'HTTP Live Streaming renderer for adaptive bitrate streaming.
interface HlsRenderer extends Renderer {
name: 'hls';
/** HLS-specific configuration options */
options: HlsOptions;
}
interface HlsOptions {
/** Path to hls.js library */
path?: string;
/** HLS.js configuration object */
hlsConfig?: HlsConfig;
/** Enable debug logging */
debug?: boolean;
}
interface HlsConfig {
/** Maximum buffer length in seconds */
maxBufferLength?: number;
/** Start level (-1 for auto) */
startLevel?: number;
/** Enable ABR (Adaptive Bitrate) */
enableWorker?: boolean;
/** Additional hls.js options */
[key: string]: any;
}Usage Examples:
// Enable HLS with custom configuration
const player = new MediaElementPlayer('video', {
renderers: ['hls', 'html5'],
hls: {
hlsConfig: {
maxBufferLength: 30,
startLevel: -1, // Auto quality
enableWorker: true
},
debug: false
}
});
// HLS playlist URL
player.media.src = 'https://example.com/stream.m3u8';MPEG-DASH renderer for adaptive streaming.
interface DashRenderer extends Renderer {
name: 'dash';
/** DASH-specific configuration options */
options: DashOptions;
}
interface DashOptions {
/** Path to dash.js library */
path?: string;
/** DASH.js configuration object */
dashConfig?: DashConfig;
/** Enable debug logging */
debug?: boolean;
}
interface DashConfig {
/** Enable debug logging in dash.js */
debug?: boolean;
/** Initial bitrate for video */
initialBitrateFor?: {
video?: number;
audio?: number;
};
/** Additional dash.js options */
[key: string]: any;
}Usage Examples:
// Enable DASH renderer
const player = new MediaElementPlayer('video', {
renderers: ['dash', 'html5'],
dash: {
dashConfig: {
debug: false,
initialBitrateFor: {
video: 1000000, // 1 Mbps
audio: 128000 // 128 kbps
}
}
}
});
// DASH manifest URL
player.media.src = 'https://example.com/stream.mpd';Renderer for embedding YouTube videos.
interface YouTubeRenderer extends Renderer {
name: 'youtube';
/** YouTube-specific options */
options: YouTubeOptions;
}
interface YouTubeOptions {
/** YouTube API key (optional) */
apiKey?: string;
/** YouTube player parameters */
youtubeParams?: YouTubeParams;
}
interface YouTubeParams {
/** Enable video controls */
controls?: 0 | 1;
/** Enable related videos */
rel?: 0 | 1;
/** Video quality preference */
vq?: 'small' | 'medium' | 'large' | 'hd720' | 'hd1080';
/** Additional YouTube parameters */
[key: string]: any;
}Usage Examples:
// YouTube video player
const player = new MediaElementPlayer('video', {
renderers: ['youtube', 'html5'],
youtube: {
youtubeParams: {
controls: 0, // Hide YouTube controls
rel: 0, // Disable related videos
vq: 'hd720' // Prefer 720p quality
}
}
});
// YouTube video URL
player.media.src = 'https://www.youtube.com/watch?v=VIDEO_ID';Renderer for embedding Vimeo videos.
interface VimeoRenderer extends Renderer {
name: 'vimeo';
/** Vimeo-specific options */
options: VimeoOptions;
}
interface VimeoOptions {
/** Vimeo player parameters */
vimeoParams?: VimeoParams;
}
interface VimeoParams {
/** Video portrait display */
portrait?: 0 | 1;
/** Video title display */
title?: 0 | 1;
/** Video byline display */
byline?: 0 | 1;
/** Player color theme */
color?: string;
/** Additional Vimeo parameters */
[key: string]: any;
}Usage Examples:
// Vimeo video player
const player = new MediaElementPlayer('video', {
renderers: ['vimeo', 'html5'],
vimeo: {
vimeoParams: {
portrait: 0,
title: 0,
byline: 0,
color: 'ff0000' // Red theme
}
}
});
// Vimeo video URL
player.media.src = 'https://vimeo.com/VIDEO_ID';The renderer system provides methods for managing and selecting renderers.
interface RendererManager {
/** Register a new renderer */
add(renderer: Renderer): void;
/** Select best renderer for media files */
select(mediaFiles: MediaFile[], renderers?: string[]): Renderer | null;
/** Get all registered renderers */
getRenderers(): { [name: string]: Renderer };
/** Set renderer priority order */
order: string[];
}
// Access renderer manager
const rendererManager = window.mejs.Renderers;Usage Examples:
// Check available renderers
const renderers = window.mejs.Renderers.getRenderers();
console.log('Available renderers:', Object.keys(renderers));
// Set renderer priority
window.mejs.Renderers.order = ['hls', 'dash', 'html5', 'youtube'];
// Select renderer for specific media
const mediaFiles = [
{ src: 'video.m3u8', type: 'application/vnd.apple.mpegurl' },
{ src: 'video.mp4', type: 'video/mp4' }
];
const selectedRenderer = window.mejs.Renderers.select(mediaFiles);
console.log('Selected renderer:', selectedRenderer?.name);Create custom renderers for specialized media formats or services.
/**
* Custom renderer implementation example
*/
const CustomRenderer = {
name: 'custom',
options: {
priority: 10
},
/**
* Check if renderer supports media type
*/
canPlayType(type) {
return type === 'custom/format' ? 'probably' : '';
},
/**
* Create renderer instance
*/
create(mediaElement, options, mediaFiles) {
const customInstance = {
// Implement required methods
play() {
console.log('Custom renderer: play');
},
pause() {
console.log('Custom renderer: pause');
},
load() {
console.log('Custom renderer: load');
},
setCurrentTime(time) {
console.log('Custom renderer: setCurrentTime', time);
},
setVolume(volume) {
console.log('Custom renderer: setVolume', volume);
},
setMuted(muted) {
console.log('Custom renderer: setMuted', muted);
},
destroy() {
console.log('Custom renderer: destroy');
}
};
return customInstance;
}
};
// Register custom renderer
window.mejs.Renderers.add(CustomRenderer);Configure renderers globally or per-player instance.
// Global renderer configuration
window.mejs.HlsRenderer = {
options: {
hlsConfig: {
maxBufferLength: 60,
enableWorker: true
}
}
};
// Per-instance renderer configuration
const player = new MediaElementPlayer('video', {
renderers: ['hls', 'html5'],
hls: {
hlsConfig: {
startLevel: 2, // Start at specific quality level
maxBufferLength: 30
},
debug: true
}
});Renderers can dispatch custom events for advanced integration.
// Listen for renderer-specific events
const player = new MediaElementPlayer('video', {
success: (mediaElement) => {
// HLS-specific events (when using HLS renderer)
mediaElement.addEventListener('hlsManifestParsed', (e) => {
console.log('HLS manifest loaded');
});
mediaElement.addEventListener('hlsLevelSwitched', (e) => {
console.log('Quality level changed');
});
// DASH-specific events (when using DASH renderer)
mediaElement.addEventListener('dashQualityChanged', (e) => {
console.log('DASH quality changed');
});
}
});