Skip to content

IACBI/lancast

Repository files navigation

English · Türkçe

LANCast

CI License: MIT OR Apache-2.0

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.


Highlights

  • 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.

How it works

        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.

Requirements

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).

Quick start

1. Install GStreamer (both machines)

Install the MSVC x86_64, Complete build so the nvcodec and wasapi2 plugins plus the development files are present. Either:

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"

2. Install Rust

From https://www.rust-lang.org/tools/install (MSVC host).

3. Configure lancast.toml

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 live

Resolution, fps, bitrate, buffer sizes, and the encoder preset all live here too. Every value is commented in the file.

4. Build & run

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.toml

Without --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.

Self-test (one machine, headless)

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).

Reading the live stats

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: fps reads low/wobbly because the pre-sink queue drops under coarse timing — treat steady kbps and low dropped as the reliable health signals.

For everything you can turn — buffers, encoder preset, GOP/keyframes, bitrate, drift — see the Tuning guide.

What LANCast is — and isn't

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.

Project layout

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

License

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).

About

Point-to-point ultra-low-latency screen+audio streaming for 1 gaming PC -> 1 streaming PC over a wired LAN (NVENC/NVDEC + GStreamer, Rust)

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages