@mediafox/core
v1.1.0
Published
Framework-agnostic media player library powered by MediaBunny
Downloads
7,179
Maintainers
Readme
MediaFox
Framework-agnostic media player library with full control over playback. Supports playlists, tracks, custom rendering, and more.
Features
- Canvas-based video rendering (WebGPU/WebGL/Canvas2D)
- Web Audio API integration
- Multi-track support (video/audio/subtitles)
- Playlist support: Sequential/manual play, position preservation
- Reactive state and type-safe events
- Framework-agnostic (React, Vue, Svelte, Angular, vanilla)
Quick Start
import { MediaFox } from 'mediafox';
const player = new MediaFox({ renderTarget: canvas });
await player.load('video.mp4');
player.play();With Playlist
await player.loadPlaylist(['video1.mp4', 'audio1.mp3']);
player.playlistMode = 'sequential';
player.play(); // Auto-switches on endSee docs/guide/getting-started.md for full setup.
A framework-agnostic, TypeScript-first Media Player library powered by Mediabunny. MediaFox provides an ergonomic API for media playback with complete control over rendering and UI.
Features
- Framework Agnostic - Works with React, Vue, Angular, or vanilla JavaScript
- Complete Media Support - Video, audio, and subtitle tracks
- Performance First - Efficient frame buffering and audio scheduling
- Small & Tree-shakable - Only include what you use
- UI Flexibility - You control the interface completely
- TypeScript Native - Full type safety and excellent IDE support
- Advanced Features - Screenshot, frame extraction, quality switching
- Plugin System - Extend functionality easily
Installation
bun add @mediafox/core mediabunny
# or
npm install @mediafox/core mediabunny
# or
yarn add @mediafox/core mediabunnyNote: Mediabunny is a peer dependency. You need to install it alongside @mediafox/core.
Quick Start
import { MediaFox } from '@mediafox/core';
// Create player instance
const player = new MediaFox({
renderTarget: document.querySelector('canvas'),
volume: 0.8
});
// Load media
await player.load(videoFile); // File, Blob, URL, or ArrayBuffer
// Control playback
await player.play();
player.pause();
player.currentTime = 30; // Seek to 30 seconds
player.volume = 0.5;
// Subscribe to state changes
player.subscribe(state => {
console.log(`Time: ${state.currentTime}/${state.duration}`);
console.log(`State: ${state.state}`);
});
// Handle events
player.on('play', () => console.log('Playing'));
player.on('pause', () => console.log('Paused'));
player.on('timeupdate', ({ currentTime }) => {
updateProgressBar(currentTime);
});Framework Packages
For React applications, use the dedicated React package:
npm install @mediafox/react @mediafox/core mediabunnyimport { useMediaFox } from '@mediafox/react';
function VideoPlayer({ src }: { src: File | string }) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const { player, state, play, pause } = useMediaFox({
renderTarget: canvasRef.current,
onError: (error) => console.error(error)
});
// ...
}Framework Integration Examples
React (using core package)
import { useEffect, useRef, useState } from 'react';
import { MediaFox, type PlayerStateData } from '@mediafox/core';
function VideoPlayer({ src }: { src: File | string }) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const playerRef = useRef<MediaFox>();
const [state, setState] = useState<PlayerStateData>();
useEffect(() => {
const player = new MediaFox({
renderTarget: canvasRef.current!
});
playerRef.current = player;
// Subscribe to state changes
const subscription = player.subscribe(setState);
// Load media
player.load(src);
return () => {
subscription.unsubscribe();
player.dispose();
};
}, [src]);
return (
<div>
<canvas ref={canvasRef} />
<div>
<button onClick={() => playerRef.current?.play()}>Play</button>
<button onClick={() => playerRef.current?.pause()}>Pause</button>
<div>{state?.currentTime} / {state?.duration}</div>
</div>
</div>
);
}Vue 3
<template>
<div>
<canvas ref="canvasRef" />
<div>
<button @click="play">Play</button>
<button @click="pause">Pause</button>
<div>{{ currentTime }} / {{ duration }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { MediaFox } from '@mediafox/core';
const props = defineProps<{ src: File | string }>();
const canvasRef = ref<HTMLCanvasElement>();
const player = ref<MediaFox>();
const currentTime = ref(0);
const duration = ref(0);
onMounted(async () => {
player.value = new MediaFox({
renderTarget: canvasRef.value
});
player.value.subscribe(state => {
currentTime.value = state.currentTime;
duration.value = state.duration;
});
await player.value.load(props.src);
});
onUnmounted(() => {
player.value?.dispose();
});
const play = () => player.value?.play();
const pause = () => player.value?.pause();
</script>Advanced Usage
Track Management
// Get available tracks
const videoTracks = player.getVideoTracks();
const audioTracks = player.getAudioTracks();
// Switch tracks
await player.selectVideoTrack(videoTracks[0].id);
await player.selectAudioTrack(audioTracks[1].id);
// Track info
videoTracks.forEach(track => {
console.log(`${track.codec} ${track.width}x${track.height} @${track.frameRate}fps`);
});Screenshot & Frame Extraction
// Take screenshot at current time
const blob = await player.screenshot({
format: 'png',
quality: 0.9
});
// Extract specific frame
player.currentTime = 10.5;
const frameBlob = await player.screenshot();Event Handling
// All events are strongly typed
player.on('loadedmetadata', (info) => {
console.log(`Duration: ${info.duration}`);
console.log(`Format: ${info.format}`);
console.log(`Has video: ${info.hasVideo}`);
console.log(`Has audio: ${info.hasAudio}`);
});
player.on('error', (error) => {
console.error('Playback error:', error);
});
player.on('trackchange', ({ type, trackId }) => {
console.log(`${type} track changed to ${trackId}`);
});Custom Rendering
// Use your own canvas
const canvas = document.createElement('canvas');
player.setRenderTarget(canvas);
// Or use OffscreenCanvas for worker rendering
const offscreen = canvas.transferControlToOffscreen();
player.setRenderTarget(offscreen);API Reference
Constructor Options
interface PlayerOptions {
renderTarget?: HTMLCanvasElement | OffscreenCanvas;
audioContext?: AudioContext;
volume?: number;
muted?: boolean;
playbackRate?: number;
autoplay?: boolean;
preload?: 'none' | 'metadata' | 'auto';
crossOrigin?: string;
maxCacheSize?: number;
}Main Methods
load(source: MediaSource, options?: LoadOptions): Promise<void>- Load media fileplay(): Promise<void>- Start playbackpause(): void- Pause playbackseek(time: number): Promise<void>- Seek to timestop(): void- Stop playback and resetscreenshot(options?: ScreenshotOptions): Promise<Blob>- Take screenshotdispose(): void- Clean up resourcesdestroy(): void- Destroy player completely
Properties
currentTime: number- Current playback positionduration: number- Total duration (readonly)volume: number- Volume level (0-1)muted: boolean- Mute stateplaybackRate: number- Playback speedpaused: boolean- Pause state (readonly)ended: boolean- Ended state (readonly)seeking: boolean- Seeking state (readonly)
State Management
// Subscribe to all state changes
const subscription = player.subscribe(state => {
// state contains all player state
});
// Get current state
const state = player.getState();
// Unsubscribe
subscription.unsubscribe();Events
All events follow the pattern:
player.on(eventName, callback);
player.once(eventName, callback);
player.off(eventName, callback);Available events:
loadstart,loadedmetadata,loadeddata,canplay,canplaythroughplay,pause,playing,endedtimeupdate,durationchange,volumechange,ratechangeseeking,seeked,waiting,progresserror,trackchange,qualitychange,resize
Browser Support
MediaFox requires a modern browser with support for:
- WebCodecs API
- Web Audio API
- Canvas API
- ES2022+
License
MIT
Credits
Powered by Mediabunny - the powerful media processing library for the web.
