The Native, Zero-Dependency Browser Media Engine
Hardware-accelerated playback, transcoding, and processing for HLS, DASH, MP4, WebM, MKV, FLV, TS, and subtitles β without a 30 MB FFmpeg WASM binary.
π Quick Start β’ β‘ Why No FFmpeg? β’ π₯ Capabilities β’ ποΈ Architecture β’ π¦ Packages β’ π€ Contributing
[!WARNING] VidoLib is in active pre-release development. Packages are built locally from source and are not yet published to npm. APIs may change without notice before v1.0.0.
Overview
Traditional web media players tend to fall into one of two traps:
- Monolithic and heavy. Bundling a 15β40 MB FFmpeg WASM binary that drains mobile battery, adds 1.5β4 seconds to startup, and holds hundreds of megabytes of RAM for the life of the session.
- Standard-player lock-in. Hardcoding layout, network logic, and UI into a single rigid package that's difficult to customize, tree-shake, or extend.
VidoLib takes a runtime-first, modular approach instead:
| Feature | Description |
|---|---|
| π Zero-copy and hardware-accelerated | Direct integration with WebCodecs, WebAudio/AudioWorklet, and WebGL/WebGPU decode paths |
| β‘ Lightweight core | @vidolib/core ships at 3.4 KB gzipped with zero bundled decoders |
| π§© Fully plugin-based | Every container parser, ABR algorithm, subtitle renderer, and UI component is an independent package |
| π‘οΈ Patent-safe | Hardware decoding for licensed codecs (H.264, HEVC, AC-3) keeps patent-pool liability off the application layer |
[!TIP] Only import the plugins you actually use. A minimal HLS-only player can land well under 15 KB gzipped.
Quick Start
VidoLib is currently source-only. Clone and build locally to try it:
# 1. Clone the repository
git clone https://github.com/swadhinbiswas/VidoLib.git
cd VidoLib
# 2. Install workspace dependencies
npm install
# 3. Build all 22 monorepo packages
npm run build
# 4. Run tests
npx vitest run
# 5. Run fuzz testing
node scripts/fuzz-all.js
[!NOTE] The build step compiles each package with esbuild and generates TypeScript declarations.
Usage in Local Projects
Import directly from the compiled dist/ output, or link packages into your own workspace:
import { Player } from '@vidolib/core';
import { PlayerUI } from '@vidolib/ui';
// Initialize the core runtime
const player = new Player();
// Mount a WCAG 2.1 AA accessible UI
const container = document.getElementById('player-root');
const ui = new PlayerUI(player, container);
// Load and play
await player.load('https://example.com/video.mp4');
player.play();
Native Browser FFmpeg-Equivalent Capabilities
VidoLib re-implements the FFmpeg operations most web apps actually need, natively:
π Transcoding
@vidolib/transcoder
GPU-accelerated client-side video frame encoding to H.264/VP9 via VideoEncoder.
const encoder = new HardwareVideoEncoder();
await encoder.init({
codec: 'avc1.4d401f',
width: 1920, height: 1080,
bitrate: 2_000_000
}, onPacket);
π¨ Filters
@vidolib/filters
Real-time GPU Video Filters: Green Screen, Brightness, Contrast, Blur, Watermark.
const processor = new VideoFilterProcessor(canvas);
processor.applyFilters(videoFrame, {
brightness: 1.1,
contrast: 1.2,
chromaKeyGreen: true
});
π΄ Recording
@vidolib/recorder
Zero-Lag Canvas & Screen Recording to downloadable MP4/WebM files.
const recorder = new MediaRecorderPipeline(stream);
recorder.start();
setTimeout(async () => {
const blob = await recorder.stop();
recorder.download('video.webm', blob);
}, 10000);
π¦ Containers
@vidolib/containers
Multi-Container Demuxing: MP4, MKV, WebM, AVI, MOV, FLV, TS, PS, OGG, ASF.
const registry = new ContainerRegistry();
const result = registry.autoDemux(u8ArrayBuffer);
console.log('Tracks:', result.tracks);
Full technical mapping: FFMPEG_CAPABILITIES_ROADMAP.md
Why No FFmpeg WASM
Full rationale: NO_FFMPEG_MANIFESTO.md
| Metric | Native VidoLib | FFmpeg WASM players |
|---|---|---|
| Engine download size | 3.4 KB β 30 KB | 15 MB β 40 MB |
| Startup latency | < 110 ms | 1,500 ms β 4,000 ms |
| Battery impact | Minimal (OS hardware decoders) | Heavy (CPU-bound WASM threads) |
| Memory footprint | < 18 MB RAM | 150 MB β 400 MB RAM |
| Mobile web compatibility | Native OS decoder support | Frequently OOM-crashes iOS Safari |
[!CAUTION] The most common production failure mode for FFmpeg WASM players is memory eviction on iOS Safari under WebKit's stricter tab memory limits.
Architecture Overview
A load request flows from the stream layer through demuxing and hardware decode, out to the render and audio sinks:
flowchart LR
A[Stream layer<br/>HTTP Range / Blob / WS / WebRTC] --> B[Container parser<br/>MP4 / MKV / WebM / TS ...]
B --> C[WebCodecs<br/>hardware decoder]
C --> D[Renderer<br/>Canvas2D / WebGL / WebGPU]
C --> E[WebAudio<br/>AudioWorklet]
F[ABR engine] -.-> A
G[Clock / EventBus] -.-> D
G -.-> E
G -.-> F
Deep dive: docs/ARCHITECTURE.md Β· Plugin authoring: docs/PLUGINS.md
Package Ecosystem
[!NOTE] All packages compile to
packages/<name>/dist/inside the monorepo. None are published to npm yet.
| Package | Purpose | Size (gzip) |
|---|---|---|
@vidolib/core |
Player, clock, pipeline, event bus | 3.44 KB |
@vidolib/stream |
Range HTTP, Blob, File, WS, WebRTC | 2.83 KB |
@vidolib/containers |
MP4, MKV, WebM, AVI, MOV, FLV, TS, PS, OGG, ASF | 14.11 KB |
@vidolib/manifest |
HLS (.m3u8) and DASH (.mpd) parsers |
6.99 KB |
@vidolib/abr |
EWMA throughput and buffer-based ABR | 1.75 KB |
@vidolib/codecs |
WebCodecs / native / WASM negotiator | 4.63 KB |
@vidolib/transcoder |
WebCodecs video/audio encoder | 1.50 KB |
@vidolib/filters |
WebGL chroma key, brightness, blur, watermark | 3.34 KB |
@vidolib/recorder |
Canvas and MediaStream MP4/WebM recorder | 1.62 KB |
@vidolib/renderer |
Canvas2D, WebGL, WebGPU backends | 5.36 KB |
@vidolib/subtitle |
ASS, SRT, VTT subtitle engine | 5.21 KB |
@vidolib/ui |
WCAG 2.1 AA accessible glassmorphic UI | 5.49 KB |
@vidolib/worker |
Web Worker pipeline with error handling | 2.73 KB |
@vidolib/telemetry |
Zero-tracking QoE metrics | 1.76 KB |
@vidolib/security |
Container parser fuzzing & CSP | 1.83 KB |
@vidolib/plugins |
Plugin registry & lifecycle | 1.42 KB |
@vidolib/utils |
BitStreamReader, RingBuffer, Logger | 2.90 KB |
Testing
# Run all unit tests (118 tests)
npx vitest run
# Run fuzz testing (8000 iterations across all demuxers)
node scripts/fuzz-all.js
Test Coverage
| Package | Tests | Status |
|---|---|---|
@vidolib/containers |
26 | β |
@vidolib/manifest |
17 | β |
@vidolib/codecs |
15 | β |
@vidolib/subtitle |
15 | β |
@vidolib/filters |
12 | β |
@vidolib/worker |
12 | β |
@vidolib/renderer |
9 | β |
@vidolib/core |
8 | β |
@vidolib/utils |
2 | β |
@vidolib/ui |
1 | β |
Contributing
| Resource | Description |
|---|---|
CONTRIBUTING.md |
Setup, build system, and PR guidelines |
docs/ARCHITECTURE.md |
Core engine flow, Web Worker pipelines, memory model |
docs/PLUGINS.md |
Build a custom plugin in under 30 lines of code |
docs/ROADMAP.md |
Open contributor tasks |
Contributors
License
Distributed under the MIT License. See LICENSING.md for the full codec licensing guardrails and royalty-free allow-list.
[!IMPORTANT] MIT covers the VidoLib source. It does not grant patent rights for any codec your deployment target doesn't already license β VidoLib sidesteps this by decoding exclusively through OS/browser hardware paths.
Built with β€οΈ using WebCodecs β’ WebGL β’ WebGPU β’ Web Workers