[package] name = "fluxer_webrtc_sender" version = "0.0.0" edition = "2024" license = "AGPL-3.0-or-later" publish = false [workspace] resolver = "2" exclude = [ "vendor/tract-linalg-0.19.16", "vendor/tract-linalg-0.23.1", ] [lib] crate-type = ["cdylib", "rlib"] [features] # `publisher` pulls the LiveKit native SDK (libwebrtc). It is on by default for # the real addon build, but `cargo test --no-default-features` builds only the # pure YUV-conversion core so the unit tests run anywhere (no libwebrtc). default = ["publisher"] publisher = ["dep:livekit", "dep:tokio", "dep:futures-util"] camera-native = ["dep:nokhwa"] # Exposes pub re-exports of private camera-background hot-path internals so the # criterion bench target can call them; never enabled for the shipped addon. bench-internals = [] [dependencies] napi = {version = "3.9.1", default-features = false, features = ["dyn-symbols", "napi8", "tokio_rt"]} napi-derive = "3.5.6" crossbeam-queue = "0.3" # LiveKit native SDK (wraps libwebrtc). Optional / feature-gated. The exact # version is resolved on the Windows build host (where the libwebrtc prebuilt # links); pinned loosely here. # Keep LiveKit's default features (default = ["tokio"] -> the runtime + # signal-client-tokio) AND add a TLS backend for the signal WebSocket -- without # one, connecting to a wss:// SFU fails with "TLS support not compiled in". # rustls-tls-native-roots = pure-Rust TLS using the OS root store (no OpenSSL). livekit = {version = "0.7", optional = true, features = ["rustls-tls-native-roots"]} tokio = {version = "1", optional = true, features = ["rt-multi-thread", "sync", "macros", "time"]} parking_lot = "0.12" fluxer_screen_frame_bus = { path = "../screen-frame-bus" } futures-core = "0.3" # StreamExt::next() for draining inbound NativeAudioStream/NativeVideoStream. futures-util = {version = "0.3", optional = true} libloading = "0.9.0" fluxer_desktop_native = { path = "../rust" } image = {version = "0.25.10", default-features = false, features = ["jpeg", "png", "webp", "gif"]} # System-camera capture for the native camera-publish path. Optional / # feature-gated for the shipped desktop builds. `input-native` maps to V4L2 on # Linux, AVFoundation on macOS, and Media Foundation on Windows. # BUILD-HOST NOTE: `decoding` pulls `mozjpeg-sys`, which statically builds # libjpeg and -- with its default `nasm_simd` -- needs NASM + a C compiler on the # build host. nokhwa = {version = "0.10", optional = true, default-features = false, features = ["input-native", "decoding"]} # Person segmentation for camera background blur / replacement on platforms # without a native segmentation API (Windows, Linux) and as the macOS fallback # when Vision is unavailable. tract is a pure-Rust ONNX inference engine: no # C++ runtime to link or ship per target, deterministic results, and the unit # tests exercise the real model on any build host. It runs the bundled Apache-2.0 # MediaPipe Selfie Segmenter landscape model (models/, ~450 KB, embedded into the # addon) in ~10 ms per 256x144 frame on a laptop core; an inference-cadence # governor halves the rate on machines that miss the frame budget. Cost: ~40 # transitive crates, all pure Rust, compile-time only impact elsewhere. tract-onnx = "0.23" # DeepFilterNet3 noise suppression for the native device-microphone publish # path, replacing the WebRTC-APM fallback when the renderer requests the # deepFilter profile (parity with the web build's deepfilternet3-noise-filter # WASM chain). The crates.io release (0.2.5, 2022) predates DFN3, so this pins # the upstream git repo at the v0.5.6 release tag -- the combination the shipped # deep-filter binaries were built from. `tract` + `default-model` run the # bundled DFN3 ONNX models (~2 MB, embedded into the addon) on the same # pure-Rust tract inference engine already used for person segmentation, albeit # at tract 0.19 (deep_filter's tested series) alongside our 0.23 tree: # compile-time cost only, no new native or C++ dependencies. deep_filter = {git = "https://github.com/Rikorose/DeepFilterNet", rev = "978576aa8400552a4ce9730838c635aa30db5e61", default-features = false, features = ["tract", "default-model"]} # deep_filter declares tract ^0.19.4, but newer releases in that semver range # regress DFN3 model codegen (0.21.4 fails with "duplicate name .../Conv.bias" # on the transposed convolutions). These renamed dependency keys exist solely # to pin deep_filter's tract subtree to 0.19.16, the version in upstream's own # v0.5.6 lockfile; tract's internal `=` pins drag tract-core/hir/data/linalg # along. Never import these directly: the 0.23 `tract-onnx` entry above is the # one the rest of this crate uses. tract-onnx-deepfilter-pin = {package = "tract-onnx", version = "=0.19.16"} tract-pulse-deepfilter-pin = {package = "tract-pulse", version = "=0.19.16"} # Pinned to the 0.15 family to match deep_filter's public API surface # (DfTract::process takes ndarray 0.15 ArrayView2 arguments). ndarray = "0.15" # macOS person segmentation for camera background blur / replacement. Vision's # VNGeneratePersonSegmentationRequest produces the per-pixel person mask that the # camera background transform composites with; without it the transform falls # back to a fixed portrait ellipse. Pinned to the objc2 0.6 / framework 0.3 # family already used across fluxer_desktop/native, so no new dependency tree. [target.'cfg(target_os = "macos")'.dependencies] objc2 = "0.6" objc2-foundation = {version = "0.3", features = ["NSArray", "NSDictionary", "NSError", "NSObject", "NSString"]} objc2-vision = {version = "0.3", default-features = false, features = ["std", "VNRequest", "VNStatefulRequest", "VNGeneratePersonSegmentationRequest", "VNRequestHandler", "VNObservation", "VNTypes", "objc2-core-video", "objc2-core-foundation"]} objc2-core-video = {version = "0.3", features = ["CVPixelBuffer", "CVImageBuffer", "CVBuffer", "CVReturn", "CVBase"]} objc2-core-foundation = {version = "0.3", features = ["CFDictionary", "CFBase"]} [build-dependencies] napi-build = "2.3.2" [dev-dependencies] # Test-only (never linked into the shipped addon): parses the committed golden # event fixtures so the renderer's (eventType, jsonPayload) parser contract is # regression-locked offline, without a live SFU or a second identity. serde_json = "1" criterion = {version = "0.8", default-features = false, features = ["cargo_bench_support", "html_reports"]} [[bench]] name = "frame_bus" harness = false required-features = [] [[bench]] name = "camera_background" harness = false required-features = ["bench-internals"] [[bench]] name = "deep_filter" harness = false required-features = ["bench-internals"] [patch.crates-io] libwebrtc = { path = "vendor/libwebrtc" } webrtc-sys = { path = "vendor/webrtc-sys" } tract-linalg-019 = { package = "tract-linalg", path = "vendor/tract-linalg-0.19.16" } tract-linalg-023 = { package = "tract-linalg", path = "vendor/tract-linalg-0.23.1" }