fix(screenshare): Fixes for the blurry desktop share issues.
Do not resize the desktop share to 720p by default when the desktop track resolution is higher than 720p. This is causing bluriness when presenter is turned on. Remove the 'detail' contentHint setting for the desktop+presenter canvas stream as it forcing chrome to send only 5 fps stream for high resolution desktop tracks. Move the desktop resizing logic behind a config.js option - videoQuality.resizeDesktopForPresenter.
This commit is contained in:
parent
895c92217a
commit
3381cf4422
|
@ -53,6 +53,7 @@ import {
|
||||||
updateDeviceList
|
updateDeviceList
|
||||||
} from './react/features/base/devices';
|
} from './react/features/base/devices';
|
||||||
import {
|
import {
|
||||||
|
browser,
|
||||||
isFatalJitsiConnectionError,
|
isFatalJitsiConnectionError,
|
||||||
JitsiConferenceErrors,
|
JitsiConferenceErrors,
|
||||||
JitsiConferenceEvents,
|
JitsiConferenceEvents,
|
||||||
|
@ -493,9 +494,9 @@ export default {
|
||||||
|
|
||||||
JitsiMeetJS.mediaDevices.addEventListener(
|
JitsiMeetJS.mediaDevices.addEventListener(
|
||||||
JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN,
|
JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN,
|
||||||
browser =>
|
browserName =>
|
||||||
APP.store.dispatch(
|
APP.store.dispatch(
|
||||||
mediaPermissionPromptVisibilityChanged(true, browser))
|
mediaPermissionPromptVisibilityChanged(true, browserName))
|
||||||
);
|
);
|
||||||
|
|
||||||
let tryCreateLocalTracks;
|
let tryCreateLocalTracks;
|
||||||
|
@ -1605,8 +1606,10 @@ export default {
|
||||||
*/
|
*/
|
||||||
async _createPresenterStreamEffect(height = null, cameraDeviceId = null) {
|
async _createPresenterStreamEffect(height = null, cameraDeviceId = null) {
|
||||||
if (!this.localPresenterVideo) {
|
if (!this.localPresenterVideo) {
|
||||||
|
const camera = cameraDeviceId ?? getUserSelectedCameraDeviceId(APP.store.getState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.localPresenterVideo = await createLocalPresenterTrack({ cameraDeviceId }, height);
|
this.localPresenterVideo = await createLocalPresenterTrack({ cameraDeviceId: camera }, height);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to create a camera track for presenter', err);
|
logger.error('Failed to create a camera track for presenter', err);
|
||||||
|
|
||||||
|
@ -1647,37 +1650,39 @@ export default {
|
||||||
|
|
||||||
// Create a new presenter track and apply the presenter effect.
|
// Create a new presenter track and apply the presenter effect.
|
||||||
if (!this.localPresenterVideo && !mute) {
|
if (!this.localPresenterVideo && !mute) {
|
||||||
let { aspectRatio, height } = this.localVideo.track.getSettings();
|
const { height, width } = this.localVideo.track.getSettings() ?? this.localVideo.track.getConstraints();
|
||||||
const { width } = this.localVideo.track.getSettings();
|
|
||||||
let desktopResizeConstraints = {};
|
let desktopResizeConstraints = {};
|
||||||
let resizeDesktopStream = false;
|
let resizeDesktopStream = false;
|
||||||
const DESKTOP_STREAM_CAP = 720;
|
const DESKTOP_STREAM_CAP = 720;
|
||||||
|
|
||||||
// Determine the constraints if the desktop track needs to be resized.
|
// Resizing the desktop track for presenter is causing blurriness of the desktop share.
|
||||||
// Resizing is needed when the resolution cannot be determined or when
|
// Disable this behavior for now until it is fixed in Chrome. The stream needs to be resized
|
||||||
// the window is bigger than 720p.
|
// Firefox always.
|
||||||
if (height && width) {
|
if ((config.videoQuality && config.videoQuality.resizeDesktopForPresenter) || browser.isFirefox()) {
|
||||||
aspectRatio = aspectRatio ?? (width / height).toPrecision(4);
|
// Resizing is needed when the window is bigger than 720p.
|
||||||
const advancedConstraints = [ { aspectRatio } ];
|
if (height && width) {
|
||||||
const isPortrait = height >= width;
|
const advancedConstraints = [ { aspectRatio: (width / height).toPrecision(4) } ];
|
||||||
|
const isPortrait = height >= width;
|
||||||
|
|
||||||
// Determine which dimension needs resizing and resize only that side
|
// Determine which dimension needs resizing and resize only that side
|
||||||
// keeping the aspect ratio same as before.
|
// keeping the aspect ratio same as before.
|
||||||
if (isPortrait && width > DESKTOP_STREAM_CAP) {
|
if (isPortrait && width > DESKTOP_STREAM_CAP) {
|
||||||
|
resizeDesktopStream = true;
|
||||||
|
advancedConstraints.push({ width: DESKTOP_STREAM_CAP });
|
||||||
|
} else if (!isPortrait && height > DESKTOP_STREAM_CAP) {
|
||||||
|
resizeDesktopStream = true;
|
||||||
|
advancedConstraints.push({ height: DESKTOP_STREAM_CAP });
|
||||||
|
}
|
||||||
|
desktopResizeConstraints.advanced = advancedConstraints;
|
||||||
|
} else {
|
||||||
resizeDesktopStream = true;
|
resizeDesktopStream = true;
|
||||||
advancedConstraints.push({ width: DESKTOP_STREAM_CAP });
|
desktopResizeConstraints = {
|
||||||
} else if (!isPortrait && height > DESKTOP_STREAM_CAP) {
|
width: 1280,
|
||||||
resizeDesktopStream = true;
|
height: 720
|
||||||
advancedConstraints.push({ height: DESKTOP_STREAM_CAP });
|
};
|
||||||
}
|
}
|
||||||
desktopResizeConstraints.advanced = advancedConstraints;
|
|
||||||
} else {
|
|
||||||
resizeDesktopStream = true;
|
|
||||||
desktopResizeConstraints = {
|
|
||||||
width: 1280,
|
|
||||||
height: 720
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resizeDesktopStream) {
|
if (resizeDesktopStream) {
|
||||||
try {
|
try {
|
||||||
await this.localVideo.track.applyConstraints(desktopResizeConstraints);
|
await this.localVideo.track.applyConstraints(desktopResizeConstraints);
|
||||||
|
@ -1686,14 +1691,15 @@ export default {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
height = this.localVideo.track.getSettings().height ?? DESKTOP_STREAM_CAP;
|
|
||||||
}
|
}
|
||||||
|
const trackHeight = resizeDesktopStream
|
||||||
|
? this.localVideo.track.getSettings().height ?? DESKTOP_STREAM_CAP
|
||||||
|
: height;
|
||||||
const defaultCamera = getUserSelectedCameraDeviceId(APP.store.getState());
|
const defaultCamera = getUserSelectedCameraDeviceId(APP.store.getState());
|
||||||
let effect;
|
let effect;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
effect = await this._createPresenterStreamEffect(height,
|
effect = await this._createPresenterStreamEffect(trackHeight, defaultCamera);
|
||||||
defaultCamera);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to unmute Presenter Video');
|
logger.error('Failed to unmute Presenter Video');
|
||||||
maybeShowErrorDialog(err);
|
maybeShowErrorDialog(err);
|
||||||
|
|
|
@ -275,9 +275,13 @@ var config = {
|
||||||
// // at least 360 pixels tall. If the thumbnail height reaches 720 pixels then the application will switch to
|
// // at least 360 pixels tall. If the thumbnail height reaches 720 pixels then the application will switch to
|
||||||
// // the high quality.
|
// // the high quality.
|
||||||
// minHeightForQualityLvl: {
|
// minHeightForQualityLvl: {
|
||||||
// 360: 'standard,
|
// 360: 'standard',
|
||||||
// 720: 'high'
|
// 720: 'high'
|
||||||
// }
|
// },
|
||||||
|
//
|
||||||
|
// // Provides a way to resize the desktop track to 720p (if it is greater than 720p) before creating a canvas
|
||||||
|
// // for the presenter mode (camera picture-in-picture mode with screenshare).
|
||||||
|
// resizeDesktopForPresenter: false
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// // Options for the recording limit notification.
|
// // Options for the recording limit notification.
|
||||||
|
|
|
@ -10771,8 +10771,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib-jitsi-meet": {
|
"lib-jitsi-meet": {
|
||||||
"version": "github:jitsi/lib-jitsi-meet#6bb0b86c0a7dd22bb5798236d9b80ca578b28d21",
|
"version": "github:jitsi/lib-jitsi-meet#3ed4e3caeeaba37f8eae6854b1b7dc9c334adba7",
|
||||||
"from": "github:jitsi/lib-jitsi-meet#6bb0b86c0a7dd22bb5798236d9b80ca578b28d21",
|
"from": "github:jitsi/lib-jitsi-meet#3ed4e3caeeaba37f8eae6854b1b7dc9c334adba7",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@jitsi/js-utils": "1.0.2",
|
"@jitsi/js-utils": "1.0.2",
|
||||||
"@jitsi/sdp-interop": "1.0.3",
|
"@jitsi/sdp-interop": "1.0.3",
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"jquery-i18next": "1.2.1",
|
"jquery-i18next": "1.2.1",
|
||||||
"js-md5": "0.6.1",
|
"js-md5": "0.6.1",
|
||||||
"jwt-decode": "2.2.0",
|
"jwt-decode": "2.2.0",
|
||||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#6bb0b86c0a7dd22bb5798236d9b80ca578b28d21",
|
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#3ed4e3caeeaba37f8eae6854b1b7dc9c334adba7",
|
||||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||||
"lodash": "4.17.19",
|
"lodash": "4.17.19",
|
||||||
"moment": "2.19.4",
|
"moment": "2.19.4",
|
||||||
|
|
|
@ -141,14 +141,7 @@ export default class JitsiStreamPresenterEffect {
|
||||||
timeMs: 1000 / this._frameRate
|
timeMs: 1000 / this._frameRate
|
||||||
});
|
});
|
||||||
|
|
||||||
const capturedStream = this._canvas.captureStream(this._frameRate);
|
return this._canvas.captureStream(this._frameRate);
|
||||||
|
|
||||||
// Put emphasis on the text details for the presenter's stream
|
|
||||||
// See https://www.w3.org/TR/mst-content-hint/
|
|
||||||
// $FlowExpectedError
|
|
||||||
capturedStream.getVideoTracks()[0].contentHint = 'text';
|
|
||||||
|
|
||||||
return capturedStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue