Video Decoder
Ember’s video decoder is a dual-backend native Rust module with zero-copy frame delivery into a SharedArrayBuffer.
Backends
Section titled “Backends”FFmpeg (preferred)
Section titled “FFmpeg (preferred)”Uses the ffmpeg-next crate. Tries hardware-accelerated NVDEC decoders first:
h264_cuvidhevc_cuvidav1_cuvid
If hardware decode is unavailable, it falls back to software decode.
GStreamer (fallback)
Section titled “GStreamer (fallback)”Uses gstreamer / gstreamer-app crates with a pipeline:
uridecodebin → videoconvert → appsinkWhy two separate .node files
Section titled “Why two separate .node files”FFmpeg and GStreamer link against different C libraries. If both were linked into the same .node, missing runtime libraries would prevent the addon from loading at all.
By building two variants and trying them at runtime, Ember gracefully degrades if only one set of libraries is present:
video-decoder-ffmpeg.nodevideo-decoder-gstreamer.node
Renderer integration
Section titled “Renderer integration”| Component | Purpose |
|---|---|
useNativeVideo.ts | React hook managing decoder lifecycle, SAB, WebGL renderer, and rAF frame pump |
webgl-renderer.ts | WebGL texture renderer for RGBA frames |
VideoPlayer.tsx | Dual-mode player: <video> element for MP4/WebM/H.264, native decoder + WebGL canvas for MKV/HEVC |
video-decoder.service.ts | Main-process service that loads the correct .node backend at runtime |
ipc/index.ts | IPC handlers bridging renderer → main → Rust decoder |
URL resolution
Section titled “URL resolution”Before passing URLs to FFmpeg, Ember resolves them:
ember://media/<path>→ local filesystem pathember://remote/<sourceId>/<path>→http://localhost:<port>/<path>