Skip to content

WebRtcUrlConfig.position is declared in types but never read — archive playback silently falls back to live #2

Description

@revz143

Package: @networkoptix/webrtc-stream-manager@0.1.29

WebRtcUrlConfigUnknown declares position?: number (dist/types/types.d.ts), but the implementation never reads it. StreamManager.buildSignalingUrl only appends positionMs= from the singleton-global _currentPosition (set via StreamManager.updatePosition()):

// dist/lib/core/stream-manager.js (buildSignalingUrl)
if (this._currentPosition) {
    params.push(`positionMs=${this._currentPosition}`);
}

A grep of dist/lib for urlConfig.position / config.position returns zero hits. So passing position on the connect config compiles fine and silently produces a live stream.

Steps to reproduce

const connection = StreamManager.getInstance().connect({
  systemId, cameraId, accessToken,
  apiVersion: ApiVersions.v2,
  targetStream: TargetStream.AUTO,
  position: 1712345678000, // epoch ms, in the past, footage exists
}, videoElement);

Expected: archive playback from the given position (v1 behavior — position was baked into the signaling URL).

Actual: live stream; signaling URL contains no positionMs.

Why the global workaround is insufficient

StreamManager.updatePosition() is process-global while the signaling URL is rebuilt lazily per connection attempt, including internal retries. With concurrent players (e.g. a live grid plus an archive dialog), any live connection that retries while the global is set reconnects into archive — and clearing the global after connect makes the archive connection's own retries come back live. Per-connection position is not expressible.

The post-connect path also can't cover the initial position: connect() applies _currentPosition via connection.updatePosition() immediately after construction, but sendSeek silently no-ops until the data channel is open.

Suggested fix

In buildSignalingUrl, honor the per-connection config with the global as fallback:

const positionMs = urlConfig.position ?? this._currentPosition;
if (positionMs) {
    params.push(`positionMs=${positionMs}`);
}

The closure in connect() already captures urlConfig per connection, so retries keep the correct per-connection position. We're running exactly this as a local patch and can confirm it restores archive playback.

Environment

  • @networkoptix/webrtc-stream-manager 0.1.29 (v2 native API)
  • Playback via cloud relay ({systemId}.relay.vmsproxy.com), useRelayPrefix: false
  • Chrome / Edge (Chromium)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions