Przeglądaj źródła

Add video background blur

dev1
Cristian Florin Ghita 6 lat temu
rodzic
commit
fd74ccc526
4 zmienionych plików z 146 dodań i 9 usunięć
  1. 1
    0
      JitsiMeetJS.js
  2. 133
    3
      modules/RTC/JitsiLocalTrack.js
  3. 8
    4
      modules/RTC/RTC.js
  4. 4
    2
      modules/RTC/RTCUtils.js

+ 1
- 0
JitsiMeetJS.js Wyświetl plik

@@ -278,6 +278,7 @@ export default _mergeNamespaceAndModule({
278 278
      * @param options Object with properties / settings specifying the tracks
279 279
      * which should be created. should be created or some additional
280 280
      * configurations about resolution for example.
281
+     * @param {Array} options.effects optional effects array for the track
281 282
      * @param {Array} options.devices the devices that will be requested
282 283
      * @param {string} options.resolution resolution constraints
283 284
      * @param {string} options.cameraDeviceId

+ 133
- 3
modules/RTC/JitsiLocalTrack.js Wyświetl plik

@@ -32,6 +32,7 @@ const logger = getLogger(__filename);
32 32
  * One <tt>JitsiLocalTrack</tt> corresponds to one WebRTC MediaStreamTrack.
33 33
  */
34 34
 export default class JitsiLocalTrack extends JitsiTrack {
35
+
35 36
     /**
36 37
      * Constructs new JitsiLocalTrack instance.
37 38
      *
@@ -43,6 +44,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
43 44
      * JitsiRemoteTrack
44 45
      * @param trackInfo.mediaType the MediaType of the JitsiRemoteTrack
45 46
      * @param trackInfo.videoType the VideoType of the JitsiRemoteTrack
47
+     * @param trackInfo.effects the effects array contains the effect instance to use
46 48
      * @param trackInfo.resolution the video resolution if it's a video track
47 49
      * @param trackInfo.deviceId the ID of the local device for this track
48 50
      * @param trackInfo.facingMode the camera facing mode used in getUserMedia
@@ -60,7 +62,8 @@ export default class JitsiLocalTrack extends JitsiTrack {
60 62
         sourceType,
61 63
         stream,
62 64
         track,
63
-        videoType
65
+        videoType,
66
+        effects = []
64 67
     }) {
65 68
         super(
66 69
             /* conference */ null,
@@ -70,6 +73,16 @@ export default class JitsiLocalTrack extends JitsiTrack {
70 73
             mediaType,
71 74
             videoType);
72 75
 
76
+        const effect = effects.find(e => e.isEnabled(this));
77
+
78
+        this._effectEnabled = false;
79
+        this._streamChangeInProgress = false;
80
+
81
+        if (effect) {
82
+            this._setStream(this._startStreamEffect(effect));
83
+            this._effectEnabled = true;
84
+        }
85
+
73 86
         /**
74 87
          * The ID assigned by the RTC module on instance creation.
75 88
          *
@@ -306,6 +319,104 @@ export default class JitsiLocalTrack extends JitsiTrack {
306 319
         }
307 320
     }
308 321
 
322
+    /**
323
+     * Starts the effect process and returns the modified stream.
324
+     *
325
+     * @private
326
+     * @param {*} effect - Represents effect instance
327
+     * @returns {MediaStream}
328
+     */
329
+    _startStreamEffect(effect) {
330
+        this._streamEffect = effect;
331
+        this._originalStream = this.stream;
332
+        this._streamEffect.startEffect(this._originalStream);
333
+
334
+        return this._streamEffect.getStreamWithEffect();
335
+    }
336
+
337
+    /**
338
+     * Stops the effect process and returns the original stream.
339
+     *
340
+     * @private
341
+     * @returns {MediaStream}
342
+     */
343
+    _stopStreamEffect() {
344
+        this._streamEffect.stopEffect();
345
+        this._streamEffect = null;
346
+
347
+        return this._originalStream;
348
+    }
349
+
350
+    /**
351
+     * Switches the video stream associated with this track and updates the containers.
352
+     *
353
+     * @private
354
+     * @param {MediaStream} newStream - The MediaStream to replace
355
+     * @returns {Promise}
356
+     */
357
+    _switchStream(newStream: MediaStream) {
358
+        if (this._streamChangeInProgress === true) {
359
+            return Promise.reject(new Error('Stream change already in progress!'));
360
+        }
361
+
362
+        this._streamChangeInProgress = true;
363
+
364
+        const conference = this.conference;
365
+
366
+        if (!conference) {
367
+            return Promise.resolve();
368
+        }
369
+
370
+        return conference.removeTrack(this)
371
+            .then(() => {
372
+                this._setStream(newStream);
373
+
374
+                if (!this.isAudioTrack()) {
375
+                    this.containers.forEach(
376
+                        cont => RTCUtils.attachMediaStream(cont, this.stream));
377
+                }
378
+
379
+                return conference.addTrack(this);
380
+            })
381
+            .then(() => {
382
+                this._streamChangeInProgress = false;
383
+            })
384
+            .catch(error => {
385
+                this._streamChangeInProgress = false;
386
+                logger.error('Failed to switch to new stream!', error);
387
+                throw error;
388
+            });
389
+    }
390
+
391
+    /**
392
+     * Sets the effect and switches between the modified stream and original one.
393
+     *
394
+     * @param {Boolean} enableFlag - Flag to start or stop the effect processing
395
+     * @param {*} effect - Represents the effect instance to use
396
+     * @returns {Promise}
397
+     */
398
+    enableEffect(enableFlag: Boolean, effect) {
399
+        if (this._effectEnabled === enableFlag) {
400
+            return Promise.resolve();
401
+        }
402
+
403
+        if (this.isMuted()) {
404
+            return Promise.resolve();
405
+        }
406
+
407
+        this._effectEnabled = enableFlag;
408
+
409
+        return this._switchStream(enableFlag ? this._startStreamEffect(effect) : this._stopStreamEffect())
410
+                    .catch(error => {
411
+                        if (enableFlag) {
412
+                            this._stopStreamEffect();
413
+                        }
414
+                        this._effectEnabled = false;
415
+                        logger.error('Failed to switch to new stream!', error);
416
+                        throw error;
417
+                    });
418
+    }
419
+
309 420
     /**
310 421
      * Asynchronously mutes this track.
311 422
      *
@@ -371,6 +482,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
371 482
                 this.track.enabled = !muted;
372 483
             }
373 484
         } else if (muted) {
485
+
374 486
             promise = new Promise((resolve, reject) => {
375 487
                 logMuteInfo();
376 488
                 this._removeStreamFromConferenceAsMute(
@@ -385,6 +497,12 @@ export default class JitsiLocalTrack extends JitsiTrack {
385 497
                     },
386 498
                     reject);
387 499
             });
500
+
501
+            promise.then(() => {
502
+                if (this._effectEnabled) {
503
+                    this._stopStreamEffect();
504
+                }
505
+            });
388 506
         } else {
389 507
             logMuteInfo();
390 508
 
@@ -392,6 +510,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
392 510
             const streamOptions = {
393 511
                 cameraDeviceId: this.getDeviceId(),
394 512
                 devices: [ MediaType.VIDEO ],
513
+                effects: this._streamEffect ? [ this._streamEffect ] : [],
395 514
                 facingMode: this.getCameraFacingMode()
396 515
             };
397 516
 
@@ -435,6 +554,10 @@ export default class JitsiLocalTrack extends JitsiTrack {
435 554
                     throw new JitsiTrackError(TRACK_NO_STREAM_FOUND);
436 555
                 }
437 556
 
557
+                if (this._effectEnabled) {
558
+                    this._setStream(this._startStreamEffect(this._streamEffect));
559
+                }
560
+
438 561
                 this.containers.map(
439 562
                     cont => RTCUtils.attachMediaStream(cont, this.stream));
440 563
 
@@ -522,6 +645,10 @@ export default class JitsiLocalTrack extends JitsiTrack {
522 645
      * @returns {Promise}
523 646
      */
524 647
     dispose() {
648
+        if (this._effectEnabled) {
649
+            this._setStream(this._stopStreamEffect());
650
+        }
651
+
525 652
         let promise = Promise.resolve();
526 653
 
527 654
         if (this.conference) {
@@ -679,7 +806,6 @@ export default class JitsiLocalTrack extends JitsiTrack {
679 806
      * Stops the associated MediaStream.
680 807
      */
681 808
     stopStream() {
682
-
683 809
         /**
684 810
          * Indicates that we are executing {@link #stopStream} i.e.
685 811
          * {@link RTCUtils#stopMediaStream} for the <tt>MediaStream</tt>
@@ -751,7 +877,11 @@ export default class JitsiLocalTrack extends JitsiTrack {
751 877
         // we aren't receiving any data from the source. We want to notify
752 878
         // the users for error if the stream is muted or ended on it's
753 879
         // creation.
754
-        return this.stream.getTracks().some(track =>
880
+
881
+        // For video blur enabled use the original video stream
882
+        const stream = this._effectEnabled ? this._originalStream : this.stream;
883
+
884
+        return stream.getTracks().some(track =>
755 885
             (!('readyState' in track) || track.readyState === 'live')
756 886
                 && (!('muted' in track) || track.muted !== true));
757 887
     }

+ 8
- 4
modules/RTC/RTC.js Wyświetl plik

@@ -51,7 +51,8 @@ function createLocalTracks(tracksInfo, options) {
51 51
             ...trackInfo,
52 52
             deviceId,
53 53
             facingMode: options.facingMode,
54
-            rtcId: rtcTrackIdCounter
54
+            rtcId: rtcTrackIdCounter,
55
+            effects: options.effects
55 56
         });
56 57
 
57 58
         newTracks.push(localTrack);
@@ -71,7 +72,8 @@ function createLocalTracks(tracksInfo, options) {
71 72
  *     track: MediaTrack within the MediaStream,
72 73
  *     videoType: "camera" or "desktop" or falsy,
73 74
  *     sourceId: ID of the desktopsharing source,
74
- *     sourceType: The desktopsharing source type
75
+ *     sourceType: The desktopsharing source type,
76
+ *     effects: Array of effect types
75 77
  * }}
76 78
  */
77 79
 function _newCreateLocalTracks(mediaStreamMetaData = []) {
@@ -81,7 +83,8 @@ function _newCreateLocalTracks(mediaStreamMetaData = []) {
81 83
             sourceType,
82 84
             stream,
83 85
             track,
84
-            videoType
86
+            videoType,
87
+            effects
85 88
         } = metaData;
86 89
 
87 90
         const { deviceId, facingMode } = track.getSettings();
@@ -100,7 +103,8 @@ function _newCreateLocalTracks(mediaStreamMetaData = []) {
100 103
             sourceType,
101 104
             stream,
102 105
             track,
103
-            videoType: videoType || null
106
+            videoType: videoType || null,
107
+            effects
104 108
         });
105 109
     });
106 110
 }

+ 4
- 2
modules/RTC/RTCUtils.js Wyświetl plik

@@ -1397,7 +1397,8 @@ class RTCUtils extends Listenable {
1397 1397
 
1398 1398
                 mediaStreamsMetaData.push({
1399 1399
                     stream: audioStream,
1400
-                    track: audioStream.getAudioTracks()[0]
1400
+                    track: audioStream.getAudioTracks()[0],
1401
+                    effects: options.effects
1401 1402
                 });
1402 1403
             }
1403 1404
 
@@ -1409,7 +1410,8 @@ class RTCUtils extends Listenable {
1409 1410
                 mediaStreamsMetaData.push({
1410 1411
                     stream: videoStream,
1411 1412
                     track: videoStream.getVideoTracks()[0],
1412
-                    videoType: VideoType.CAMERA
1413
+                    videoType: VideoType.CAMERA,
1414
+                    effects: options.effects
1413 1415
                 });
1414 1416
             }
1415 1417
         };

Ładowanie…
Anuluj
Zapisz