-
Notifications
You must be signed in to change notification settings - Fork 53
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Describe the bug
When using expo-audio
to play sounds during an ongoing LiveKit meeting (via @livekit/react-native
), the LiveKit audio session stops working. After a sound is played, microphone input is no longer captured — no voice is picked up in the meeting. I'm not sure if this is even supposed to work. If not, are there any workarounds to this?
To Reproduce
Steps to reproduce the behavior:
- Join a LiveKit room using
@livekit/react-native
. - Configure audio session with
AudioSession.startAudioSession()
anduseIOSAudioManagement
. - Use
expo-audio
’suseAudioPlayer
to play any sound (e.g., a short notification sound). - After playback, the LiveKit audio session stops and voice input is no longer transmitted.
Expected behavior
Playing notification sounds with expo-audio
should not interfere with or stop the LiveKit audio session. Microphone input should continue to function normally during and after playback.
Screenshots / Logs
N/A
Device Info
- Device: IPhone XR
- OS: IOS 18.6
Dependencies Info
@livekit/react-native
: 2.9.1livekit-client
: 2.15.5react-native-webrtc
: 137.0.1expo-audio
: 0.4.9react-native
: 0.79.5expo
: 53.0.15
Additional context
Relevant code:
// Configure LiveKit AudioSession
useEffect(() => {
const start = async () => {
AudioSession.configureAudio({
ios: { defaultOutput: "speaker" },
})
await AudioSession.startAudioSession()
}
start()
return () => {
AudioSession.stopAudioSession()
}
}, [])
useIOSAudioManagement(room, true, (): AppleAudioConfiguration => {
return {
audioCategory: "playAndRecord",
audioCategoryOptions: [
"interruptSpokenAudioAndMixWithOthers",
"allowAirPlay",
"allowBluetooth",
"allowBluetoothA2DP",
"defaultToSpeaker",
],
audioMode: "videoChat",
}
})
// Expo Audio player hook
export function useSoundPlayer() {
const chat = useAudioPlayer(SOUND_MAP.CHAT)
const knock = useAudioPlayer(SOUND_MAP.KNOCK)
const raiseHand = useAudioPlayer(SOUND_MAP.RAISE_HAND)
const meetJoin = useAudioPlayer(SOUND_MAP.MEET_JOIN)
const meetLeave = useAudioPlayer(SOUND_MAP.MEET_LEAVE)
const meetEnd = useAudioPlayer(SOUND_MAP.MEET_END)
const recStart = useAudioPlayer(SOUND_MAP.RECORDING_START)
const recEnd = useAudioPlayer(SOUND_MAP.RECORDING_END)
const play = (key: SoundKey) => {
const map = {
CHAT: chat,
KNOCK: knock,
RAISE_HAND: raiseHand,
MEET_JOIN: meetJoin,
MEET_LEAVE: meetLeave,
MEET_END: meetEnd,
RECORDING_START: recStart,
RECORDING_END: recEnd,
}
const player = map[key]
player.seekTo(0)
player.play()
}
return { play }
}
// in app.tsx
useEffect(() => {
const prepare = async () => {
await configureAudioForSpeaker()
await SplashScreen.hideAsync()
}
prepare()
, [])
async function configureAudioForSpeaker() {
await setAudioModeAsync({
playsInSilentMode: true,
shouldPlayInBackground: false,
interruptionModeAndroid: "duckOthers",
interruptionMode: "mixWithOthers",
allowsRecording: true, // tried with both true and false
})
}
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working