Fix double audio tracks
See comments. I'm not very happy with how this code bounces state in and out of different hooks and useEffect blocks, but as a quick fix this should work.
This commit is contained in:
@@ -17,10 +17,8 @@ limitations under the License.
|
||||
import {
|
||||
AudioCaptureOptions,
|
||||
ConnectionState,
|
||||
LocalTrackPublication,
|
||||
Room,
|
||||
RoomEvent,
|
||||
Track,
|
||||
} from "livekit-client";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
@@ -56,24 +54,22 @@ async function doConnect(
|
||||
audioOptions: AudioCaptureOptions
|
||||
): Promise<void> {
|
||||
await livekitRoom!.connect(sfuConfig!.url, sfuConfig!.jwt);
|
||||
const hasMicrophoneTrack = Array.from(
|
||||
livekitRoom?.localParticipant.audioTracks.values()
|
||||
).some((track: LocalTrackPublication) => {
|
||||
return track.source == Track.Source.Microphone;
|
||||
});
|
||||
// We create a track in case there isn't any.
|
||||
if (!hasMicrophoneTrack) {
|
||||
const audioTracks = await livekitRoom!.localParticipant.createTracks({
|
||||
audio: audioOptions,
|
||||
});
|
||||
if (audioTracks.length < 1) {
|
||||
logger.info("Tried to pre-create local audio track but got no tracks");
|
||||
return;
|
||||
}
|
||||
if (!audioEnabled) await audioTracks[0].mute();
|
||||
|
||||
await livekitRoom?.localParticipant.publishTrack(audioTracks[0]);
|
||||
// Always create an audio track manually.
|
||||
// livekit (by default) keeps the mic track open when you mute, but if you start muted,
|
||||
// doesn't publish it until you unmute. We want to publish it from the start so we're
|
||||
// always capturing audio: it helps keep bluetooth headsets in the right mode and
|
||||
// mobile browsers to know we're doing a call.
|
||||
const audioTracks = await livekitRoom!.localParticipant.createTracks({
|
||||
audio: audioOptions,
|
||||
});
|
||||
if (audioTracks.length < 1) {
|
||||
logger.info("Tried to pre-create local audio track but got no tracks");
|
||||
return;
|
||||
}
|
||||
if (!audioEnabled) await audioTracks[0].mute();
|
||||
|
||||
await livekitRoom?.localParticipant.publishTrack(audioTracks[0]);
|
||||
}
|
||||
|
||||
export function useECConnectionState(
|
||||
@@ -89,6 +85,7 @@ export function useECConnectionState(
|
||||
);
|
||||
|
||||
const [isSwitchingFocus, setSwitchingFocus] = useState(false);
|
||||
const [isInDoConnect, setIsInDoConnect] = useState(false);
|
||||
|
||||
const onConnStateChanged = useCallback((state: ConnectionState) => {
|
||||
if (state == ConnectionState.Connected) setSwitchingFocus(false);
|
||||
@@ -125,12 +122,17 @@ export function useECConnectionState(
|
||||
(async () => {
|
||||
setSwitchingFocus(true);
|
||||
await livekitRoom?.disconnect();
|
||||
await doConnect(
|
||||
livekitRoom!,
|
||||
sfuConfig!,
|
||||
initialAudioEnabled,
|
||||
initialAudioOptions
|
||||
);
|
||||
setIsInDoConnect(true);
|
||||
try {
|
||||
await doConnect(
|
||||
livekitRoom!,
|
||||
sfuConfig!,
|
||||
initialAudioEnabled,
|
||||
initialAudioOptions
|
||||
);
|
||||
} finally {
|
||||
setIsInDoConnect(false);
|
||||
}
|
||||
})();
|
||||
} else if (
|
||||
!sfuConfigValid(currentSFUConfig.current) &&
|
||||
@@ -142,16 +144,24 @@ export function useECConnectionState(
|
||||
// doesn't publish it until you unmute. We want to publish it from the start so we're
|
||||
// always capturing audio: it helps keep bluetooth headsets in the right mode and
|
||||
// mobile browsers to know we're doing a call.
|
||||
setIsInDoConnect(true);
|
||||
doConnect(
|
||||
livekitRoom!,
|
||||
sfuConfig!,
|
||||
initialAudioEnabled,
|
||||
initialAudioOptions
|
||||
);
|
||||
).finally(() => setIsInDoConnect(false));
|
||||
}
|
||||
|
||||
currentSFUConfig.current = Object.assign({}, sfuConfig);
|
||||
}, [sfuConfig, livekitRoom, initialAudioOptions, initialAudioEnabled]);
|
||||
|
||||
return isSwitchingFocus ? ECAddonConnectionState.ECSwitchingFocus : connState;
|
||||
// Because we create audio tracks by hand, there's more to connecting than
|
||||
// just what LiveKit does in room.connect, and we should continue to return
|
||||
// ConnectionState.Connecting for the entire duration of the doConnect promise
|
||||
return isSwitchingFocus
|
||||
? ECAddonConnectionState.ECSwitchingFocus
|
||||
: isInDoConnect
|
||||
? ConnectionState.Connecting
|
||||
: connState;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user