diff --git a/.changeset/preconnect-buffer-publish-options.md b/.changeset/preconnect-buffer-publish-options.md new file mode 100644 index 0000000000..f8ea938751 --- /dev/null +++ b/.changeset/preconnect-buffer-publish-options.md @@ -0,0 +1,5 @@ +--- +'livekit-client': patch +--- + +Read `preConnectBuffer` from the publish options passed to `setMicrophoneEnabled` instead of the capture options. diff --git a/src/room/participant/LocalParticipant.test.ts b/src/room/participant/LocalParticipant.test.ts index cc8adc04cf..4dfe68cf87 100644 --- a/src/room/participant/LocalParticipant.test.ts +++ b/src/room/participant/LocalParticipant.test.ts @@ -2,7 +2,7 @@ import { PacketTrailerFeature } from '@livekit/protocol'; import { describe, expect, it, vi } from 'vitest'; import type LocalTrack from '../track/LocalTrack'; import { Track } from '../track/Track'; -import type { TrackPublishOptions } from '../track/options'; +import type { AudioCaptureOptions, TrackPublishOptions } from '../track/options'; import LocalParticipant from './LocalParticipant'; type FrameMetadataTestParticipant = { @@ -79,3 +79,53 @@ describe('LocalParticipant frame metadata publish options', () => { expect(participant.log.warn).toHaveBeenCalledOnce(); }); }); + +type PreConnectBufferTestParticipant = Pick & { + log: { debug: ReturnType; info: ReturnType }; + roomOptions: { publishDefaults?: TrackPublishOptions }; + pendingPublishing: Set; + getTrackPublication: ReturnType; + createTracks: ReturnType; + publishTrack: ReturnType; +}; + +function makeAudioTrackWithBufferSpy() { + const track = makeTrack(Track.Kind.Audio) as LocalTrack & { + startPreConnectBuffer: ReturnType; + }; + track.startPreConnectBuffer = vi.fn(); + return track; +} + +function makePreConnectParticipant(track: LocalTrack) { + const participant = Object.create(LocalParticipant.prototype) as PreConnectBufferTestParticipant; + participant.log = { debug: vi.fn(), info: vi.fn() }; + participant.roomOptions = { publishDefaults: {} }; + participant.pendingPublishing = new Set(); + participant.getTrackPublication = vi.fn().mockReturnValue(undefined); + participant.createTracks = vi.fn().mockResolvedValue([track]); + participant.publishTrack = vi.fn().mockResolvedValue(undefined); + return participant; +} + +describe('LocalParticipant preconnect buffer', () => { + it('starts the preconnect buffer when preConnectBuffer is set in the publish options', async () => { + const track = makeAudioTrackWithBufferSpy(); + const participant = makePreConnectParticipant(track); + + await participant.setMicrophoneEnabled(true, undefined, { preConnectBuffer: true }); + + expect(track.startPreConnectBuffer).toHaveBeenCalledOnce(); + }); + + it('does not start the preconnect buffer when preConnectBuffer is set in the capture options', async () => { + const track = makeAudioTrackWithBufferSpy(); + const participant = makePreConnectParticipant(track); + + await participant.setMicrophoneEnabled(true, { + preConnectBuffer: true, + } as AudioCaptureOptions); + + expect(track.startPreConnectBuffer).not.toHaveBeenCalled(); + }); +}); diff --git a/src/room/participant/LocalParticipant.ts b/src/room/participant/LocalParticipant.ts index 645482c224..ed890999ef 100644 --- a/src/room/participant/LocalParticipant.ts +++ b/src/room/participant/LocalParticipant.ts @@ -583,11 +583,11 @@ export default class LocalParticipant extends Participant { throw e; } + const opts: TrackPublishOptions = { + ...this.roomOptions.publishDefaults, + ...publishOptions, + }; for (const localTrack of localTracks) { - const opts: TrackPublishOptions = { - ...this.roomOptions.publishDefaults, - ...options, - }; if ( source === Track.Source.Microphone && isAudioTrack(localTrack) &&