Modules โ
Movi-Player is designed with modularity in mind. Use only what you need.
Module Overview โ
| Module | Import Path | Size | Gzip | Brotli | Use Case |
|---|---|---|---|---|---|
| Demuxer | movi-player/demuxer | ~45KB | 2.31 MB | 1.74 MB | Metadata, HDR detection, packet reading |
| Player | movi-player/player | ~180KB | 2.52 MB | 1.91 MB | Playback control, custom UI |
| Element | movi-player / movi-player/element | ~410KB | 2.57 MB | 1.95 MB | Full UI player (drop-in) |
Module sizes (first column) exclude the embedded WASM binary. Gzip/Brotli columns show the total transfer size including WASM. Enable Brotli compression on your server for optimal delivery.
Demuxer Module (~45KB) โ
Use when you only need metadata extraction without playback.
typescript
import { Demuxer, HttpSource, FileSource } from "movi-player/demuxer";Exports โ
| Export | Type | Description |
|---|---|---|
Demuxer | Class | Media file demuxer |
HttpSource | Class | HTTP source adapter |
FileSource | Class | Local file source adapter |
ThumbnailHttpSource | Class | Optimized for thumbnails |
MoviVideoDecoder | Class | WebCodecs video decoder |
MoviAudioDecoder | Class | WebCodecs audio decoder |
SubtitleDecoder | Class | Subtitle parser |
SoftwareVideoDecoder | Class | Fallback video decoder |
SoftwareAudioDecoder | Class | Fallback audio decoder |
CodecParser | Class | Codec string utilities |
WasmBindings | Class | Low-level FFmpeg bindings |
LRUCache | Class | Cache implementation |
Logger, LogLevel | Utility | Logging |
Time, TIME_BASE | Utility | Time conversions |
EventEmitter | Class | Event handling |
Use Cases โ
- โ Extract video metadata (duration, resolution, codec)
- โ Detect HDR content (colorPrimaries, colorTransfer)
- โ List audio/subtitle tracks with languages
- โ Video file validation
- โ Read packets for custom processing
- โ No playback
- โ No rendering
Example โ
typescript
import { Demuxer, HttpSource } from "movi-player/demuxer";
async function getVideoInfo(url: string) {
const source = new HttpSource(url);
const demuxer = new Demuxer(source);
const info = await demuxer.open();
const video = demuxer.getVideoTracks()[0];
const audio = demuxer.getAudioTracks();
const subtitles = demuxer.getSubtitleTracks();
const result = {
format: info.formatName,
duration: info.duration,
video: video
? {
codec: video.codec,
resolution: `${video.width}x${video.height}`,
frameRate: video.frameRate,
isHDR: video.isHDR,
}
: null,
audioTracks: audio.length,
subtitleTracks: subtitles.length,
};
demuxer.close();
return result;
}Player Module (~180KB) โ
Use when you need full playback control without the built-in UI.

