Selaa lähdekoodia

feat(iFrame): Add a method for capturing screenshot of the large video (#7717)

j8
Jaya Allamsetty 4 vuotta sitten
vanhempi
commit
1d5decc14f
No account linked to committer's email address
3 muutettua tiedostoa jossa 86 lisäystä ja 3 poistoa
  1. 20
    1
      modules/API/API.js
  2. 12
    0
      modules/API/external/external_api.js
  3. 54
    2
      react/features/large-video/actions.js

+ 20
- 1
modules/API/API.js Näytä tiedosto

@@ -21,7 +21,11 @@ import {
21 21
 import { isEnabled as isDropboxEnabled } from '../../react/features/dropbox';
22 22
 import { toggleE2EE } from '../../react/features/e2ee/actions';
23 23
 import { invite } from '../../react/features/invite';
24
-import { resizeLargeVideo, selectParticipantInLargeVideo } from '../../react/features/large-video/actions';
24
+import {
25
+    captureLargeVideoScreenshot,
26
+    resizeLargeVideo,
27
+    selectParticipantInLargeVideo
28
+} from '../../react/features/large-video/actions';
25 29
 import { toggleLobbyMode } from '../../react/features/lobby/actions.web';
26 30
 import { RECORDING_TYPES } from '../../react/features/recording/constants';
27 31
 import { getActiveSession } from '../../react/features/recording/functions';
@@ -339,6 +343,21 @@ function initCommands() {
339 343
         const { name } = request;
340 344
 
341 345
         switch (name) {
346
+        case 'capture-largevideo-screenshot' :
347
+            APP.store.dispatch(captureLargeVideoScreenshot())
348
+                .then(dataURL => {
349
+                    let error;
350
+
351
+                    if (!dataURL) {
352
+                        error = new Error('No large video found!');
353
+                    }
354
+
355
+                    callback({
356
+                        error,
357
+                        dataURL
358
+                    });
359
+                });
360
+            break;
342 361
         case 'invite': {
343 362
             const { invitees } = request;
344 363
 

+ 12
- 0
modules/API/external/external_api.js Näytä tiedosto

@@ -636,6 +636,18 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
636 636
         }
637 637
     }
638 638
 
639
+    /**
640
+     * Captures the screenshot of the large video.
641
+     *
642
+     * @returns {dataURL} - Base64 encoded image data of the screenshot if large
643
+     * video is detected, an error otherwise.
644
+     */
645
+    captureLargeVideoScreenshot() {
646
+        return this._transport.sendRequest({
647
+            name: 'capture-largevideo-screenshot'
648
+        });
649
+    }
650
+
639 651
     /**
640 652
      * Removes the listeners and removes the Jitsi Meet frame.
641 653
      *

+ 54
- 2
react/features/large-video/actions.js Näytä tiedosto

@@ -10,6 +10,7 @@ import {
10 10
 import { _handleParticipantError } from '../base/conference';
11 11
 import { MEDIA_TYPE } from '../base/media';
12 12
 import { getParticipants } from '../base/participants';
13
+import { getTrackByMediaTypeAndParticipant } from '../base/tracks';
13 14
 import { reportError } from '../base/util';
14 15
 import { shouldDisplayTileView } from '../video-layout';
15 16
 
@@ -20,12 +21,63 @@ import {
20 21
 
21 22
 declare var APP: Object;
22 23
 
24
+/**
25
+* Captures a screenshot of the video displayed on the large video.
26
+*
27
+* @returns {Function}
28
+*/
29
+export function captureLargeVideoScreenshot() {
30
+    return (dispatch: Dispatch<any>, getState: Function): Promise<Object> => {
31
+        const state = getState();
32
+        const largeVideo = state['features/large-video'];
33
+
34
+        if (!largeVideo) {
35
+            return Promise.resolve();
36
+        }
37
+        const tracks = state['features/base/tracks'];
38
+        const { jitsiTrack } = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId);
39
+        const videoStream = jitsiTrack.getOriginalStream();
40
+
41
+        // Create a HTML canvas and draw video from the track on to the canvas.
42
+        const [ track ] = videoStream.getVideoTracks();
43
+        const { height, width } = track.getSettings() ?? track.getConstraints();
44
+        const canvasElement = document.createElement('canvas');
45
+        const ctx = canvasElement.getContext('2d');
46
+        const videoElement = document.createElement('video');
47
+
48
+        videoElement.height = parseInt(height, 10);
49
+        videoElement.width = parseInt(width, 10);
50
+        videoElement.autoplay = true;
51
+        videoElement.srcObject = videoStream;
52
+        canvasElement.height = videoElement.height;
53
+        canvasElement.width = videoElement.width;
54
+
55
+        // Wait for the video to load before drawing on to the canvas.
56
+        const promise = new Promise(resolve => {
57
+            videoElement.onloadeddata = () => resolve();
58
+        });
59
+
60
+        return promise.then(() => {
61
+            ctx.drawImage(videoElement, 0, 0, videoElement.width, videoElement.height);
62
+            const dataURL = canvasElement.toDataURL('image/png', 1.0);
63
+
64
+            // Cleanup.
65
+            ctx.clearRect(0, 0, videoElement.width, videoElement.height);
66
+            videoElement.srcObject = null;
67
+            canvasElement.remove();
68
+            videoElement.remove();
69
+
70
+            return Promise.resolve(dataURL);
71
+        });
72
+    };
73
+}
74
+
23 75
 /**
24 76
  * Resizes the large video container based on the dimensions provided.
25 77
  *
26 78
  * @param {number} width - Width that needs to be applied on the large video container.
27 79
  * @param {number} height - Height that needs to be applied on the large video container.
28
- * @returns {void}
80
+ * @returns {Function}
29 81
  */
30 82
 export function resizeLargeVideo(width: number, height: number) {
31 83
     return (dispatch: Dispatch<any>, getState: Function) => {
@@ -72,7 +124,7 @@ export function selectParticipant() {
72 124
 
73 125
 /**
74 126
  * Action to select the participant to be displayed in LargeVideo based on the
75
- * participant id provided. If a partcipant id is not provided, the LargeVideo
127
+ * participant id provided. If a participant id is not provided, the LargeVideo
76 128
  * participant will be selected based on a variety of factors: If there is a
77 129
  * dominant or pinned speaker, or if there are remote tracks, etc.
78 130
  *

Loading…
Peruuta
Tallenna