From 67a5a54244068d05429a54062480f43591d0717a Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 9 Jul 2026 13:01:49 -0400 Subject: [PATCH] =?UTF-8?q?fix(voice):=20simplify=20RemoteAudioTrack=20?= =?UTF-8?q?=E2=80=94=20remove=20stale=20listener=20race?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/AudioRenderers.tsx | 35 ++++++++------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/web/src/components/AudioRenderers.tsx b/web/src/components/AudioRenderers.tsx index 2cf0df9..dac4e81 100644 --- a/web/src/components/AudioRenderers.tsx +++ b/web/src/components/AudioRenderers.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; import { useVoiceStore } from '../stores/voice.ts'; -import { Track } from 'livekit-client'; +import { Track, RoomEvent } from 'livekit-client'; import type { Participant, TrackPublication, Room } from 'livekit-client'; function RemoteAudioTrack({ participant, room }: { participant: Participant; room: Room }) { @@ -12,7 +12,7 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo let pub: TrackPublication | undefined; - const attachTrack = () => { + const attachIfReady = () => { pub = participant.getTrackPublication(Track.Source.Microphone); if (pub?.track && el) { pub.track.attach(el); @@ -20,36 +20,21 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo } }; - const detachTrack = () => { - if (pub?.track && el) { - pub.track.detach(el); - } - }; + // ponytail: check immediately — track may already be subscribed + attachIfReady(); - attachTrack(); - - const handlePublished = (publication: TrackPublication) => { - if (publication.source === Track.Source.Microphone && publication.track) { - publication.track.attach(el); - el.play().catch(() => {}); - } - }; - - room.on('trackPublished' as any, handlePublished); - - // If a track is subscribed later - const handleSubscribed = (track: Track, publication: TrackPublication, trackParticipant: Participant) => { - if (trackParticipant.identity === participant.identity && publication.source === Track.Source.Microphone) { + // ponytail: also listen for delayed subscription + const handleSubscribed = (track: Track, _pub: TrackPublication, p: Participant) => { + if (p.identity === participant.identity && _pub.source === Track.Source.Microphone) { track.attach(el); el.play().catch(() => {}); } }; - room.on('trackSubscribed' as any, handleSubscribed); + room.on(RoomEvent.TrackSubscribed, handleSubscribed); return () => { - detachTrack(); - room.off('trackPublished' as any, handlePublished); - room.off('trackSubscribed' as any, handleSubscribed); + if (pub?.track) pub.track.detach(el); + room.off(RoomEvent.TrackSubscribed, handleSubscribed); }; }, [participant, room]);