fix(iframe): Use largeVideo video element for screenshot.
Get the existing HTMLVideoElement for large video instead of creating a new video element for capturing the screenshot. This should prevent the video player from getting displayed on mobile Safari.
This commit is contained in:
parent
7a9a6855b7
commit
09124ad7e9
|
@ -639,8 +639,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
|||
/**
|
||||
* Captures the screenshot of the large video.
|
||||
*
|
||||
* @returns {dataURL} - Base64 encoded image data of the screenshot if large
|
||||
* video is detected, an error otherwise.
|
||||
* @returns {Promise<string>} - Resolves with a base64 encoded image data of the screenshot
|
||||
* if large video is detected, an error otherwise.
|
||||
*/
|
||||
captureLargeVideoScreenshot() {
|
||||
return this._transport.sendRequest({
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
import { _handleParticipantError } from '../base/conference';
|
||||
import { MEDIA_TYPE } from '../base/media';
|
||||
import { getParticipants } from '../base/participants';
|
||||
import { getTrackByMediaTypeAndParticipant } from '../base/tracks';
|
||||
import { reportError } from '../base/util';
|
||||
import { shouldDisplayTileView } from '../video-layout';
|
||||
|
||||
|
@ -18,57 +17,6 @@ import {
|
|||
UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* Captures a screenshot of the video displayed on the large video.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function captureLargeVideoScreenshot() {
|
||||
return (dispatch: Dispatch<any>, getState: Function): Promise<Object> => {
|
||||
const state = getState();
|
||||
const largeVideo = state['features/large-video'];
|
||||
|
||||
if (!largeVideo) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const tracks = state['features/base/tracks'];
|
||||
const { jitsiTrack } = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId);
|
||||
const videoStream = jitsiTrack.getOriginalStream();
|
||||
|
||||
// Create a HTML canvas and draw video from the track on to the canvas.
|
||||
const [ track ] = videoStream.getVideoTracks();
|
||||
const { height, width } = track.getSettings() ?? track.getConstraints();
|
||||
const canvasElement = document.createElement('canvas');
|
||||
const ctx = canvasElement.getContext('2d');
|
||||
const videoElement = document.createElement('video');
|
||||
|
||||
videoElement.height = parseInt(height, 10);
|
||||
videoElement.width = parseInt(width, 10);
|
||||
videoElement.autoplay = true;
|
||||
videoElement.srcObject = videoStream;
|
||||
canvasElement.height = videoElement.height;
|
||||
canvasElement.width = videoElement.width;
|
||||
|
||||
// Wait for the video to load before drawing on to the canvas.
|
||||
const promise = new Promise(resolve => {
|
||||
videoElement.onloadeddata = () => resolve();
|
||||
});
|
||||
|
||||
return promise.then(() => {
|
||||
ctx.drawImage(videoElement, 0, 0, videoElement.width, videoElement.height);
|
||||
const dataURL = canvasElement.toDataURL('image/png', 1.0);
|
||||
|
||||
// Cleanup.
|
||||
ctx.clearRect(0, 0, videoElement.width, videoElement.height);
|
||||
videoElement.srcObject = null;
|
||||
canvasElement.remove();
|
||||
videoElement.remove();
|
||||
|
||||
return Promise.resolve(dataURL);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals conference to select a participant.
|
||||
*
|
||||
|
|
|
@ -3,9 +3,56 @@
|
|||
import type { Dispatch } from 'redux';
|
||||
|
||||
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout';
|
||||
import { MEDIA_TYPE } from '../base/media';
|
||||
import { getTrackByMediaTypeAndParticipant } from '../base/tracks';
|
||||
|
||||
export * from './actions.any';
|
||||
|
||||
/**
|
||||
* Captures a screenshot of the video displayed on the large video.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function captureLargeVideoScreenshot() {
|
||||
return (dispatch: Dispatch<any>, getState: Function): Promise<string> => {
|
||||
const state = getState();
|
||||
const largeVideo = state['features/large-video'];
|
||||
|
||||
if (!largeVideo) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const tracks = state['features/base/tracks'];
|
||||
const { jitsiTrack } = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId);
|
||||
const videoStream = jitsiTrack.getOriginalStream();
|
||||
|
||||
// Get the video element for the large video, cast HTMLElement to HTMLVideoElement to make flow happy.
|
||||
/* eslint-disable-next-line no-extra-parens*/
|
||||
const videoElement = ((document.getElementById('largeVideo'): any): HTMLVideoElement);
|
||||
|
||||
if (!videoElement) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Create a HTML canvas and draw video on to the canvas.
|
||||
const [ track ] = videoStream.getVideoTracks();
|
||||
const { height, width } = track.getSettings() ?? track.getConstraints();
|
||||
const canvasElement = document.createElement('canvas');
|
||||
const ctx = canvasElement.getContext('2d');
|
||||
|
||||
canvasElement.style.display = 'none';
|
||||
canvasElement.height = parseInt(height, 10);
|
||||
canvasElement.width = parseInt(width, 10);
|
||||
ctx.drawImage(videoElement, 0, 0);
|
||||
const dataURL = canvasElement.toDataURL('image/png', 1.0);
|
||||
|
||||
// Cleanup.
|
||||
ctx.clearRect(0, 0, canvasElement.width, canvasElement.height);
|
||||
canvasElement.remove();
|
||||
|
||||
return Promise.resolve(dataURL);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the large video container based on the dimensions provided.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue