[fix](trx-frontend-http): fix virtual channel audio streaming
Three bugs prevented vchan audio from working reliably: 1. vchan.js: `vchanReconnectAudio` returned before updating `_audioChannelOverride` when audio was inactive. Switching to a virtual channel with audio off then starting audio manually would connect to the primary channel instead. Move the override update before the rxActive guard so it always reflects the active channel. 2. audio.rs: `audio_ws` returned 404 immediately if the channel was not yet in `vchan_audio`. The entry is populated when `AUDIO_MSG_VCHAN_ALLOCATED` arrives from the audio TCP client, which can lag the HTTP allocation by up to ~100 ms. Replace the instant 404 with a 2-second polling loop (50 ms intervals) so the WebSocket upgrade waits for the channel to be ready. 3. vchan.rs: `release_session_on_rig` evicted zero-subscriber channels silently — no `VChanAudioCmd::Remove` was sent. Collect evicted channel IDs before retain() and send Remove commands so the server-side DSP pipeline and Opus encoder are torn down properly on session disconnect. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -170,19 +170,23 @@ async function vchanSubscribe(channelId) {
|
||||
// Reconnect the audio WebSocket to the appropriate endpoint:
|
||||
// - virtual channel: /audio?channel_id=<uuid>
|
||||
// - primary channel: /audio (no param)
|
||||
// Only reconnects if RX audio is currently active.
|
||||
// Always updates _audioChannelOverride so that starting audio later
|
||||
// connects to the correct channel. Only reconnects if RX audio is active.
|
||||
function vchanReconnectAudio() {
|
||||
if (typeof rxActive === "undefined" || !rxActive) return;
|
||||
// Set the channel override so startRxAudio picks up the right URL.
|
||||
// Always update the override so startRxAudio picks up the right URL,
|
||||
// even when audio isn't currently running.
|
||||
const ch = vchanIsOnVirtual() ? vchanActiveChannel() : null;
|
||||
if (typeof _audioChannelOverride !== "undefined") {
|
||||
_audioChannelOverride = ch ? ch.id : null;
|
||||
}
|
||||
if (typeof rxActive === "undefined" || !rxActive) return;
|
||||
if (typeof stopRxAudio === "function") stopRxAudio();
|
||||
// Small delay so the server has time to set up the per-channel encoder.
|
||||
// Delay so the server has time to set up the per-channel encoder.
|
||||
// The server-side audio_ws handler also polls for up to 2 s, so this
|
||||
// just needs to be long enough for the WS upgrade to reach the server.
|
||||
setTimeout(() => {
|
||||
if (typeof startRxAudio === "function") startRxAudio();
|
||||
}, 200);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Called by app.js from applyCapabilities().
|
||||
|
||||
Reference in New Issue
Block a user