diff --git a/packages/client/src/helpers/AudioBindingsWatchdog.ts b/packages/client/src/helpers/AudioBindingsWatchdog.ts index c2a2c31591..d331748054 100644 --- a/packages/client/src/helpers/AudioBindingsWatchdog.ts +++ b/packages/client/src/helpers/AudioBindingsWatchdog.ts @@ -3,6 +3,7 @@ import { CallingState, CallState } from '../store'; import { createSubscription } from '../store/rxUtils'; import { videoLoggerSystem } from '../logger'; import { Tracer } from '../stats'; +import { TrackType } from '../gen/video/sfu/models/models'; const toBindingKey = ( sessionId: string, @@ -91,12 +92,23 @@ export class AudioBindingsWatchdog { const danglingUserIds: string[] = []; for (const p of this.state.participants) { if (p.isLocalParticipant) continue; - const { audioStream, screenShareAudioStream, sessionId, userId } = p; - if (audioStream && !this.bindings.has(toBindingKey(sessionId))) { + const { + audioStream, + screenShareAudioStream, + sessionId, + userId, + publishedTracks, + } = p; + if ( + audioStream && + publishedTracks.includes(TrackType.AUDIO) && + !this.bindings.has(toBindingKey(sessionId)) + ) { danglingUserIds.push(userId); } if ( screenShareAudioStream && + publishedTracks.includes(TrackType.SCREEN_SHARE_AUDIO) && !this.bindings.has(toBindingKey(sessionId, 'screenShareAudioTrack')) ) { danglingUserIds.push(userId); diff --git a/packages/client/src/helpers/__tests__/AudioBindingsWatchdog.test.ts b/packages/client/src/helpers/__tests__/AudioBindingsWatchdog.test.ts index 3bbdd7e44b..0e6732e1e0 100644 --- a/packages/client/src/helpers/__tests__/AudioBindingsWatchdog.test.ts +++ b/packages/client/src/helpers/__tests__/AudioBindingsWatchdog.test.ts @@ -11,6 +11,7 @@ import { StreamClient } from '../../coordinator/connection/client'; import { CallingState, StreamVideoWriteableStateStore } from '../../store'; import { noopComparator } from '../../sorting'; import { fromPartial } from '@total-typescript/shoehorn'; +import { TrackType } from '../../gen/video/sfu/models/models'; describe('AudioBindingsWatchdog', () => { let watchdog: AudioBindingsWatchdog; @@ -44,12 +45,17 @@ describe('AudioBindingsWatchdog', () => { screenShareAudioStream?: MediaStream; }, ) => { + const publishedTracks = []; + if (streams?.audioStream) publishedTracks.push(TrackType.AUDIO); + if (streams?.screenShareAudioStream) { + publishedTracks.push(TrackType.SCREEN_SHARE_AUDIO); + } call.state.updateOrAddParticipant( sessionId, fromPartial({ userId, sessionId, - publishedTracks: [], + publishedTracks, ...streams, }), ); @@ -233,6 +239,26 @@ describe('AudioBindingsWatchdog', () => { expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('user-1')); }); + it('should not warn when audioStream exists but audio is not published', () => { + // @ts-expect-error private property + const warnSpy = vi.spyOn(watchdog.logger, 'warn'); + + call.state.updateOrAddParticipant( + 'session-1', + fromPartial({ + userId: 'user-1', + sessionId: 'session-1', + publishedTracks: [], + audioStream: new MediaStream(), + }), + ); + + call.state.setCallingState(CallingState.JOINED); + vi.advanceTimersByTime(3000); + + expect(warnSpy).not.toHaveBeenCalled(); + }); + it('should not warn when screenShareAudio element is bound', () => { // @ts-expect-error private property const warnSpy = vi.spyOn(watchdog.logger, 'warn');