English · Türkçe
Point-to-point, ultra-low-latency screen + audio streaming for one gaming PC → one streaming PC over a wired LAN.
LANCast does one thing and tries to do it better than anything general-purpose: mirror a gaming PC's screen and its game audio onto a second Windows PC, on the same 100 Mbps wired network, with the lowest possible glass-to-glass latency and rock-solid A/V sync. It is not a general NDI replacement — it deliberately throws away discovery, multi-source, scaling, and format negotiation, and over-optimizes for this single fixed setup.
If your situation is different (multiple sources, the open internet, non-NVIDIA GPUs), NDI or OBS+NDI will serve you better. LANCast only wins inside the narrow box it was built for.
- Latency-first transport. Hardware NVENC H.264 (no B-frames, ultra-low-latency tune) over RTP with a tiny 1–2 frame jitter buffer. Capped CBR keeps the 100 Mbps link from saturating, which is the real source of queuing latency.
- A/V sync by construction. Audio and video are stamped from a single sender clock and
carried as two RTP streams synchronized by RTCP. The receiver slaves its clock to the sender's
over the network (
GstNetClientClock), so the two machines share one timeline and audio never drifts away from video over a long session. - First-class game audio. System/game audio is captured with WASAPI loopback and encoded with Opus — not an afterthought bolted on next to the video.
- Resilient, not fragile. Packet loss triggers an on-demand keyframe via RTCP PLI, so a dropped frame self-heals without forcing a periodic-keyframe bitrate spike.
- Built-in instrumentation. The receiver prints live bitrate, fps, A/V offset and its drift, and dropped frames — so you can A/B it against OBS+NDI on your own hardware.
Gaming PC (sender) Streaming PC (receiver)
┌─────────────────────────────┐ ┌──────────────────────────────┐
│ D3D11 screen capture ─┐ │ │ ┌─► NVDEC H.264 ─► display │
│ ├─NVENC├── RTP video ──────┼───┤ (rtpbin: RTCP-synced) │
│ WASAPI loopback ──Opus┘ │ RTP audio │ └─► Opus decode ─► speakers│
│ shared sender clock ────────┼── net clock ───────┼─► slaved clock (drift corr.) │
└─────────────────────────────┘ RTCP/PLI ◄───────┴──────────────────────────────┘
Both media are timestamped against one sender clock (common PTS). The receiver presents them against that same timeline with a deliberately tiny buffer; if a video frame is late or lost, audio keeps playing on the shared clock and re-syncs instead of drifting.
| Topology | Exactly one sender and one receiver. Addresses come from a config file — no discovery. |
| OS | Windows on both machines. |
| GPU | NVIDIA with NVENC (encode, sender) and NVDEC (decode, receiver). Developed/verified on an RTX 3050 Ti Laptop GPU. |
| Network | Both wired to the same router; ~100 Mbps. Encode target stays ~20–40 Mbps to leave headroom. |
| Toolchain | Rust (stable ≥ 1.74) and GStreamer 1.28.x (MSVC x86_64). |
Install the MSVC x86_64, Complete build so the nvcodec and wasapi2 plugins plus the
development files are present. Either:
winget install gstreamerproject.gstreamer— installs to%LOCALAPPDATA%\Programs\GStreamer\1.0\msvc_x86_64, or- the Complete installer from https://gstreamer.freedesktop.org/download/.
Point your shell at it (adjust the root to your install path):
$env:GSTREAMER_1_0_ROOT_MSVC_X86_64 = "$env:LOCALAPPDATA\Programs\GStreamer\1.0\msvc_x86_64"
$env:PATH = "$env:GSTREAMER_1_0_ROOT_MSVC_X86_64\bin;$env:PATH"
$env:PKG_CONFIG_PATH = "$env:GSTREAMER_1_0_ROOT_MSVC_X86_64\lib\pkgconfig"From https://www.rust-lang.org/tools/install (MSVC host).
The same file is used on both machines. At minimum set the two LAN IPs (find them with
ipconfig):
[network]
receiver_ip = "192.168.1.50" # streaming PC — where video/audio is sent
sender_ip = "192.168.1.40" # gaming PC — where the net clock + RTCP liveResolution, fps, bitrate, buffer sizes, and the encoder preset all live here too. Every value is commented in the file.
Start the receiver first, then the sender:
# Streaming PC (receiver):
cargo run --release --features pipeline --bin lancast-receiver -- --config lancast.toml
# Gaming PC (sender):
cargo run --release --features pipeline --bin lancast-sender -- --config lancast.tomlWithout
--features pipeline, the apps run a dry run: they validate the config and print the exact GStreamer pipeline they would launch, without needing GStreamer installed. Handy for editing config on any machine.
Verify the whole chain on a single PC without touching your screen or speakers — synthetic video/
audio in, fakesink out:
cargo build --features pipeline -p lancast-sender -p lancast-receiver
# In lancast.toml set receiver_ip and sender_ip to 127.0.0.1, then:
.\target\debug\lancast-sender.exe --test-pattern --seconds 16 # start first
.\target\debug\lancast-receiver.exe --test-pattern --seconds 14--test-pattern swaps real capture/sinks for synthetic ones; --seconds N auto-stops. To
exercise loss recovery, add --simulate-drop 0.02 to the receiver (drops 2% of video packets via
netsim; watch the kf counter climb as PLI pulls fresh keyframes).
The receiver prints one line per second:
[receiver] 30300 kbps 54.0 fps kf 1 A/V +6.9ms drift -0.04ms/min dropped 0
| Field | Meaning |
|---|---|
kbps |
Received video bitrate — should sit at your configured CBR target. |
fps |
Frames presented (post buffer; see caveat below). |
kf |
Keyframes into the decoder per second (jumps when PLI recovers from loss). |
A/V |
Smoothed audio↔video offset. Target: a few ms, stable. |
drift |
Trend of that offset. The key long-session metric — should stay ≈ 0. |
dropped |
Buffers dropped late at the sinks. |
Caveat:
fpsreads low/wobbly because the pre-sink queue drops under coarse timing — treat steadykbpsand lowdroppedas the reliable health signals.
For everything you can turn — buffers, encoder preset, GOP/keyframes, bitrate, drift — see the Tuning guide.
It can beat OBS+NDI here on: glass-to-glass latency, A/V sync tightness, and (likely) sender GPU/CPU overhead, for this exact 1:1 wired-LAN setup.
It will not beat them on: robustness under heavy loss, multi-source, discovery/ease of use, or anything outside the fixed scenario. Those are conscious trade-offs, not bugs.
crates/lancast-core/ config parsing/validation, pipeline builders, stats (no GStreamer dep)
crates/lancast-sender/ gaming PC app: capture + NVENC + WASAPI/Opus + RTP TX
crates/lancast-receiver/ streaming PC app: RTP RX + NVDEC + audio + synced playback + drift corr.
lancast.toml the single shared config
TUNING.md how to trade latency / sync / robustness
Licensed under either of Apache-2.0 or MIT at your option. Unless you state otherwise, contributions you submit are dual-licensed the same way.
Dependencies & codecs. LANCast's source is the Rust code in this repo; it does not bundle
GStreamer — you install it separately and LANCast links to it at runtime. The gstreamer-rs
bindings are MIT/Apache-2.0; the GStreamer C libraries are LGPL (some plugins have other terms).
H.264 is patent-encumbered; encoding/decoding uses your NVIDIA hardware, and you are responsible
for any codec patent licensing that applies to your use (especially commercial use).