Fix mic processing toggles after LiveKit voiceIsolation default
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
ParticipantEvent,
|
||||
Participant,
|
||||
LocalTrackPublication,
|
||||
LocalAudioTrack,
|
||||
Track,
|
||||
} from 'livekit-client';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
@@ -31,7 +32,7 @@ import {
|
||||
getLiveKitHomeserverPriority,
|
||||
} from './useRtcConfig';
|
||||
import { getActiveCallMembers } from './useRoomCallMembers';
|
||||
import { getAudioSettings, SCREEN_SHARE_RESOLUTIONS, SCREEN_SHARE_BITRATES } from '../settings/audio/Audio';
|
||||
import { getAudioCaptureOptions, getAudioSettings, AUDIO_SETTINGS_CHANGED_EVENT, SCREEN_SHARE_RESOLUTIONS, SCREEN_SHARE_BITRATES } from '../settings/audio/Audio';
|
||||
import { getCallSounds, CallSoundType } from './CallSounds';
|
||||
|
||||
type CallEventListener = (event: CallEvent) => void;
|
||||
@@ -102,6 +103,10 @@ export class CallService {
|
||||
|
||||
private wasMutedBeforeDeafen = false;
|
||||
|
||||
private readonly onAudioSettingsChanged = () => {
|
||||
void this.applyAudioCaptureSettings();
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new CallService instance
|
||||
* @param config - Service configuration including homeserver and LiveKit URLs
|
||||
@@ -110,6 +115,7 @@ export class CallService {
|
||||
constructor(config: CallServiceConfig, matrixClient: MatrixClient) {
|
||||
this.config = config;
|
||||
this.matrixClient = matrixClient;
|
||||
window.addEventListener(AUDIO_SETTINGS_CHANGED_EVENT, this.onAudioSettingsChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,9 +392,13 @@ export class CallService {
|
||||
}
|
||||
|
||||
// Step 4: Create and connect to LiveKit room
|
||||
// Pin audioCaptureDefaults so mute/unmute republish doesn't re-enable LiveKit's
|
||||
// voiceIsolation:true default (which ignores noiseSuppression).
|
||||
const audioCaptureOptions = getAudioCaptureOptions();
|
||||
this.livekitRoom = new Room({
|
||||
adaptiveStream: true,
|
||||
dynacast: true,
|
||||
audioCaptureDefaults: audioCaptureOptions,
|
||||
});
|
||||
|
||||
this.setupLiveKitEventHandlers();
|
||||
@@ -400,19 +410,7 @@ export class CallService {
|
||||
console.log('Local participant identity:', this.livekitRoom.localParticipant.identity);
|
||||
console.log('Remote participants:', this.livekitRoom.remoteParticipants.size);
|
||||
|
||||
// Get user's audio device preferences
|
||||
const audioSettings = getAudioSettings();
|
||||
console.log('Using audio settings:', audioSettings);
|
||||
|
||||
// Build audio capture options with processing settings
|
||||
const audioCaptureOptions = {
|
||||
deviceId: audioSettings.microphoneId || undefined,
|
||||
noiseSuppression: audioSettings.noiseSuppression,
|
||||
echoCancellation: audioSettings.echoCancellation,
|
||||
autoGainControl: audioSettings.autoGainControl,
|
||||
};
|
||||
|
||||
console.log('Audio capture options:', audioCaptureOptions);
|
||||
console.log('Using audio capture options:', audioCaptureOptions);
|
||||
|
||||
// Step 5: Publish local tracks based on call type with selected devices and processing
|
||||
if (callType === CallType.Video) {
|
||||
@@ -881,7 +879,10 @@ export class CallService {
|
||||
getCallSounds().playSound(CallSoundType.Undeafen);
|
||||
}
|
||||
|
||||
this.livekitRoom.localParticipant.setMicrophoneEnabled(!newMuteState);
|
||||
this.livekitRoom.localParticipant.setMicrophoneEnabled(
|
||||
!newMuteState,
|
||||
getAudioCaptureOptions()
|
||||
);
|
||||
this.activeCall.isMuted = newMuteState;
|
||||
|
||||
// Play mute/unmute sound
|
||||
@@ -929,7 +930,7 @@ export class CallService {
|
||||
} else {
|
||||
// Undeafening - only unmute if user wasn't muted before deafening
|
||||
if (!this.wasMutedBeforeDeafen && this.activeCall.isMuted) {
|
||||
this.livekitRoom.localParticipant.setMicrophoneEnabled(true);
|
||||
this.livekitRoom.localParticipant.setMicrophoneEnabled(true, getAudioCaptureOptions());
|
||||
this.activeCall.isMuted = false;
|
||||
}
|
||||
this.wasMutedBeforeDeafen = false;
|
||||
@@ -1129,10 +1130,39 @@ export class CallService {
|
||||
return this.activeCall?.isScreenSharing ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-apply stored mic processing settings to the live published track.
|
||||
* Needed because LiveKit merges voiceIsolation:true by default, and because
|
||||
* settings changes mid-call previously only wrote localStorage.
|
||||
*/
|
||||
async applyAudioCaptureSettings(): Promise<void> {
|
||||
if (!this.livekitRoom || !this.activeCall) return;
|
||||
|
||||
const options = getAudioCaptureOptions();
|
||||
this.livekitRoom.options.audioCaptureDefaults = {
|
||||
...this.livekitRoom.options.audioCaptureDefaults,
|
||||
...options,
|
||||
};
|
||||
|
||||
const publication = this.livekitRoom.localParticipant.getTrackPublication(
|
||||
Track.Source.Microphone
|
||||
);
|
||||
const track = publication?.track;
|
||||
if (!(track instanceof LocalAudioTrack)) return;
|
||||
|
||||
try {
|
||||
await track.restartTrack(options);
|
||||
console.log('Reapplied audio capture settings:', options);
|
||||
} catch (error) {
|
||||
console.error('Failed to reapply audio capture settings:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up resources
|
||||
*/
|
||||
dispose(): void {
|
||||
window.removeEventListener(AUDIO_SETTINGS_CHANGED_EVENT, this.onAudioSettingsChanged);
|
||||
this.stopMembershipRefresh();
|
||||
this.endCall();
|
||||
this.listeners.clear();
|
||||
|
||||
Reference in New Issue
Block a user