lvqr-cli 1.1.0

LVQR single binary entry point
[package]
name = "lvqr-cli"
description = "LVQR single binary entry point"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
authors.workspace = true
keywords = ["streaming", "server", "quic", "moq"]
categories = ["multimedia", "network-programming", "command-line-utilities"]

[lib]
name = "lvqr_cli"
path = "src/lib.rs"

[[bin]]
name = "lvqr"
path = "src/main.rs"

[features]
default = ["rtmp", "quinn-transport", "cluster"]
full = ["rtmp", "quinn-transport", "cluster", "c2pa", "whisper", "transcode", "jwks", "webhook"]
# PLAN row 120: JWKS dynamic key discovery. Adds `--jwks-url` + companion
# flags to `lvqr serve` and pulls reqwest + tokio::spawn into the auth
# layer via `lvqr-auth/jwks`. Off by default so `cargo install lvqr-cli`
# stays lean; operators opt in via `--features jwks` or `--features full`.
jwks = ["lvqr-auth/jwks"]
# PLAN Phase D: webhook auth provider. Adds `--webhook-auth-url` + companion
# TTL / timeout flags and pulls reqwest + tokio::spawn into the auth layer
# via `lvqr-auth/webhook`. Off by default; included in `--features full`.
webhook = ["lvqr-auth/webhook"]
rtmp = ["lvqr-ingest/rtmp"]
quinn-transport = ["lvqr-relay/quinn-transport"]
# Enables cluster-mode CLI flags + bootstrap in `start()`. Disabled
# deployments fall back to the single-node path.
cluster = ["dep:lvqr-cluster"]
# Tier 4 item 4.3 session B3: enables the `/playback/verify/{broadcast}`
# admin route, plumbs `C2paConfig` through `ServeConfig`, and wires
# `lvqr_archive::provenance::finalize_broadcast_signed` into the drain-
# task termination path. Default off so operators without a provenance
# requirement do not link the c2pa-rs transitive closure.
c2pa = ["lvqr-archive/c2pa", "dep:c2pa"]
# Tier 4 item 4.5 session D: enables the `--whisper-model <PATH>` CLI
# flag, plumbs the model path through `ServeConfig`, and installs a
# `WhisperCaptionsFactory` + `AgentRunner` on the shared fragment
# registry inside `start()`. Default off so `cargo install lvqr-cli`
# does not pull `whisper-rs` (bindgen + cmake against whisper.cpp) or
# `symphonia` into the default build path.
whisper = [
    "dep:lvqr-agent",
    "dep:lvqr-agent-whisper",
    "lvqr-agent-whisper/whisper",
    "lvqr-test-utils/whisper",
]
# Tier 4 item 4.6 session 105 B: pulls `lvqr-transcode/transcode` into the
# build. `lvqr-cli` does not yet wire `SoftwareTranscoderFactory` into the
# composition root (that lands in session 106 C together with the
# `--transcode-rendition` flag and the LL-HLS master playlist composition);
# the feature lives here in 105 B so `cargo build -p lvqr-cli --features full`
# exercises the GStreamer dep graph on CI the moment an operator opts in.
# Session 113 also activates `lvqr-whep/aac-opus` so the AAC-to-Opus
# encoder factory is available to the composition root when the operator
# opts into the same GStreamer runtime dep.
transcode = [
    "dep:lvqr-transcode",
    "lvqr-transcode/transcode",
    "lvqr-test-utils/transcode",
    "lvqr-whep/aac-opus",
]
# Tier 4 item 4.6 session 156: forwards the `hw-videotoolbox` feature
# from `lvqr-transcode` so a binary built with this flag exposes the
# `--transcode-encoder videotoolbox` CLI value. Implies `transcode`
# (the new module reuses gstreamer-rs); macOS-only by element
# requirement (`vtenc_h264_hw` lives in `applemedia` from gst-plugins-bad).
hw-videotoolbox = ["transcode", "lvqr-transcode/hw-videotoolbox"]
# Linux + Nvidia GPU HW encoder backend. Implies `transcode`; the
# `nvh264enc` element comes from the `nvcodec` plugin in
# `gst-plugins-bad` and probes the CUDA runtime + driver at element-
# factory load time.
hw-nvenc = ["transcode", "lvqr-transcode/hw-nvenc"]
# Linux + Intel iGPU / AMD HW encoder backend via VA-API. Implies
# `transcode`; the `vah264enc` element comes from the modern `va`
# plugin in `gst-plugins-bad` and probes libva + a usable DRI device
# at element-factory load time.
hw-vaapi = ["transcode", "lvqr-transcode/hw-vaapi"]
# Linux + Intel Quick Sync HW encoder backend. Implies `transcode`;
# the `qsvh264enc` element comes from the `qsv` plugin in
# `gst-plugins-bad` and probes Intel Media SDK / oneVPL at element-
# factory load time.
hw-qsv = ["transcode", "lvqr-transcode/hw-qsv"]