typescript
import { MoviPlayer, LogLevel } from "movi-player/player";Exports โ
Includes everything from demuxer module, plus:
| Export | Type | Description |
|---|---|---|
MoviPlayer | Class | Main player class |
CanvasRenderer | Class | WebGL2 canvas renderer |
AudioRenderer | Class | Web Audio renderer |
TrackManager | Class | Track management |
Clock | Class | A/V sync clock |
PlayerStateManager | Class | State machine |
PlaybackController | Class | Playback orchestration |
Use Cases โ
- โ Build custom player UI
- โ Canvas-based video rendering
- โ Thumbnail/preview generation
- โ Multi-player instances
- โ Headless video processing
- โ Frame-by-frame control
- โ No built-in controls
Example โ
typescript
import { MoviPlayer, LogLevel } from "movi-player/player";
MoviPlayer.setLogLevel(LogLevel.ERROR);
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const player = new MoviPlayer({
source: {
type: "url",
url: "video.mp4",
},
canvas: canvas,
renderer: "canvas",
decoder: "auto",
});
// Event listeners
player.on("loadEnd", () => console.log("Ready!"));
player.on("stateChange", (state) => updateUI(state));
player.on("error", (e) => console.error(e));
// Load and control
await player.load();
await player.play();
// Build your own controls
document.getElementById("playBtn").onclick = () => player.play();
document.getElementById("pauseBtn").onclick = () => player.pause();
document.getElementById("seekBar").oninput = (e) => {
player.seek(parseFloat(e.target.value));
};Element Module (~410KB) โ
Complete drop-in video player with built-in UI.
typescript
import "movi-player";Exports โ
Registers the <movi-player> custom element. Includes everything from player module, plus:
- Custom Element (Web Component)
- Built-in controls UI
- Touch/mouse gestures
- Context menu
- Keyboard shortcuts
- Theming support
- Auto-scaling
Use Cases โ
- โ
Drop-in
<video>replacement - โ Zero configuration
- โ Built-in controls
- โ Mobile-friendly gestures
- โ Keyboard navigation
- โ Quick prototypes
Example โ
html
<script type="module">
import "movi-player";
</script>
<movi-player
src="video.mp4"
controls
autoplay
muted
style="width: 100%; height: 500px;"
></movi-player>Module Composition โ
demuxer (~45KB)
โโโ FFmpeg WASM bindings
โโโ Container parsing (MP4, MKV, WebM, etc.)
โโโ Metadata extraction
โโโ Track enumeration
โโโ HDR detection
โโโ Packet reading
โโโ Source adapters (HTTP, File)
โโโ Codec parsers
player (~180KB) = demuxer +
โโโ MoviPlayer orchestrator
โโโ WebCodecs video decoder
โโโ WebCodecs audio decoder
โโโ Software decoder fallbacks
โโโ CanvasRenderer (WebGL2)
โโโ AudioRenderer (Web Audio)
โโโ TrackManager
โโโ Clock (A/V sync)
โโโ PlaybackController
โโโ State management
element (~410KB) = player +
โโโ <movi-player> Custom Element
โโโ Controls UI (play, seek, volume, fullscreen)
โโโ Touch gesture handler
โโโ Mouse gesture handler
โโโ Context menu
โโโ Settings panel
โโโ Theming engine
โโโ Keyboard shortcutsTree Shaking โ
Movi-Player supports tree shaking. Unused exports are removed:
typescript
// Only imports Demuxer and HttpSource
// ~45KB after tree shaking
import { Demuxer, HttpSource } from "movi-player/demuxer";
// Only what you use is bundled
const demuxer = new Demuxer(new HttpSource(url));CDN Usage โ
Use specific modules via CDN:
html
<!-- Full element (recommended for quick start) -->
<script type="module">
import "https://unpkg.com/movi-player@latest/dist/element.js";
</script>
<!-- Player only (for custom UI) -->
<script type="module">
import { MoviPlayer } from "https://unpkg.com/movi-player@latest/dist/player.js";
</script>
<!-- Demuxer only (for metadata) -->
<script type="module">
import {
Demuxer,
HttpSource,
} from "https://unpkg.com/movi-player@latest/dist/demuxer.js";
</script>Decision Guide โ
mermaid
flowchart TD
A[What do you need?] --> B{Video playback?}
B -->|No| C[demuxer ~45KB]
B -->|Yes| D{Custom UI?}
D -->|Yes| E[player ~180KB]
D -->|No| F[element ~410KB]
C --> G[Metadata, HDR detection, validation]
E --> H[Build your own controls]
F --> I[Drop-in video player]| Scenario | Recommended Module |
|---|---|
| Video upload validation | demuxer |
| HDR detection service | demuxer |
| Video metadata API | demuxer |
| Custom player UI | player |
| Video editing timeline | player |
| Video thumbnail generation | player |
| Simple video playback | element |
| Quick prototype | element |
| Streaming platform | element or player |
Combining Modules โ
You can import from multiple modules, but avoid duplicates:
typescript
// โ
Good - import from most specific module
import { Demuxer, HttpSource } from "movi-player/demuxer";
import { MoviPlayer } from "movi-player/player";
// โ Avoid - don't import same thing from different paths
// import { Demuxer } from 'movi-player/demuxer';
// import { Demuxer } from 'movi-player/player'; // Same class, duplicatedPre-check Before Playback โ
typescript
import { Demuxer, HttpSource } from "movi-player/demuxer";
import { MoviPlayer } from "movi-player/player";
// Quick metadata check with demuxer
async function isValidVideo(url: string): Promise<boolean> {
const demuxer = new Demuxer(new HttpSource(url));
try {
await demuxer.open();
const hasVideo = demuxer.getVideoTracks().length > 0;
demuxer.close();
return hasVideo;
} catch {
return false;
}
}
// Full playback with player
async function play(url: string, canvas: HTMLCanvasElement) {
if (!(await isValidVideo(url))) {
throw new Error("Invalid or unsupported video");
}
const player = new MoviPlayer({
source: { type: "url", url },
canvas,
});
await player.load();
await player.play();
return player;
}