Files
qortal-go-2.0/docs/group-call-v2-post-cutover-roadmap.md

118 lines
4.7 KiB
Markdown

# Group Call Audio V2 — Post-Cutover Upgrade Roadmap
This document tracks architectural improvements that become available AFTER the
v2 architecture (control plane, receive engine, policy FSM, decode service, replay
harness) is fully in production and all legacy paths have been deleted.
These are NOT blockers for the cutover. They are evaluated after the v2 baseline
is stable and the regression fixture suite passes.
---
## 1. Native Reticulum-level improvements
**Motivation:** Phil had `reticulumAudioPacketPathTimeouts` = 11.9% (vs Kenny's 3.9%).
Path resolution failures at the Reticulum layer cannot be fixed by the v2 policy FSM —
they require changes at the network/routing level.
**Candidates:**
- Reticulum path pre-caching: resolve and cache paths for known group call peers
before they are needed, so the first post-join packet doesn't trigger resolution.
- Reduce path resolution timeout from the current default to 2s for audio peers.
- Evaluate Reticulum-native multicast for group audio fanout to eliminate the
application-level fanout hop.
**Gate:** Requires Reticulum Python daemon changes. Out of scope for the JavaScript
v2 architecture; file separate issues against `reticulum-daemon.ts`.
---
## 2. Native Opus decode via WASM / Emscripten
**Motivation:** The current `WebCodecs AudioDecoder` path does not expose PLC (packet
loss concealment) beyond silence fill. The WASM Opus decoder has a proper `decode_loss`
API that produces plausible audio for gaps.
**Plan:**
- Integrate the WASM libopus decoder as a `IDecodeService` implementation alongside
`WebCodecsDecodeService`.
- The `DecodeService` factory selects WASM when `AudioDecoder` is not available, or
when the caller requests the WASM path explicitly (e.g. for PLC quality).
- Evaluate whether `gcall-opus-fec.worker.ts` can be retired in favor of the unified
`IDecodeService` interface.
---
## 3. Opaque relay / fanout optimization
**Motivation:** Root forwarders today decrypt-and-reencrypt. For large rooms this is
wasteful: the forwarder could relay the already-encrypted bytes opaquely.
**Plan:**
- The `ReticulumSessionController` should emit a `canRelayOpaque` flag per stream
once the topology is stable. When true, the forwarder skips decrypt/reencrypt and
forwards the wire bytes directly.
- The `ReceiveEngine` should accept opaque relay packets and dispatch them without
involving the `DecodeService`.
- This requires the wire format to carry enough routing metadata outside the secretbox
so the forwarder can route without decrypting.
---
## 4. SharedArrayBuffer playout bridge
**Motivation:** The current PCM ring lives on the main thread. The playout worklet
reads from it via `postMessage`, which adds one message-queue hop of latency.
**Plan:**
- Export the `PerSourcePcmRing`'s internal `Float32Array` as a `SharedArrayBuffer`.
- The playout worklet reads directly from the SAB with `Atomics`-based fill tracking.
- Eliminates the main-thread ↔ worklet round trip for PCM delivery.
**Gate:** Requires COOP/COEP headers (`Cross-Origin-Opener-Policy: same-origin`,
`Cross-Origin-Embedder-Policy: require-corp`). Verify Electron's context isolation
configuration supports this.
---
## 5. Multi-party jitter and FEC tuning
**Motivation:** The `DEFAULT_POLICY_CONFIG` targets 1:1 calls (the call-63 scenario).
For 3+ participants, `targetBufferMs` should be higher and `backlogDrainTriggerRatio`
may need adjustment.
**Plan:**
- The `GcallV2Session` or `ReceivePolicyEngine` should accept a `participantCount`
signal and scale `targetBufferMs` accordingly.
- For N ≥ 3, consider enabling WASM FEC in the `DecodeService` factory.
---
## 6. Replay harness CI integration
**Motivation:** The regression fixture tests currently run in Jest with simulated
time. They should also run in a headless Electron instance to catch Electron-specific
scheduling artifacts (the tick budget breaches from the Phil scenario are
Electron/WebAudio scheduling artifacts).
**Plan:**
- Add a `npm run replay:ci` target that runs `replayHarness.test.ts` in a headless
Electron context.
- Use `electron-mocha` or `playwright` with `@playwright/test`'s Electron driver.
- Make this a required CI step before any group-call PR merges.
---
## 7. Paired export upload / comparison tool
**Motivation:** Today, comparing paired exports requires manual JSON archaeology.
The `PairedExportAnalyzer` automates classification, but the exports still need to
be collected manually.
**Plan:**
- Add an in-app "Share call diagnostics" button that exports a bundle and optionally
uploads it to a diagnostics endpoint.
- The endpoint stores paired exports keyed by `roomId + exportedAtMs` so the analyzer
can fetch both peers' exports automatically.
- Surface the `PairedAnalysisResult.callSummary` in the UI for QA triage.