Demux media files in the browser using WebAssembly, designed for WebCodecs
npm install web-demuxer-abacusismadDemux media files in the browser using WebAssembly, designed for WebCodecs.
bash
npm install web-demuxer
`
`typescript
import { WebDemuxer } from "web-demuxer";
const demuxer = new WebDemuxer();
// Example: Get video frame at specific time
async function seek(file, time) {
// 1. Load video file
await demuxer.load(file);
// 2. Demux video file and generate VideoDecoderConfig and EncodedVideoChunk required by WebCodecs
const videoDecoderConfig = await demuxer.getDecoderConfig('video');
const videoEncodedChunk = await demuxer.seek('video', time);
// 3. Decode video frame through WebCodecs
const decoder = new VideoDecoder({
output: (frame) => {
// Render frame, e.g., using canvas drawImage
frame.close();
},
error: (e) => {
console.error('video decoder error:', e);
}
});
decoder.configure(videoDecoderConfig);
decoder.decode(videoEncodedChunk);
decoder.flush();
}
`
Installation
$3
`bash
npm install web-demuxer
`
$3
`html
`
$3
‼️ Important: Place the WASM file in your static directory (e.g., public/) for proper loading.
`typescript
const demuxer = new WebDemuxer({
// Option 1: Use CDN
wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm",
// Option 2: Use local file
// Copy dist/wasm-files/web-demuxer.wasm from npm package to public directory
// You can use plugins like vite-plugin-static-copy to sync automatically
// If JS and WASM are in the same public directory, wasmFilePath can be omitted
// wasmFilePath: "/path/to/your/public/web-demuxer.wasm"
});
`
Live Examples
- Seek Video Frame | Source Code
- Play Video | Source Code
API
$3
#### new WebDemuxer(options?: WebDemuxerOptions)
Creates a new WebDemuxer instance.
Parameters:
- options.wasmFilePath (optional): Custom WASM file path. Defaults to looking for web-demuxer.wasm in the script directory.
$3
#### load(source: File | string): Promise
Loads a media file and initializes the WASM worker.
Parameters:
- source: File object or URL string
Note: All subsequent methods require successful load() execution.
#### getDecoderConfig(type: MediaType): Promise
Gets WebCodecs decoder configuration.
Parameters:
- type: 'video' or 'audio'
Returns: VideoDecoderConfig or AudioDecoderConfig
#### seek(type: MediaType, time: number, seekFlag?: AVSeekFlag): Promise
Seeks to specific time and returns encoded chunk.
Parameters:
- type: 'video' or 'audio'
- time: Time in seconds
- seekFlag: Seek direction (default: backward)
Returns: EncodedVideoChunk or EncodedAudioChunk
#### read(type: MediaType, start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream
Creates a stream of encoded chunks.
Parameters:
- type: 'video' or 'audio'
- start: Start time in seconds (default: 0)
- end: End time in seconds (default: end of file)
- seekFlag: Seek direction (default: backward)
Returns: ReadableStream of encoded chunks
$3
#### getMediaInfo(): Promise
Extracts comprehensive media metadata (similar to ffprobe output).
Returns:
📋 Example Response (Click to expand)
`json
{
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"duration": 263.383946,
"bit_rate": "6515500",
"start_time": 0,
"nb_streams": 2,
"streams": [
{
"id": 1,
"index": 0,
"codec_type": 0,
"codec_type_string": "video",
"codec_name": "h264",
"codec_string": "avc1.640032",
"color_primaries": "bt2020",
"color_range": "tv",
"color_space": "bt2020nc",
"color_transfer": "arib-std-b67",
"profile": "High",
"pix_fmt": "yuv420p",
"level": 50,
"width": 1080,
"height": 2336,
"channels": 0,
"sample_rate": 0,
"sample_fmt": "u8",
"bit_rate": "6385079",
"extradata_size": 36,
"extradata": "Uint8Array",
"r_frame_rate": "30/1",
"avg_frame_rate": "30/1",
"sample_aspect_ratio": "N/A",
"display_aspect_ratio": "N/A",
"start_time": 0,
"duration": 263.33333333333337,
"rotation": 0,
"nb_frames": "7900",
"tags": {
"creation_time": "2023-12-10T15:50:56.000000Z",
"language": "und",
"handler_name": "VideoHandler",
"vendor_id": "[0][0][0][0]"
}
},
{
"id": 2,
"index": 1,
"codec_type": 1,
"codec_type_string": "audio",
"codec_name": "aac",
"codec_string": "mp4a.40.2",
"profile": "",
"pix_fmt": "",
"level": -99,
"width": 0,
"height": 0,
"channels": 2,
"sample_rate": 44100,
"sample_fmt": "",
"bit_rate": "124878",
"extradata_size": 2,
"extradata": "Uint8Array",
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"sample_aspect_ratio": "N/A",
"display_aspect_ratio": "N/A",
"start_time": 0,
"duration": 263.3839455782313,
"rotation": 0,
"nb_frames": "11343",
"tags": {
"creation_time": "2023-12-10T15:50:56.000000Z",
"language": "und",
"handler_name": "SoundHandler",
"vendor_id": "[0][0][0][0]"
}
}
]
}
`
#### getMediaStream(type: MediaType, streamIndex?: number): Promise
Gets information about a specific media stream.
Parameters:
- type: 'video', 'audio' or 'subtitle'
- streamIndex: Stream index (optional)
$3
#### seekMediaPacket(type: MediaType, time: number, seekFlag?: AVSeekFlag): Promise
Gets raw media packet at specific time.
Parameters:
- type: Media type ('video', 'audio' or 'subtitle')
- time: Time in seconds
- seekFlag: Seek direction (default: backward seek)
#### readMediaPacket(type: MediaType, start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream
Returns a ReadableStream for streaming raw media packet data.
Parameters:
- type: Media type ('video', 'audio' or 'subtitle')
- start: Start time in seconds (default: 0)
- end: End time in seconds (default: 0, read till end)
- seekFlag: Seek direction (default: backward seek)
$3
#### setLogLevel(level: AVLogLevel): void
Sets logging verbosity level for debugging purposes.
Parameters:
- level: Log level (see AVLogLevel for available options)
#### destroy(): void
Cleans up resources and terminates worker.
Custom Demuxer
Web-Demuxer provides two pre-built versions:
| Version | Size (gzipped) | Supported Formats |
|---------|----------------|-------------------|
| Full (web-demuxer.wasm) | 1131 kB | mov, mp4, avi, flv, mkv, webm, mpeg, asf, mpegts, etc. |
| Mini (web-demuxer-mini.wasm) | 493 kB | mov, mp4, mkv, webm, m4v |
$3
For specific format support, customize the build:
1. Configure formats in Makefile:
`makefile
DEMUX_ARGS = \
--enable-demuxer=mov,mp4,m4a,3gp,3g2,mj2
`
2. Start Docker environment:
`bash
For ARM64 (Apple Silicon)
npm run dev:docker:arm64
For x86_64 (Intel/AMD)
npm run dev:docker:x86_64
`
3. Build custom WASM:
`bash
npm run build:wasm
`
License
This project is licensed under the MIT License for the main codebase.
The lib/` directory contains FFmpeg-derived code under the LGPL License.