Add minimum frame rate constraint for screen share

This commit is contained in:
automated-signal 2024-10-16 12:48:18 -05:00 committed by GitHub
parent ee1e15646b
commit a23d107343
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 20 deletions

8
package-lock.json generated
View file

@ -14,7 +14,7 @@
"@formatjs/icu-messageformat-parser": "2.3.0",
"@formatjs/intl-localematcher": "0.2.32",
"@indutny/dicer": "0.3.2",
"@indutny/mac-screen-share": "1.0.11",
"@indutny/mac-screen-share": "1.0.13",
"@indutny/range-finder": "1.3.4",
"@indutny/simple-windows-notifications": "2.0.7",
"@indutny/sneequals": "4.0.0",
@ -4086,9 +4086,9 @@
}
},
"node_modules/@indutny/mac-screen-share": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@indutny/mac-screen-share/-/mac-screen-share-1.0.11.tgz",
"integrity": "sha512-0UHiWyUBYn3VjjwpaS0nD6bppunyaTdFGXU84uGmzlV1R9RYcXQOF4EDCWQLpMlw4TieLOBvsh10gLEP116MPw==",
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/@indutny/mac-screen-share/-/mac-screen-share-1.0.13.tgz",
"integrity": "sha512-fCOYWGaIuZAwfk/eUUjqPKge4+PKKCwTsuH9SSoaBZMP8IsWQtyyrTVpeuq84oDren4b9EUgRGgh2t950sQA0w==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {

View file

@ -98,7 +98,7 @@
"@formatjs/icu-messageformat-parser": "2.3.0",
"@formatjs/intl-localematcher": "0.2.32",
"@indutny/dicer": "0.3.2",
"@indutny/mac-screen-share": "1.0.11",
"@indutny/mac-screen-share": "1.0.13",
"@indutny/range-finder": "1.3.4",
"@indutny/simple-windows-notifications": "2.0.7",
"@indutny/sneequals": "4.0.0",

View file

@ -18,6 +18,8 @@ import { strictAssert } from './assert';
import { explodePromise } from './explodePromise';
import { isNotNil } from './isNotNil';
import { drop } from './drop';
import { SECOND } from './durations';
import { isOlderThan } from './timestamp';
// Chrome-only API for now, thus a declaration:
declare class MediaStreamTrackGenerator extends MediaStreamTrack {
@ -176,19 +178,26 @@ export class DesktopCapturer {
liveCapturers.add(this);
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: {
width: {
max: REQUESTED_SCREEN_SHARE_WIDTH,
ideal: REQUESTED_SCREEN_SHARE_WIDTH,
},
height: {
max: REQUESTED_SCREEN_SHARE_HEIGHT,
ideal: REQUESTED_SCREEN_SHARE_HEIGHT,
},
frameRate: {
max: REQUESTED_SCREEN_SHARE_FRAMERATE,
ideal: REQUESTED_SCREEN_SHARE_FRAMERATE,
},
video: true,
});
const videoTrack = stream.getVideoTracks()[0];
strictAssert(videoTrack, 'videoTrack does not exist');
// Apply constraints and ensure that there is at least 1 frame per second.
await videoTrack.applyConstraints({
width: {
max: REQUESTED_SCREEN_SHARE_WIDTH,
ideal: REQUESTED_SCREEN_SHARE_WIDTH,
},
height: {
max: REQUESTED_SCREEN_SHARE_HEIGHT,
ideal: REQUESTED_SCREEN_SHARE_HEIGHT,
},
frameRate: {
min: 1,
max: REQUESTED_SCREEN_SHARE_FRAMERATE,
ideal: REQUESTED_SCREEN_SHARE_FRAMERATE,
},
});
@ -222,6 +231,20 @@ export class DesktopCapturer {
let isRunning = false;
let lastFrame: VideoFrame | undefined;
let lastFrameSentAt = 0;
let frameRepeater: NodeJS.Timeout | undefined;
const cleanup = () => {
lastFrame?.close();
if (frameRepeater != null) {
clearInterval(frameRepeater);
}
frameRepeater = undefined;
lastFrame = undefined;
};
const stream = new macScreenShare.Stream({
width: REQUESTED_SCREEN_SHARE_WIDTH,
height: REQUESTED_SCREEN_SHARE_HEIGHT,
@ -230,6 +253,17 @@ export class DesktopCapturer {
onStart: () => {
isRunning = true;
// Repeat last frame every second to match "min" constraint above.
frameRepeater = setInterval(() => {
if (isRunning && track.readyState !== 'ended' && lastFrame != null) {
if (isOlderThan(lastFrameSentAt, SECOND)) {
drop(writer.write(lastFrame.clone()));
}
} else {
cleanup();
}
}, SECOND);
this.options.onMediaStream(mediaStream);
},
onStop() {
@ -253,13 +287,15 @@ export class DesktopCapturer {
return;
}
const videoFrame = new VideoFrame(frame, {
lastFrame?.close();
lastFrameSentAt = Date.now();
lastFrame = new VideoFrame(frame, {
format: 'NV12',
codedWidth: width,
codedHeight: height,
timestamp: 0,
});
drop(writer.write(videoFrame));
drop(writer.write(lastFrame.clone()));
},
});