Skip to content

MediaFoxFramework-Agnostic Media Player

A TypeScript-first Media Player library powered by Mediabunny. Full control over rendering and UI, zero opinions.

MediaFox
bash
bun add @mediafox/core mediabunny

Complete media playback control

MediaFox gives you full control over video playback without imposing any UI constraints. Handle multi-track media files with video, audio, and subtitle tracks. Perfect canvas-based rendering with hardware acceleration.

Learn more
typescript
import { MediaFox } from '@mediafox/core';

const player = new MediaFox({
  renderTarget: document.querySelector('#canvas'),
  volume: 0.8,
  autoplay: false
});

// Load media from various sources
await player.load(videoFile);
await player.load('https://example.com/video.mp4');
await player.load(blob);

// Control playback
await player.play();
player.pause();
await player.seek(30);

// Multi-track support
const videoTracks = player.getVideoTracks();
const audioTracks = player.getAudioTracks();
await player.selectAudioTrack(audioTracks[1].id);
typescript
// React to all state changes
player.subscribe(state => {
  console.log('Current time:', state.currentTime);
  console.log('Duration:', state.duration);
  console.log('Playing:', state.playing);
  console.log('Volume:', state.volume);
  console.log('Selected tracks:', {
    video: state.selectedVideoTrack,
    audio: state.selectedAudioTrack,
    subtitle: state.selectedSubtitleTrack
  });
});

// Listen to specific events
player.on('loadedmetadata', (info) => {
  console.log(`Format: ${info.format}`);
  console.log(`Duration: ${info.duration}s`);
});

player.on('timeupdate', ({ currentTime }) => {
  updateProgressBar(currentTime);
});

Reactive state management

Subscribe to state changes and handle events with a clean, type-safe API. Get real-time updates on playback progress, track changes, and media loading states.

Docs

Framework agnostic

Works seamlessly with React, Vue, Angular, Svelte, or vanilla JavaScript. No UI opinions means you can build exactly the interface you want with complete control over every pixel.

Framework guides
typescript
// Framework integration examples

// React
function VideoPlayer({ src }) {
  const playerRef = useRef();
  const [state, setState] = useState(null);

  useEffect(() => {
    const player = new MediaFox({ renderTarget: canvasRef.current });
    const { unsubscribe } = player.subscribe(setState);

    playerRef.current = player;
    return () => { unsubscribe(); player.dispose(); };
  }, []);

  return <canvas ref={canvasRef} onClick={() => player.play()} />;
}

// Vue
const player = new MediaFox({ renderTarget: canvasRef.value });
const state = ref(null);
player.subscribe(newState => state.value = newState);

// Vanilla
const player = new MediaFox({ renderTarget: canvas });
player.subscribe(state => updateUI(state));
typescript
import {
  MediaFox,
  PlayerStateData,
  VideoTrackInfo,
  AudioTrackInfo
} from '@mediafox/core';

const player = new MediaFox({
  renderTarget: canvas,
  volume: 0.8
});

// Full IntelliSense support
player.subscribe((state: PlayerStateData) => {
  updateUI({
    currentTime: state.currentTime, // number
    duration: state.duration,       // number
    playing: state.playing,         // boolean
    tracks: state.videoTracks       // VideoTrackInfo[]
  });
});

TypeScript native

Built from scratch in TypeScript with complete type definitions. Tree-shakable architecture means you only include what you use. Zero dependencies beyond Mediabunny.

Type reference

Multi-renderer system

Automatic selection of the best rendering backend for optimal performance. Seamlessly switches between WebGPU, WebGL, and Canvas2D based on availability and performance needs with automatic fallback.

Performance guide
typescript
// Auto-detect best renderer
const player = new MediaFox({
  renderTarget: canvas
  // Automatically uses WebGPU, WebGL, or Canvas2D
});

// Check available renderers
const supported = MediaFox.getSupportedRenderers();
console.log('Available:', supported);
// Output: ['webgpu', 'webgl', 'canvas2d']

// Manually switch renderers
await player.switchRenderer('webgl');

// Monitor renderer changes
player.on('rendererchange', (type) => {
  console.log(`Using ${type} renderer`);
});

player.on('rendererfallback', ({ from, to }) => {
  console.warn(`Fallback: ${from} → ${to}`);
});
typescript
// Load multiple media files
await player.loadPlaylist([
  { mediaSource: 'video1.mp4', title: 'Episode 1' },
  { mediaSource: 'video2.mp4', title: 'Episode 2' },
  { mediaSource: 'audio.mp3', title: 'Podcast' }
]);

// Set playback mode
player.playlistMode = 'sequential'; // Auto-advance
// Other modes: 'manual', 'repeat', 'repeat-one', null

// Navigation
player.next();  // Next item
player.prev();  // Previous item
player.jumpTo(2); // Jump to index 2

// Position preservation
console.log(player.currentItem?.savedPosition);
// Returns to saved position when switching back

// Listen to playlist events
player.on('playlistitemchange', ({ item, index }) => {
  console.log(`Now playing: ${item.title}`);
});

Playlist support

Play multiple media files in sequence with automatic or manual navigation. Preserves playback position for each item, lazy-loads sources, and prefetches the next item for smooth transitions.

Playlist guide

MIT License