[dependencies]
lvqr-core = { workspace = true }
lvqr-relay = { workspace = true }
lvqr-moq = { workspace = true }
moq-lite = { workspace = true }
lvqr-mesh = { workspace = true }
lvqr-ingest = { workspace = true }
lvqr-signal = { workspace = true }
lvqr-admin = { workspace = true }
lvqr-auth = { workspace = true, features = ["jwt"] }
lvqr-record = { workspace = true }
lvqr-fragment = { workspace = true }
lvqr-codec = { workspace = true }
lvqr-cmaf = { workspace = true }
lvqr-hls = { workspace = true }
lvqr-dash = { workspace = true }
lvqr-whep = { workspace = true }
lvqr-whip = { workspace = true }
lvqr-archive = { workspace = true }
lvqr-rtsp = { workspace = true }
lvqr-srt = { workspace = true }
lvqr-cluster = { workspace = true, optional = true }
lvqr-observability = { workspace = true }
lvqr-wasm = { workspace = true }
# Feature-gated on `c2pa`; exposes `c2pa::Reader` in the admin verify
# route. Inherited from the workspace so the lockfile-level pin tracks
# lvqr-archive's.
c2pa = { workspace = true, optional = true }
# Feature-gated on `whisper`; `start()` builds a
# `WhisperCaptionsFactory` + `AgentRunner` on the shared fragment
# registry so the captions track the HLS subtitle rendition consumes
# has a live producer. Without the feature neither dep links at all
# and the `--whisper-model` flag is absent from the CLI.
lvqr-agent = { workspace = true, optional = true }
lvqr-agent-whisper = { workspace = true, optional = true }
# Feature-gated on `transcode`. Adding the dep here lets the `full`
# meta-feature activate `lvqr-transcode/transcode` from a single flag;
# `start()` does not yet install a `TranscodeRunner` (session 106 C).
lvqr-transcode = { workspace = true, optional = true }

axum = { workspace = true }
bytes = { workspace = true }
dashmap = { workspace = true }
tower-http = { workspace = true }
clap = { workspace = true }
toml = { workspace = true }
tokio = { workspace = true, features = ["full", "signal"] }
tokio-util = { workspace = true }
futures = { workspace = true }
metrics = { workspace = true }
metrics-exporter-prometheus = { workspace = true }
metrics-util = { workspace = true }
rcgen = { workspace = true }
rustls = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
anyhow = { workspace = true }
# Mutex for ConfigReloadHandle's last-reload state (session 147).
# parking_lot avoids std-Mutex poisoning + matches the rest of the
# workspace's locking conventions.
parking_lot = { workspace = true }
# Swappable handles for hot config reload v2 (session 148): the mesh
# ICE list and HMAC playback secret are atomically replaced via
# `ArcSwap` so the signal callback and live-playback middleware can
# `load_full` per call without holding a lock.
arc-swap = { workspace = true }

# Signed playback URLs (PLAN row 121). hmac + sha2 implement the
# HMAC-SHA256 primitive; base64 encodes the signature for the
# query string; subtle gives constant-time comparison so verify
# has no timing oracle.
hmac = { workspace = true }
sha2 = { workspace = true }
base64 = { workspace = true }
subtle = { workspace = true }

[dev-dependencies]
# Real RTMP client for the RTMP -> WS E2E test.
rml_rtmp = { workspace = true }
# WebSocket client for the RTMP -> WS E2E test.
tokio-tungstenite = "0.24"
# SRT client for the SRT -> HLS E2E test.
srt-tokio = "0.4"
futures-util = "0.3"
tracing-subscriber = { workspace = true }
tower = { workspace = true }
http = "1"
# Full-stack TestServer for auth_integration.rs. The `c2pa` feature
# is opt-in from the `lvqr-cli/c2pa` feature union: Tier 4 item 4.3
# session B3's `c2pa_verify_e2e.rs` test uses `TestServerConfig::
# with_c2pa(..)`, which is gated on `lvqr-test-utils/c2pa`. Activating
# it here keeps the dev-dep feature unified with the lvqr-cli feature
# flag when `cargo test -p lvqr-cli --features c2pa` runs, and is a
# no-op in default builds because dev-dependencies only resolve during
# test target compilation.
lvqr-test-utils = { workspace = true, features = ["c2pa"] }
# JWT minting in auth_integration.rs. Matches the version pulled in
# transitively through `lvqr-auth/jwt`.
jsonwebtoken = { workspace = true }
serde_json = { workspace = true }
tempfile = "3"
# Federation two-cluster E2E test opens a real MoQ client against the
# second TestServer and reads announcements; it also names
# `FederationLink` to construct the config. Both are dev-only.
lvqr-cluster = { workspace = true }
moq-native = { workspace = true }
url = { workspace = true }
# Session 114 row 1: WHIP->HLS E2E test drives a real str0m client
# against the CLI-hosted WHIP surface. Dev-only; matches the pin in
# `lvqr-whep`'s dependency graph (0.18).
str0m = "0.18"