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.
This commit is contained in:
Jaya Allamsetty 2021-08-31 11:06:31 -04:00 committed by Jaya Allamsetty
parent e5041202dc
commit b9866e3464
2 changed files with 19 additions and 6 deletions

View File

@ -56,6 +56,7 @@ import {
setAudioOutputDeviceId, setAudioOutputDeviceId,
updateDeviceList updateDeviceList
} from './react/features/base/devices'; } from './react/features/base/devices';
import { isIosMobileBrowser } from './react/features/base/environment/utils';
import { import {
browser, browser,
isFatalJitsiConnectionError, isFatalJitsiConnectionError,
@ -834,7 +835,13 @@ export default {
this._initDeviceList(true); this._initDeviceList(true);
if (initialOptions.startWithAudioMuted) { 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); return this.startConference(con, localTracks);
@ -1322,8 +1329,8 @@ export default {
APP.store.dispatch(conferenceWillJoin(room)); APP.store.dispatch(conferenceWillJoin(room));
// Filter out the tracks that are muted. // Filter out the tracks that are muted (except on mobile Safari).
const tracks = localTracks.filter(track => !track.isMuted()); const tracks = isIosMobileBrowser() ? localTracks : localTracks.filter(track => !track.isMuted());
this._setLocalAudioVideoStreams(tracks); this._setLocalAudioVideoStreams(tracks);
this._room = room; // FIXME do not use this this._room = room; // FIXME do not use this
@ -2261,7 +2268,9 @@ export default {
// Remove the tracks from the peerconnection. // Remove the tracks from the peerconnection.
for (const track of localTracks) { 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)); promises.push(this.useAudioStream(null));
} }
if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) { if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {

View File

@ -2,7 +2,8 @@
import { CONFERENCE_JOINED } from '../base/conference'; import { CONFERENCE_JOINED } from '../base/conference';
import { updateConfig } from '../base/config'; 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 { MiddlewareRegistry } from '../base/redux';
import { updateSettings } from '../base/settings'; import { updateSettings } from '../base/settings';
import { import {
@ -46,7 +47,10 @@ MiddlewareRegistry.register(store => next => async action => {
// Do not signal audio/video tracks if the user joins muted. // Do not signal audio/video tracks if the user joins muted.
for (const track of localTracks) { 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)); await dispatch(replaceLocalTrack(track.jitsiTrack, null));
} }
} }