OpenNOW
Reference

WebRTC

Signaling, SDP negotiation, NVST SDP, data channels, diagnostics, and Chromium acceleration in OpenNOW

OpenNOW has two streaming clients that share Electron-owned session lifecycle and NVST signaling:

  • Web mode (streamClientMode: "web", default): the renderer owns Chromium RTCPeerConnection, media elements, data channels, stats, microphone, screenshots, and recordings.
  • Native mode (experimental on supported desktop platforms): the Rust/GStreamer child process answers the server offer and handles WebRTC media/data channels natively. Main-process signaling remains shared, and OpenNOW may fall back to web mode for executable, backend, protocol, runtime, or media capability gaps.

Source files

RoleFile
WebSocket signaling transportopennow-stable/src/main/platforms/gfn/signaling.ts
Signaling IPC coordination + native bridgeopennow-stable/src/main/signaling/signalingCoordinator.ts
Chromium startup flagsopennow-stable/src/main/index.ts, opennow-stable/src/main/videoAcceleration.ts
Renderer peer connection + inputopennow-stable/src/renderer/src/platforms/gfn/webrtcClient.ts
SDP/NVST helpersopennow-stable/src/renderer/src/platforms/gfn/sdp.ts
Codec capability diagnosticsopennow-stable/src/renderer/src/lib/codecDiagnostics.ts
Native executable/protocol lifecycleopennow-stable/src/main/nativeStreamer/manager.ts
Native input/surface helpersopennow-stable/src/main/nativeStreamer/input.ts, opennow-stable/src/main/nativeStreamer/surface.ts
Native protocol/typesopennow-stable/src/shared/nativeStreamer.ts, native/opennow-streamer/src/protocol.rs

Signaling

The main process connects to the session signaling server:

wss://{signalingServer}/nvst/sign_in?peer_id={name}&version=2
  • Subprotocol: x-nv-sessionid.{sessionId}
  • Origin: https://play.geforcenow.com
  • Heartbeat: { hb: 1 } every 5 seconds

After the peer_info init message, incoming signaling messages are classified as SDP offers, ICE candidates, or peer messages that may need ACKs. Offers and ICE are routed to the active streaming client. Answers, NVST SDP, and local ICE candidates are sent back through the same main-process signaling client.

Electron routes connect/disconnect, answer/ICE, native input, native render surface, native status, and Cloud G-Sync capability IPC through SignalingCoordinator. GfnSignalingClient remains the WebSocket transport; the coordinator decides whether incoming offers/ICE go to the renderer or native manager and sends answers/local ICE back through the client.

Renderer peer connection

In web mode, the renderer:

  1. Fixes server SDP placeholders such as 0.0.0.0 using the session server IP.
  2. Creates RTCPeerConnection with GFN ICE servers.
  3. Prefers the configured codec and normalized color quality.
  4. Sets the remote offer and creates a local answer.
  5. Waits for ICE gathering, then sends the answer plus NVST SDP.
  6. Injects the manual media endpoint candidate from mediaConnectionInfo when present.
  7. Attaches video/audio tracks to <video> and <audio> elements.

Native answer path

In experimental native mode, SignalingCoordinator sends the server offer to the Rust child through NativeStreamerManager with an offer command. The GStreamer backend uses webrtcbin to create the local answer and emits local ICE as protocol events. Electron still sends the answer and ICE through GfnSignalingClient, so CloudMatch, signaling auth, and session teardown stay centralized.

NVST SDP

OpenNOW sends standard WebRTC SDP plus an NVIDIA NVST SDP blob. NVST SDP carries stream-quality attributes such as resolution, viewport, FPS, bitrate, codec, color quality, QoS/FEC, bandwidth estimation, and ICE credentials.

The NVST session describes these m-lines:

m-lineDirectionPurpose
videoreceive-onlyCloud GPU video RTP
audioreceive-onlyGame audio
micsend-onlyMicrophone audio when enabled
applicationbidirectionalInput data channels

Data channels

ChannelReliabilityTraffic
input_channel_v1ordered, reliableKeyboard and control messages
input_channel_partially_reliableunordered, partially reliableMouse deltas and gamepad state

The partially reliable threshold is read from the negotiated a=ri.partialReliableThresholdMs SDP attribute. Native mode creates compatible data channels in the child process and reports input-ready before Electron sends native input packets.

Diagnostics

Renderer WebRTC diagnostics poll RTCPeerConnection.getStats() for connection state, codec, resolution, HDR/color, bitrate, RTT, jitter, packet loss, frame decode/render timing, data-channel pressure, lag classification, and microphone state.

The Settings codec diagnostics use Chromium mediaCapabilities plus WebRTC codec probing to show whether H.264, H.265, and AV1 decode/encode are available and whether the browser reports GPU-backed acceleration. Results are cached in session storage for the current renderer session. On Linux, OpenNOW shows an extra hint when diagnostics are software-only or H.265 is unavailable: AppImage diagnostics still depend on the host distro's VA-API stack, so proprietary NVIDIA systems may need libva-nvidia-driver/nvidia-vaapi-driver and distro codec packages even though OpenNOW enables NVIDIA VA-API flags on restart.

Native mode emits protocol events instead: status, input-ready, shortcut, video-stall, video-transition, stats, log, and error. See Native Streamer for experimental status, event fields, issue reporting, and fallback behavior.

Chromium acceleration flags

At startup the main process configures Chromium/WebRTC for the renderer path:

PlatformCurrent acceleration behavior
WindowsD3D11 video decode and Media Foundation integration
Linux x64VA-API decoder/encoder flags with driver checks relaxed, Linux GL accelerated decode, zero-copy GL decode, accelerated encode, and NVIDIA VA-API enablement
Linux ARMV4L2/direct decoder flags
macOSNative VideoToolbox path
AllMP4 MediaRecorder support, dav1d AV1 fallback, disabled mDNS candidates, unthrottled renderer/background behavior

decoderPreference and encoderPreference are read before Electron startup. hardware adds the corresponding force-enable Chromium switch, software adds the corresponding disable switch, and auto leaves Chromium to choose while still enabling the platform feature set. ignore-gpu-blocklist is always set so the GPU process does not silently blocklist available video acceleration.

These flags affect the renderer WebRTC path. Native mode uses the GStreamer platform paths documented in Native Streamer.

On this page

On this page