| Crates.io | videocall-codecs |
| lib.rs | videocall-codecs |
| version | 0.1.7 |
| created_at | 2025-06-23 05:47:13.129114+00 |
| updated_at | 2025-09-24 02:07:24.506206+00 |
| description | Cross-platform video codec library with VP8/VP9 support for native and WebAssembly environments |
| homepage | https://github.com/security-union/videocall-rs |
| repository | https://github.com/security-union/videocall-rs |
| max_upload_size | |
| id | 1722309 |
| size | 4,776,315 |
videocall-codecs: Jitter Buffer & DecoderThis crate is a core component of the videocall.rs project. It provides a high-fidelity, cross-platform video decoder and jitter buffer, implemented in pure Rust.
Currently focused on high-quality video decoding and jitter buffering, videocall-codecs is expanding to become a comprehensive multimedia codec solution. Audio support is coming soon - we're actively working on integrating audio codecs (Opus, AAC) alongside our existing video capabilities to provide a unified, cross-platform audio/video processing pipeline.
Our roadmap includes:
push_frame() interface hides complexityuse videocall_codecs::{
decoder::{Decoder, VideoCodec},
frame::{FrameBuffer, VideoFrame, FrameType}
};
let decoder = Decoder::new(
VideoCodec::VP9,
Box::new(|decoded_frame| {
println!("Decoded frame: {}x{}", decoded_frame.width, decoded_frame.height);
})
);
let video_frame = VideoFrame {
sequence_number: 1,
frame_type: FrameType::KeyFrame,
data: encoded_data,
timestamp: 0.0,
};
decoder.decode(FrameBuffer::new(video_frame, current_time_ms));
For WASM builds, the decoder runs in a Web Worker for better performance. Add this to your index.html:
<!-- Compile the worker -->
<link
data-trunk
rel="rust"
href="../videocall-codecs/Cargo.toml"
data-bin="worker_decoder"
data-type="worker"
data-cargo-features="wasm"
data-cargo-no-default-features
data-loader-shim
/>
<!-- Runtime link for decoder -->
<link id="codecs-worker" href="/worker_decoder_loader.js" />
The jitter buffer is the heart of smooth video playback, working with the jitter estimator to adaptively handle network variability:
Real-time video streams suffer from network jitter - frames arrive at irregular intervals even though they were sent at regular intervals. The jitter buffer solves this by:
Here's how the jitter buffer and estimator work together to transform irregular network arrivals into smooth video:
graph TB
subgraph "Network Layer"
NET["🌐 Network Stream<br/>VP9 Frames"]
JITTER["⚡ Network Jitter<br/>Irregular Arrival Times"]
end
subgraph "Jitter Estimator"
ARRIVAL["📥 Frame Arrival<br/>sequence_number: 42<br/>arrival_time: 1000ms"]
CALC["🧮 Jitter Calculation<br/>Expected: 33.3ms intervals<br/>Actual: 45ms interval<br/>Delta: +11.7ms"]
ESTIMATE["📊 Jitter Estimate<br/>Running Average: 8.5ms<br/>(EWMA with 1/16 smoothing)"]
end
subgraph "Jitter Buffer"
BUFFER["📦 Frame Buffer<br/>Reorder & Store<br/>Max: 200 frames"]
DELAY["⏱️ Adaptive Playout Delay<br/>Target: jitter × 3.0<br/>Range: 10ms - 500ms<br/>Current: 25.5ms"]
READY["✅ Ready Queue<br/>Frames past delay threshold"]
end
subgraph "Output"
DECODE["🎬 Decoder<br/>Smooth Frame Stream"]
DISPLAY["📺 Video Display<br/>Consistent 30fps"]
end
NET --> JITTER
JITTER --> ARRIVAL
ARRIVAL --> CALC
CALC --> ESTIMATE
ESTIMATE --> DELAY
ARRIVAL --> BUFFER
BUFFER --> READY
DELAY --> READY
READY --> DECODE
DECODE --> DISPLAY
classDef networkBox fill:#8B0000,stroke:#660000,stroke-width:2px,color:#ffffff
classDef jitterEstBox fill:#1E3A8A,stroke:#1E40AF,stroke-width:2px,color:#ffffff
classDef bufferBox fill:#166534,stroke:#15803D,stroke-width:2px,color:#ffffff
classDef outputBox fill:#B45309,stroke:#C2410C,stroke-width:2px,color:#ffffff
class NET,JITTER networkBox
class ARRIVAL,CALC,ESTIMATE jitterEstBox
class BUFFER,DELAY,READY bufferBox
class DECODE,DISPLAY outputBox
Key Insights:
Example Scenario:
This approach trades a small amount of latency (10-500ms) for significantly improved video quality and eliminates stuttering caused by network jitter.
The crate provides unified jitter buffering across native and web platforms, with platform-specific decoder implementations:
graph TB
subgraph "Application Layer"
APP["🔧 Your Application<br/>push_frame(), decode()"]
end
subgraph "Native Platform"
subgraph "Native Runtime"
NATIVE_JB["📦 Jitter Buffer<br/>Frame Reordering<br/>Adaptive Delay<br/>Gap Recovery"]
NATIVE_DEC["🖥️ Native Decoder<br/>libvpx (VP9)<br/>Direct System Access"]
end
NATIVE_OUT["📺 Native Output<br/>Direct Memory<br/>No GC Overhead"]
end
subgraph "Web Platform"
subgraph "Main Thread"
WASM_API["🌐 WASM API<br/>WasmDecoder<br/>JavaScript Bindings"]
JS_APP["📱 Web App<br/>Canvas Rendering<br/>VideoFrame API"]
end
subgraph "Web Worker Thread"
WORKER_JB["📦 WASM Jitter Buffer<br/>Frame Reordering<br/>Adaptive Delay<br/>Gap Recovery"]
WORKER_DEC["⚙️ WebCodecs Decoder<br/>Browser API<br/>Isolated Processing"]
end
end
APP --> NATIVE_JB
APP --> WASM_API
NATIVE_JB --> NATIVE_DEC
NATIVE_DEC --> NATIVE_OUT
WASM_API --> WORKER_JB
WORKER_JB --> WORKER_DEC
WORKER_DEC --> JS_APP
classDef appBox fill:#4A5568,stroke:#2D3748,stroke-width:2px,color:#ffffff
classDef nativeBox fill:#166534,stroke:#15803D,stroke-width:2px,color:#ffffff
classDef webBox fill:#1E3A8A,stroke:#1E40AF,stroke-width:2px,color:#ffffff
classDef workerBox fill:#7C2D12,stroke:#9A3412,stroke-width:2px,color:#ffffff
class APP appBox
class NATIVE_JB,NATIVE_DEC,NATIVE_OUT nativeBox
class WASM_API,JS_APP webBox
class WORKER_JB,WORKER_DEC workerBox
Architecture Benefits:
🖥️ Native Performance: Direct libvpx integration with zero-copy memory access
🌐 Web Compatibility: WebCodecs API with automatic Web Worker isolation
⚙️ Worker Separation: Heavy processing moved off main thread for smooth UI
🎯 Unified Logic: Same jitter buffer and frame management across platforms
📦 Memory Safety: Rust ownership prevents common C/C++ decoder vulnerabilities
Platform Comparison:
| Feature | Native | WASM/Web |
|---|---|---|
| Decoder | libvpx (C++) | WebCodecs API |
| Threading | OS threads | Web Workers |
| Memory | Direct access | Managed + manual cleanup |
| Performance | Maximum | Near-native |
| Deployment | Binary executable | Browser + CDN |
The crate implements a trait-based abstraction that allows the same jitter buffer logic to work across both native and WASM targets, with platform-specific decoder implementations handling the actual video decoding.
pub struct VideoFrame {
pub sequence_number: u64,
pub frame_type: FrameType, // KeyFrame or DeltaFrame
pub data: Vec<u8>,
pub timestamp: f64,
}
pub struct FrameBuffer {
pub frame: VideoFrame,
pub arrival_time_ms: u128,
}
Native:
let decoder = Decoder::new(VideoCodec::VP9, Box::new(|frame| {
// Handle decoded frame
}));
WASM:
const decoder = new WasmDecoder(VideoCodec.VP9, (videoFrame) => {
ctx.drawImage(videoFrame, 0, 0);
videoFrame.close();
});
const MIN_PLAYOUT_DELAY_MS: f64 = 10.0;
const MAX_PLAYOUT_DELAY_MS: f64 = 500.0;
const JITTER_MULTIPLIER: f64 = 3.0;
const MAX_BUFFER_SIZE: usize = 200;
[features]
default = ["native"]
native = ["libvpx-sys"]
wasm = ["wasm-bindgen", "web-sys", "js-sys", "wasm-bindgen-futures"]
videoFrame.close() in WASM to prevent memory leakscargo test --all-features
wasm-pack test --headless --chrome --features wasm
Licensed under either of Apache License, Version 2.0 or MIT license at your option.