sec4i-player
v0.1.0
Published
Lightweight, high-performance HLS video player powered by Rust/WebAssembly
Maintainers
Readme
Why sec4i-player?
| | sec4i-player | hls.js | |---|---|---| | JS Bundle | ~46 KB | ~300 KB | | Heavy Processing | Rust/WASM (Worker) | Main Thread JS | | GC Pressure | Near Zero | High | | Dropped Frames | 0 | 3+ | | Dependencies | 0 | 30+ |
All demuxing, transmuxing, and ABR computation happens in a Web Worker via Rust/WebAssembly — your main thread stays free.
Features
- HLS Streaming — MPEG-TS → fMP4 transmuxing entirely in Rust/WASM
- Video + Audio — H.264 video and AAC audio with separate MSE SourceBuffers
- Web Worker — All heavy processing off the main thread
- Adaptive Bitrate — EWMA bandwidth estimation with buffer-aware quality selection
- Seek — Full seek support with on-demand segment loading
- Buffer Management — Smart pruning, overflow recovery, rebuffering
- Lightweight — Zero runtime dependencies, no framework required
- MP4 — Direct MP4 playback support
- TypeScript — Full type definitions, strict mode
Quick Start
CDN / Script Tag
<video id="player" playsinline></video>
<script src="sec4i-player.min.js"></script>
<script>
const player = new Sec4iPlayer.Sec4iPlayer(
document.getElementById('player'),
{ controls: true, workerUrl: './sec4i-player.worker.js' }
);
player.load('https://example.com/stream.m3u8');
</script>ESM / npm
npm install sec4i-playerimport { Sec4iPlayer } from 'sec4i-player';
const player = new Sec4iPlayer(videoElement, {
controls: true,
workerUrl: '/sec4i-player.worker.js',
});
await player.load('https://example.com/stream.m3u8');
await player.play();API
Constructor
new Sec4iPlayer(element: HTMLVideoElement | string, options?: Sec4iPlayerOptions)Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| controls | boolean | true | Show built-in playback controls |
| autoplay | boolean | false | Auto-play on load |
| muted | boolean | false | Start muted |
| loop | boolean | false | Loop playback |
| workerUrl | string | 'sec4i-player.worker.js' | Web Worker script URL |
| bufferGoal | number | 60 | Target forward buffer (seconds) |
| bufferMax | number | 120 | Maximum buffer (seconds) |
| bufferBehind | number | 90 | Data to keep behind playhead (seconds) |
Methods
player.load(src: string): Promise<void> // Load MP4 or HLS stream
player.play(): Promise<void> // Start playback
player.pause(): void // Pause playback
player.seek(time: number): void // Seek to time in seconds
player.destroy(): void // Release all resources
// Properties
player.currentTime: number // Get/set playback position
player.duration: number // Stream duration
player.volume: number // Get/set volume (0-1)
player.muted: boolean // Get/set mute state
player.paused: boolean // Playback state
player.levels: QualityLevel[] // Available quality levelsEvents
player.on('ready', () => { /* Player initialized */ });
player.on('play', () => { /* Playback started */ });
player.on('pause', () => { /* Playback paused */ });
player.on('ended', () => { /* Playback ended */ });
player.on('timeupdate', (time: number) => { /* Time changed */ });
player.on('error', (err: Sec4iPlayerError) => { /* Error occurred */ });
player.on('qualitychange', (level: QualityLevel) => { /* ABR quality info */ });
// Unsubscribe
const unsub = player.on('timeupdate', handler);
unsub(); // Remove listenerStatic
Sec4iPlayer.isSupported() // Check MSE/WASM support
Sec4iPlayer.version // "0.1.0"Architecture
┌──────────────────────────────────────────────────┐
│ Main Thread │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Player │ │ UI │ │ MSE │ │
│ │Controller │ │ Controls │ │ Manager │ │
│ └─────┬─────┘ └──────────┘ └──────┬───────┘ │
│ │ │ │
│ └──────────┬──────────────────┘ │
│ │ postMessage │
└───────────────────┼──────────────────────────────┘
│
┌───────────────────▼──────────────────────────────┐
│ Web Worker │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Rust / WebAssembly │ │
│ │ │ │
│ │ ┌──────────┐ ┌────────────────────────┐ │ │
│ │ │ HLS │ │ TS → fMP4 │ │ │
│ │ │ Parser │ │ Transmuxer │ │ │
│ │ └──────────┘ └────────────────────────┘ │ │
│ │ ┌──────────┐ ┌────────────────────────┐ │ │
│ │ │ ABR │ │ Buffer │ │ │
│ │ │ Engine │ │ Strategy │ │ │
│ │ └──────────┘ └────────────────────────┘ │ │
│ └────────────────────────────────────────────┘ │
└───────────────────┬──────────────────────────────┘
│ ArrayBuffer (Transferable)
┌───────────────────▼──────────────────────────────┐
│ <video> element │
│ Media Source Extensions (MSE) │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Video SB │ │ Audio SB │ │
│ │ (H.264) │ │ (AAC) │ │
│ └─────────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────┘Build from Source
Prerequisites: Node.js 18+, Rust 1.70+, wasm-pack
git clone https://github.com/wktk0/sec4i-player.git
cd sec4i-player
npm install
npm run build # Build everything (WASM + TS + Worker + CSS)Individual build targets
npm run build:wasm # Rust → WebAssembly
npm run build:ts # TypeScript → IIFE bundle
npm run build:esm # TypeScript → ESM bundle
npm run build:worker # Worker → bundle
npm run build:css # StylesSupported Formats
| Format | Container | Video | Audio | Status | |--------|-----------|-------|-------|--------| | HLS | MPEG-TS | H.264 | AAC | Supported | | MP4 | MP4 | H.264 | AAC | Supported (native) | | HLS | fMP4 | — | — | Planned | | DASH | — | — | — | Not planned |
Browser Support
| Browser | Version | Notes | |---------|---------|-------| | Chrome | 60+ | Full support | | Edge | 79+ | Full support | | Firefox | 42+ | Full support | | Safari | 11+ | Partial (MSE quirks) |
Requires: MediaSource Extensions, WebAssembly, Web Workers (ESM)
Roadmap
- [ ] ABR quality switching (changeType API)
- [ ] AES-128 encrypted HLS
- [ ] Live HLS streams
- [ ] fMP4 HLS segments
- [ ] WebVTT subtitles
- [ ] npm publish
See TASKS.md for the full roadmap.
License
MIT — free for commercial and personal use.
