I'm trying to get a screen to stream to my Angular 5 Electron app. I'm using the desktopCapturer provided by Electron. This is my code:
loadCurrentScreensource() {
desktopCapturer.getSources({
types: [
'window',
'screen'
]
}, (error, sources) => {
if (error) {
throw error;
}
console.log('Finding screen: ' + this.selectedScreenSource);
console.log(sources);
for (let i = 0; i < sources.length; ++i) {
if (sources[i].id === this.selectedScreenSource.id) {
console.log('Found screen');
const constraints = {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sources[i].id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
};
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => this.handleStream(stream))
.catch((e) => this.handleError(e));
return;
}
}
}
);
}
According to the documentation here, I need to use the mandatory part of the constraints to get the correct stream. However, TypeScript gives me the error that the types of property 'video' are incompatible. If I enter the following constraints I sometimes get a stream of my webcam:
{ width: 1280, height: 720 }
The docs at mozzilla.org never mention the mandatory part, so I guess I overlooked some import or something to get getUserMedia to accept my constraints. Either that, or maybe getUserMedia has been changed, but the docs didn't?
What am I doing wrong here?
[edit]
Also, the documentation for MediaTrackConstraints does not have the mandatory, nor the chromeMediaSourceId properties. This is however, the same documentation that Electron links to.
[edit2]
I found the deviceId constraint, which I previously overlooked. When I use the following constraints, I still get the webcam stream though.
video: {
width: 1280,
height: 720,
deviceId: this.selectedScreenSource.id
}
getUserMedia() Deprecated: This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes.
getUserMedia() method prompts the user for permission to use a media input which produces a MediaStream with tracks containing the requested types of media.
getDisplayMedia() The MediaDevices interface's getDisplayMedia() method prompts the user to select and grant permission to capture the contents of a display or portion thereof (such as a window) as a MediaStream .
In a previous blog post we’ve focused on the audio constraints. The getUserMedia () function receives only one parameter, a MediaStreamConstraints object used to specify what kind of tracks (audio, video or both) to request, and, optionally, any requirements for each track.
Chrome will throw a “TypeError: Failed to execute ‘getUserMedia’ on ‘MediaDevices’: At least one of audio and video must be requested”. It’s thrown by Chrome when the user closes the privacy dialog asking for mic and webcam access.
The error object will also mention the constraint that could not be satisfied through the constraintName property and the message “Constraints could be not satisfied.”. Is thrown when the user denies (or has previously denied) access to the webcam or microphone.
The getUserMedia() method is only available in secure contexts. A secure context is one the browser is reasonably confident contains a document which was loaded securely, using HTTPS/TLS, and has limited exposure to insecure contexts.
@Scuba Kay I can suggest you the workaround. You can just replace
navigator.mediaDevices.getUserMedia(constraints)
with
(<any> navigator.mediaDevices).getUserMedia(constraints)
It will work.
To add a little more context about @Manthan Makani his solution, check out: https://github.com/microsoft/TypeScript/issues/22897
TS follows the latest WebRTC specification. Each browser can have differences in API as WebRTC specification is not an official standard yet.
Chrome seems to follow a deviating standard still. So it can be solved by defining mediaDevices
as 'any' and define your own methods that coincide with Chrome's implementation. This will satisfy the Typescript compiler. Note: we follow Chrome's implementation specifically because Electron runs on the Chromium browser.
const mediaDevices = navigator.mediaDevices as any;
mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id,
minWidth: 1280,
maxWidth: 1280,
minHeight: 720,
maxHeight: 720
}
}
}).then((stream: MediaStream) => {
// do stuff
stream.getTracks()[0].stop();
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With