瀏覽代碼

fix(conference) Fix different bugs with startMuted policy. (#2777)

* fix(conference) Fix different bugs with startMuted policy.
If the user changes mute state after joining the call and before the other participats join the call, make sure those state changes are honored.

* feat(startMuted) Ignore startMuted in Jingle from focus.
Apply startMuted policy based on startMuted setting in room meta data.
Moderator settings and AV moderation settings will now be propagated to new endpoints joining the call through room meta data.
Advertise a new capability 'start-muted-room-metadata' to Jicofo for feature detection.
dev0
Jaya Allamsetty 6 月之前
父節點
當前提交
b9a9ac03c3

+ 31
- 60
JitsiConference.js 查看文件

@@ -187,8 +187,6 @@ export default function JitsiConference(options) {
187 187
     this.dtmfManager = null;
188 188
     this.somebodySupportsDTMF = false;
189 189
     this.authEnabled = false;
190
-    this.startAudioMuted = false;
191
-    this.startVideoMuted = false;
192 190
     this.startMutedPolicy = {
193 191
         audio: false,
194 192
         video: false
@@ -1229,38 +1227,6 @@ JitsiConference.prototype._fireMuteChangeEvent = function(track) {
1229 1227
     this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track, actorParticipant);
1230 1228
 };
1231 1229
 
1232
-/**
1233
- * Returns the list of local tracks that need to be added to the peerconnection on join.
1234
- * This takes the startAudioMuted/startVideoMuted flags into consideration since we do not
1235
- * want to add the tracks if the user joins the call audio/video muted. The tracks will be
1236
- * added when the user unmutes for the first time.
1237
- * @returns {Array<JitsiLocalTrack>} - list of local tracks that are unmuted.
1238
- */
1239
-JitsiConference.prototype._getInitialLocalTracks = function() {
1240
-    // Always add the audio track on certain platforms:
1241
-    //  * Safari / WebKit: because of a known issue where audio playout doesn't happen
1242
-    //    if the user joins audio and video muted.
1243
-    //  * React Native: after iOS 15, if a user joins muted they won't be able to unmute.
1244
-    return this.getLocalTracks()
1245
-        .filter(track => {
1246
-            const trackType = track.getType();
1247
-
1248
-            if (trackType === MediaType.AUDIO
1249
-                    && (!(this.isStartAudioMuted() || this.startMutedPolicy.audio)
1250
-                    || browser.isWebKitBased()
1251
-                    || browser.isReactNative())) {
1252
-                return true;
1253
-            } else if (trackType === MediaType.VIDEO && !this.isStartVideoMuted() && !this.startMutedPolicy.video) {
1254
-                return true;
1255
-            }
1256
-
1257
-            // Remove the track from the conference.
1258
-            this.onLocalTrackRemoved(track);
1259
-
1260
-            return false;
1261
-        });
1262
-};
1263
-
1264 1230
 /**
1265 1231
  * Clear JitsiLocalTrack properties and listeners.
1266 1232
  * @param track the JitsiLocalTrack object.
@@ -1825,6 +1791,31 @@ JitsiConference.prototype.onMemberJoined = function(
1825 1791
     }
1826 1792
 
1827 1793
     this._maybeSetSITimeout();
1794
+    const { startAudioMuted, startVideoMuted } = this.options.config;
1795
+
1796
+    // Ignore startAudio/startVideoMuted settings if the media session has already been established.
1797
+    // Apply the policy if the number of participants exceeds the startMuted thresholds.
1798
+    if ((this.jvbJingleSession && this.getActiveMediaSession() === this.jvbJingleSession)
1799
+        || ((typeof startAudioMuted === 'undefined' || startAudioMuted === -1)
1800
+            && (typeof startVideoMuted === 'undefined' || startVideoMuted === -1))) {
1801
+        return;
1802
+    }
1803
+
1804
+    let audioMuted = false;
1805
+    let videoMuted = false;
1806
+    const numberOfParticipants = this.getParticipantCount();
1807
+
1808
+    if (numberOfParticipants > this.options.config.startAudioMuted) {
1809
+        audioMuted = true;
1810
+    }
1811
+
1812
+    if (numberOfParticipants > this.options.config.startVideoMuted) {
1813
+        videoMuted = true;
1814
+    }
1815
+
1816
+    if ((audioMuted && !this.startMutedPolicy.audio) || (videoMuted && !this.startMutedPolicy.video)) {
1817
+        this._updateStartMutedPolicy(audioMuted, videoMuted);
1818
+    }
1828 1819
 };
1829 1820
 
1830 1821
 /* eslint-enable max-params */
@@ -2264,7 +2255,7 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(jingleSession, jingl
2264 2255
     // Open a channel with the videobridge.
2265 2256
     this._setBridgeChannel(jingleOffer, jingleSession.peerconnection);
2266 2257
 
2267
-    const localTracks = this._getInitialLocalTracks();
2258
+    const localTracks = this.getLocalTracks();
2268 2259
 
2269 2260
     try {
2270 2261
         jingleSession.acceptOffer(
@@ -2633,11 +2624,9 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2633 2624
         return;
2634 2625
     }
2635 2626
 
2636
-    // Do not apply the startMutedPolicy locally on the moderator, the moderator should join with available local
2637
-    // sources and the policy needs to be applied only on users that join the call after.
2638
-    // this.startMutedPolicy = policy;
2639
-    // TODO: to remove using presence for startmuted policy after old clients update
2640
-    // we keep presence to update UI of old clients
2627
+    logger.info(`Setting start muted policy: ${JSON.stringify(policy)} in presence and in conference metadata`);
2628
+
2629
+    // TODO: to remove using presence for startmuted policy after old clients update to using metadata always.
2641 2630
     this.room.addOrReplaceInPresence('startmuted', {
2642 2631
         attributes: {
2643 2632
             audio: policy.audio,
@@ -2646,9 +2635,6 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2646 2635
         }
2647 2636
     }) && this.room.sendPresence();
2648 2637
 
2649
-    // we want to ignore applying startMutedPolicy locally when we set it
2650
-    this._ignoreFirstStartMutedPolicyUpdate = true;
2651
-
2652 2638
     this.getMetadataHandler().setMetadata('startMuted', {
2653 2639
         audio: policy.audio,
2654 2640
         video: policy.video
@@ -2662,9 +2648,8 @@ JitsiConference.prototype.setStartMutedPolicy = function(policy) {
2662 2648
  * @param {boolean} video if video should be muted.
2663 2649
  */
2664 2650
 JitsiConference.prototype._updateStartMutedPolicy = function(audio, video) {
2665
-    if (this._ignoreFirstStartMutedPolicyUpdate) {
2666
-        this._ignoreFirstStartMutedPolicyUpdate = false;
2667
-
2651
+    // Update the start muted policy for the conference only if the meta data is received before conference join.
2652
+    if (this.isJoined()) {
2668 2653
         return;
2669 2654
     }
2670 2655
 
@@ -2696,20 +2681,6 @@ JitsiConference.prototype.getStartMutedPolicy = function() {
2696 2681
     return this.startMutedPolicy;
2697 2682
 };
2698 2683
 
2699
-/**
2700
- * Check if audio is muted on join.
2701
- */
2702
-JitsiConference.prototype.isStartAudioMuted = function() {
2703
-    return this.startAudioMuted;
2704
-};
2705
-
2706
-/**
2707
- * Check if video is muted on join.
2708
- */
2709
-JitsiConference.prototype.isStartVideoMuted = function() {
2710
-    return this.startVideoMuted;
2711
-};
2712
-
2713 2684
 /**
2714 2685
  * Returns measured connectionTimes.
2715 2686
  */

+ 6
- 37
JitsiConferenceEventManager.js 查看文件

@@ -413,10 +413,12 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
413 413
     // Room metadata.
414 414
     chatRoom.addListener(XMPPEvents.ROOM_METADATA_UPDATED, metadata => {
415 415
         if (metadata.startMuted) {
416
-            conference._updateStartMutedPolicy(
417
-                metadata.startMuted.audio || false,
418
-                metadata.startMuted.video || false
419
-            );
416
+            const audio = metadata.startMuted.audio || false;
417
+            const video = metadata.startMuted.video || false;
418
+
419
+            audio && (conference.isMutedByFocus = true);
420
+            video && (conference.isVideoMutedByFocus = true);
421
+            conference._updateStartMutedPolicy(audio, video);
420 422
         }
421 423
         conference.eventEmitter.emit(JitsiConferenceEvents.METADATA_UPDATED, metadata);
422 424
     });
@@ -591,39 +593,6 @@ JitsiConferenceEventManager.prototype.setupXMPPListeners = function() {
591 593
         XMPPEvents.CALL_ENDED,
592 594
         conference.onCallEnded.bind(conference));
593 595
 
594
-    this._addConferenceXMPPListener(XMPPEvents.START_MUTED_FROM_FOCUS,
595
-        (audioMuted, videoMuted) => {
596
-            if (conference.options.config.ignoreStartMuted) {
597
-                return;
598
-            }
599
-
600
-            conference.startAudioMuted = audioMuted;
601
-            conference.startVideoMuted = videoMuted;
602
-
603
-            if (audioMuted) {
604
-                conference.isMutedByFocus = true;
605
-            }
606
-
607
-            if (videoMuted) {
608
-                conference.isVideoMutedByFocus = true;
609
-            }
610
-
611
-            // mute existing local tracks because this is initial mute from
612
-            // Jicofo
613
-            conference.getLocalTracks().forEach(track => {
614
-                switch (track.getType()) {
615
-                case MediaType.AUDIO:
616
-                    conference.startAudioMuted && track.mute();
617
-                    break;
618
-                case MediaType.VIDEO:
619
-                    conference.startVideoMuted && track.mute();
620
-                    break;
621
-                }
622
-            });
623
-
624
-            conference.eventEmitter.emit(JitsiConferenceEvents.STARTED_MUTED);
625
-        });
626
-
627 596
     this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_CHANGED,
628 597
         (value, mediaType, actorJid) => {
629 598
             const actorParticipant = conference.getParticipants().find(p => p.getJid() === actorJid);

+ 0
- 3
JitsiConferenceEvents.spec.ts 查看文件

@@ -58,7 +58,6 @@ describe( "/JitsiConferenceEvents members", () => {
58 58
         VIDEO_SIP_GW_AVAILABILITY_CHANGED,
59 59
         VIDEO_SIP_GW_SESSION_STATE_CHANGED,
60 60
         START_MUTED_POLICY_CHANGED,
61
-        STARTED_MUTED,
62 61
         SUBJECT_CHANGED,
63 62
         SUSPEND_DETECTED,
64 63
         TALK_WHILE_MUTED,
@@ -146,7 +145,6 @@ describe( "/JitsiConferenceEvents members", () => {
146 145
         expect( VIDEO_SIP_GW_SESSION_STATE_CHANGED ).toBe( 'conference.videoSIPGWSessionStateChanged' );
147 146
         expect( VISITORS_SUPPORTED_CHANGED ).toBe( 'conference.visitorsSupported' );
148 147
         expect( START_MUTED_POLICY_CHANGED ).toBe( 'conference.start_muted_policy_changed' );
149
-        expect( STARTED_MUTED ).toBe( 'conference.started_muted' );
150 148
         expect( SUBJECT_CHANGED ).toBe( 'conference.subjectChanged' );
151 149
         expect( SUSPEND_DETECTED ).toBe( 'conference.suspendDetected' );
152 150
         expect( TALK_WHILE_MUTED ).toBe( 'conference.talk_while_muted' );
@@ -227,7 +225,6 @@ describe( "/JitsiConferenceEvents members", () => {
227 225
         expect( JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED ).toBe( 'conference.videoSIPGWAvailabilityChanged' );
228 226
         expect( JitsiConferenceEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED ).toBe( 'conference.videoSIPGWSessionStateChanged' );
229 227
         expect( JitsiConferenceEvents.START_MUTED_POLICY_CHANGED ).toBe( 'conference.start_muted_policy_changed' );
230
-        expect( JitsiConferenceEvents.STARTED_MUTED ).toBe( 'conference.started_muted' );
231 228
         expect( JitsiConferenceEvents.SUBJECT_CHANGED ).toBe( 'conference.subjectChanged' );
232 229
         expect( JitsiConferenceEvents.SUSPEND_DETECTED ).toBe( 'conference.suspendDetected' );
233 230
         expect( JitsiConferenceEvents.TALK_WHILE_MUTED ).toBe( 'conference.talk_while_muted' );

+ 0
- 6
JitsiConferenceEvents.ts 查看文件

@@ -371,11 +371,6 @@ export enum JitsiConferenceEvents {
371 371
      */
372 372
     SILENT_STATUS_CHANGED = 'conference.silentStatusChanged',
373 373
 
374
-    /**
375
-     * Indicates that the local user has started muted.
376
-     */
377
-    STARTED_MUTED = 'conference.started_muted',
378
-
379 374
     /**
380 375
      * Indicates that start muted settings changed.
381 376
      */
@@ -582,7 +577,6 @@ export const RECORDER_STATE_CHANGED = JitsiConferenceEvents.RECORDER_STATE_CHANG
582 577
 export const SERVER_REGION_CHANGED = JitsiConferenceEvents.SERVER_REGION_CHANGED;
583 578
 export const SILENT_STATUS_CHANGED = JitsiConferenceEvents.SILENT_STATUS_CHANGED;
584 579
 export const START_MUTED_POLICY_CHANGED = JitsiConferenceEvents.START_MUTED_POLICY_CHANGED;
585
-export const STARTED_MUTED = JitsiConferenceEvents.STARTED_MUTED;
586 580
 export const SUBJECT_CHANGED = JitsiConferenceEvents.SUBJECT_CHANGED;
587 581
 export const SUSPEND_DETECTED = JitsiConferenceEvents.SUSPEND_DETECTED;
588 582
 export const TALK_WHILE_MUTED = JitsiConferenceEvents.TALK_WHILE_MUTED;

+ 1
- 0
modules/xmpp/RoomMetadata.ts 查看文件

@@ -95,6 +95,7 @@ export default class RoomMetadata {
95 95
         }
96 96
 
97 97
         this._metadata = metadata;
98
+        logger.debug('Received metadata update', metadata);
98 99
         this.room.eventEmitter.emit(XMPPEvents.ROOM_METADATA_UPDATED, metadata);
99 100
     }
100 101
 

+ 0
- 11
modules/xmpp/strophe.jingle.js 查看文件

@@ -3,7 +3,6 @@ import $ from 'jquery';
3 3
 import { cloneDeep } from 'lodash-es';
4 4
 import { $iq, Strophe } from 'strophe.js';
5 5
 
6
-import { MediaType } from '../../service/RTC/MediaType';
7 6
 import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
8 7
 import RandomUtil from '../util/RandomUtil';
9 8
 
@@ -179,18 +178,8 @@ export default class JingleConnectionPlugin extends ConnectionPlugin {
179 178
         switch (action) {
180 179
         case 'session-initiate': {
181 180
             logger.info('(TIME) received session-initiate:\t', now);
182
-            const startMuted = $(iq).find('jingle>startmuted');
183 181
 
184 182
             isP2P && logger.debug(`Received ${action} from ${fromJid}`);
185
-            if (startMuted?.length) {
186
-                const audioMuted = startMuted.attr(MediaType.AUDIO);
187
-                const videoMuted = startMuted.attr(MediaType.VIDEO);
188
-
189
-                this.eventEmitter.emit(
190
-                    XMPPEvents.START_MUTED_FROM_FOCUS,
191
-                    audioMuted === 'true',
192
-                    videoMuted === 'true');
193
-            }
194 183
             const pcConfig = isP2P ? this.p2pIceConfig : this.jvbIceConfig;
195 184
 
196 185
             sess

+ 3
- 0
modules/xmpp/xmpp.js 查看文件

@@ -284,6 +284,9 @@ export default class XMPP extends Listenable {
284 284
         // for keeping stats, since it is not made available to jocofo at
285 285
         // the time of the initial conference-request.
286 286
         this.caps.addFeature('http://jitsi.org/visitors-1');
287
+
288
+        // Advertise support for startMuted policy through room metadata.
289
+        this.caps.addFeature('http://jitsi.org/start-muted-room-metadata');
287 290
     }
288 291
 
289 292
     /**

+ 0
- 1
service/xmpp/XMPPEvents.spec.ts 查看文件

@@ -98,7 +98,6 @@ describe( "/service/xmpp/XMPPEvents members", () => {
98 98
         expect( XMPPEvents.BREAKOUT_ROOMS_UPDATED ).toBe( 'xmpp.breakout-rooms.updated' );
99 99
         expect( XMPPEvents.ROOM_METADATA_EVENT ).toBe( 'xmpp.room-metadata.event' );
100 100
         expect( XMPPEvents.ROOM_METADATA_UPDATED ).toBe( 'xmpp.room-metadata.updated' );
101
-        expect( XMPPEvents.START_MUTED_FROM_FOCUS ).toBe( 'xmpp.start_muted_from_focus' );
102 101
         expect( XMPPEvents.SUBJECT_CHANGED ).toBe( 'xmpp.subject_changed' );
103 102
         expect( XMPPEvents.SUSPEND_DETECTED ).toBe( 'xmpp.suspend_detected' );
104 103
         expect( XMPPEvents.TRANSCRIPTION_STATUS_CHANGED ).toBe( 'xmpp.transcription_status_changed' );

+ 0
- 4
service/xmpp/XMPPEvents.ts 查看文件

@@ -376,10 +376,6 @@ export enum XMPPEvents {
376 376
      */
377 377
     SPEAKER_STATS_RECEIVED = 'xmpp.speaker_stats_received',
378 378
 
379
-    // Designates an event indicating that we should join the conference with
380
-    // audio and/or video muted.
381
-    START_MUTED_FROM_FOCUS = 'xmpp.start_muted_from_focus',
382
-
383 379
     // Designates an event indicating that the subject of the XMPP MUC has
384 380
     // changed.
385 381
     SUBJECT_CHANGED = 'xmpp.subject_changed',

+ 0
- 2
types/hand-crafted/JitsiConference.d.ts 查看文件

@@ -105,8 +105,6 @@ export default class JitsiConference {
105 105
   getConnectionState: () => string | null;
106 106
   setStartMutedPolicy: ( policy: { audio: boolean, video: boolean } ) => void;
107 107
   getStartMutedPolicy: () => { audio: boolean, video: boolean };
108
-  isStartAudioMuted: () => boolean;
109
-  isStartVideoMuted: () => boolean;
110 108
   getConnectionTimes: () => unknown;
111 109
   setLocalParticipantProperty: ( name: string, value: unknown ) => void;
112 110
   removeLocalParticipantProperty: ( name: string ) => void;

+ 0
- 1
types/hand-crafted/JitsiConferenceEvents.d.ts 查看文件

@@ -41,7 +41,6 @@ export enum JitsiConferenceEvents {
41 41
   VIDEO_SIP_GW_AVAILABILITY_CHANGED = 'conference.videoSIPGWAvailabilityChanged',
42 42
   VIDEO_SIP_GW_SESSION_STATE_CHANGED = 'conference.videoSIPGWSessionStateChanged',
43 43
   START_MUTED_POLICY_CHANGED = 'conference.start_muted_policy_changed',
44
-  STARTED_MUTED = 'conference.started_muted',
45 44
   SUBJECT_CHANGED = 'conference.subjectChanged',
46 45
   SUSPEND_DETECTED = 'conference.suspendDetected',
47 46
   TALK_WHILE_MUTED = 'conference.talk_while_muted',

+ 0
- 1
types/hand-crafted/service/xmpp/XMPPEvents.d.ts 查看文件

@@ -70,7 +70,6 @@
70 70
   AV_MODERATION_RECEIVED = 'xmpp.av_moderation.received',
71 71
   AV_MODERATION_CHANGED = 'xmpp.av_moderation.changed',
72 72
   AV_MODERATION_PARTICIPANT_APPROVED = 'xmpp.av_moderation.participant.approved',
73
-  START_MUTED_FROM_FOCUS = 'xmpp.start_muted_from_focus',
74 73
   SUBJECT_CHANGED = 'xmpp.subject_changed',
75 74
   SUSPEND_DETECTED = 'xmpp.suspend_detected',
76 75
   TRANSCRIPTION_STATUS_CHANGED = 'xmpp.transcription_status_changed',

Loading…
取消
儲存