LensLink

Latency and performance

Roughly 60 ms camera to OBS over USB, at 1080p or 4K; Wi-Fi is higher and more variable. The figure is measured continuously, not estimated, and shown in the Status field, the status bar and the log.

Where the delay comes from#

StageRoughlyNotes
Capture and exposureOne frameBrighter scenes expose faster, and it shows up here.
Hardware encodeA few msVideoToolbox. Nothing to tune.
The linkUSB: small, steady. Wi-Fi: variableThe stage that separates a good setup from a frustrating one.
DecodeA few msGPU by default, software fallback automatic.
Into your sceneSub-millisecond on the GPU pipelineOtherwise a copy out of GPU memory and back.

Lowering it#

  1. Use USB. Most consistent, immune to Wi-Fi congestion, and it charges the phone.
  2. Light the scene. A dark room lengthens exposure, and that lands straight in the latency budget.
  3. Leave the defaults on. Low latency mode and hardware decoding both ship enabled.
  4. Don't over-specify. If the shot is a talking head 1000 px wide in your scene, 1080p is not a compromise.
  5. Use the telephoto rather than heavy digital zoom. Zoomed, noisy video compresses badly, which shows up as bitrate and latency spikes.

Congestion is dropped, not queued. When the link stalls, LensLink drops frames and briefly lowers quality rather than building a backlog, so latency stays flat instead of drifting up through a stream.

Watching the numbers#

The figure is real: an NTP-style clock-offset exchange runs once a second, which is also what makes automatic lip sync possible.

The GPU decode pipeline (beta)#

Normally each decoded frame is downloaded from the GPU into system memory, handed to OBS, and uploaded straight back for compositing — about 2 GB/s of pixels at 4K60, for nothing. The beta pipeline hands OBS the frame as a texture and skips the round trip.

Tools → LensLink Settings. All sources switch together, after an OBS restart.

Measured results#

Twelve configurations, ~25 s of live video each, same PC and phone over Wi-Fi. Pixel copies read 0.00 MB/s on every GPU-pipeline run.

ConfigCost per frame (ms)Pixel copies (MB/s)OBS CPU
720p 60 HEVC0.81 → 0.09163 → 02.2% → 1.4%
1080p 60 H.2642.11 → 0.10370 → 02.3% → 1.6%
1080p 60 HEVC1.42 → 0.09373 → 02.6% → 1.4%
4K 30 HEVC4.96 → 0.14721 → 02.9% → 1.5%
4K 60 H.2647.54 → 0.101221 → 04.1% → 1.8%
4K 60 HEVC4.75 → 0.101439 → 04.1% → 1.6%

Per-frame cost drops 89–99%, and the win scales with resolution: at 4K60 HEVC the standard pipeline pushed about 1.4 GB/s through system memory, which this removes outright, roughly halving OBS's process CPU. Latency and frame rate showed no systematic difference — they are set by the network and the phone's encoder, not the render path.

Platform notes#

WindowsAny OBS 32-supported system (Windows 10 1909+), using shared D3D11 textures.
macOSAny OBS 32-supported system (macOS 13+), via IOSurface.
LinuxNeeds OBS on EGL (the default on Wayland and current X11 builds) and a VAAPI driver — built into Mesa for Intel and AMD; NVIDIA needs nvidia-vaapi-driver.
Multi-GPUDecoding and rendering on different GPUs can't share textures; the source falls back automatically.

Fallback is per source and automatic: the worst case is exactly the standard pipeline, with a log line saying why.

Measuring it yourself#

Tools → LensLink Settings → Record pipeline benchmark writes one CSV row per second into the plugin's config folder (path in the log), plus a summary every five seconds. Stream ten seconds on each configuration, then compare a pair:

python3 tools/bench-report.py BEFORE.csv AFTER.csv

Any performance change proposed to LensLink is expected to quote one of these.