Context
Currently the StatsBar shows latency as two segments: Robot→Server (using robot.pingMs — socket.io ping to NestJS) and Server→Web (WebRTC RTT from browser getStats()).
The Robot→Server value is an approximation: it measures the socket.io ping to NestJS, not the actual WHIP stream path to MediaMTX. In prod they're co-located so it's close, but not exact.
Options considered
Option A — HTTP ping to MediaMTX (simple)
Periodically GET /v3/paths/robot/{id}/video on the MediaMTX API from the robot and measure response time. Add as a telemetry field (e.g. streamPingMs). No change to the streaming pipeline.
Pros: trivial to implement, no new dependencies
Cons: HTTP overhead ≠ WebRTC path, approximation
Option B — Replace ffmpeg WHIP with node-webrtc (thorough)
Use @roamhq/wrtc to handle the WebRTC transport layer directly, exposing getStats() for true RTT measurement — same approach as the browser side.
Pros: accurate RTT, lower buffering latency, unified ICE/TURN control
Cons: ARM build support uncertain on Pi, ffmpeg still needed for capture + encoding, significant refactor
Recommendation
Start with Option A as a quick win. Revisit Option B if stream latency accuracy becomes a priority or if we overhaul the video pipeline.
Web side reference
web/src/features/stream/ — uses RTCPeerConnection.getStats() to extract roundTripTime from ICE candidate stats, reported to useVideoStatsStore.
Context
Currently the StatsBar shows latency as two segments: Robot→Server (using
robot.pingMs— socket.io ping to NestJS) and Server→Web (WebRTC RTT from browsergetStats()).The Robot→Server value is an approximation: it measures the socket.io ping to NestJS, not the actual WHIP stream path to MediaMTX. In prod they're co-located so it's close, but not exact.
Options considered
Option A — HTTP ping to MediaMTX (simple)
Periodically
GET /v3/paths/robot/{id}/videoon the MediaMTX API from the robot and measure response time. Add as a telemetry field (e.g.streamPingMs). No change to the streaming pipeline.Pros: trivial to implement, no new dependencies
Cons: HTTP overhead ≠ WebRTC path, approximation
Option B — Replace ffmpeg WHIP with
node-webrtc(thorough)Use
@roamhq/wrtcto handle the WebRTC transport layer directly, exposinggetStats()for true RTT measurement — same approach as the browser side.Pros: accurate RTT, lower buffering latency, unified ICE/TURN control
Cons: ARM build support uncertain on Pi, ffmpeg still needed for capture + encoding, significant refactor
Recommendation
Start with Option A as a quick win. Revisit Option B if stream latency accuracy becomes a priority or if we overhaul the video pipeline.
Web side reference
web/src/features/stream/— usesRTCPeerConnection.getStats()to extractroundTripTimefrom ICE candidate stats, reported touseVideoStatsStore.