From b9866e3464fab388dfe2629c39b237d6cd80a4da Mon Sep 17 00:00:00 2001 From: Jaya Allamsetty Date: Tue, 31 Aug 2021 11:06:31 -0400 Subject: [PATCH] fix(tracks) Fix mobile safari issue with startMuted. On mobile Safari, when a user joins both audio and video muted, browser doesn't playout the remote audio because of a webkit bug. As a workaround, always add the audio track to peerconnection and then mute the track if needed. --- conference.js | 17 +++++++++++++---- react/features/prejoin/middleware.js | 8 ++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/conference.js b/conference.js index 886525789..e9ca00ee6 100644 --- a/conference.js +++ b/conference.js @@ -56,6 +56,7 @@ import { setAudioOutputDeviceId, updateDeviceList } from './react/features/base/devices'; +import { isIosMobileBrowser } from './react/features/base/environment/utils'; import { browser, isFatalJitsiConnectionError, @@ -834,7 +835,13 @@ export default { this._initDeviceList(true); if (initialOptions.startWithAudioMuted) { - localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO); + // Always add the audio track to the peer connection and then mute the track on mobile Safari + // because of a known issue where audio playout doesn't happen if the user joins audio and video muted. + if (isIosMobileBrowser()) { + this.muteAudio(true, true); + } else { + localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO); + } } return this.startConference(con, localTracks); @@ -1322,8 +1329,8 @@ export default { APP.store.dispatch(conferenceWillJoin(room)); - // Filter out the tracks that are muted. - const tracks = localTracks.filter(track => !track.isMuted()); + // Filter out the tracks that are muted (except on mobile Safari). + const tracks = isIosMobileBrowser() ? localTracks : localTracks.filter(track => !track.isMuted()); this._setLocalAudioVideoStreams(tracks); this._room = room; // FIXME do not use this @@ -2261,7 +2268,9 @@ export default { // Remove the tracks from the peerconnection. for (const track of localTracks) { - if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO) { + // Always add the track on mobile Safari because of a known issue where audio playout doesn't happen + // if the user joins audio and video muted. + if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO && !isIosMobileBrowser()) { promises.push(this.useAudioStream(null)); } if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) { diff --git a/react/features/prejoin/middleware.js b/react/features/prejoin/middleware.js index f6dbc6621..edce76b33 100644 --- a/react/features/prejoin/middleware.js +++ b/react/features/prejoin/middleware.js @@ -2,7 +2,8 @@ import { CONFERENCE_JOINED } from '../base/conference'; import { updateConfig } from '../base/config'; -import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media'; +import { isIosMobileBrowser } from '../base/environment/utils'; +import { MEDIA_TYPE, SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../base/media'; import { MiddlewareRegistry } from '../base/redux'; import { updateSettings } from '../base/settings'; import { @@ -46,7 +47,10 @@ MiddlewareRegistry.register(store => next => async action => { // Do not signal audio/video tracks if the user joins muted. for (const track of localTracks) { - if (track.muted) { + // Always add the audio track on mobile Safari because of a known issue where audio playout doesn't happen + // if the user joins audio and video muted. + if (track.muted + && !(isIosMobileBrowser() && track.jitsiTrack && track.jitsiTrack.getType() === MEDIA_TYPE.AUDIO)) { await dispatch(replaceLocalTrack(track.jitsiTrack, null)); } }