Electron+React+WebRTC screen sharing (2): get video stream

In the last chapter of the book, a usable Electron+React+WebRTC development environment has been established last time. This time, we focus on the problem of obtaining video streams.

Mobx management status

I use mobx to extract the internal state data of the React component. This has two advantages, one is to facilitate state sharing, and the other is to write logic outside the component.

 import { observable } from "mobx"; let rtcState = observable({ sources:[], sourceId:-1, mediaStream:null, SetAllSources :function(sources){ //Zimiao haunting blog (azimiao. com) sets all source references this.sources.replace(sources); }, SetChoseId : function(index){ //Set the selected id zi to haunt the blog (azimiao. com) try { this.sourceId = this.sources[index].id; return true; } catch (error) { // throw error; //Blog return false; } }, GetMediaStream : function(){ //Get video stream }, Clear:function(){ //Clear information this.sources = []; this.sourceId = -1; this.mediaStream = null; } }); export {rtcState}

Electron gets the WebRTC window list

We know that browsers can navigator.mediaDevices.getUserMedia Get the video stream, and a few lines of code can fix it:

 navigator.mediaDevices.getUserMedia({ audio:true, video:true }).then((source)=>{ console.log(source); }).catch(e=>{ alert(e);// Zimiao haunting blog (azimiao. com) })

However, when executing the above code, there will be an application prompt, as shown in the following figure:

We do not want the application to pop up such a selection window, but should display all source windows in the application for users to choose.

Electron provides desktopCapturer Object, through which we can obtain DesktopCapturerSource Array, and DesktopCapturerSource The properties are as follows:

 { //An identifier of a window or screen, //When calling [navigator. webkitGetUserMedia], you can use [Zimiao Blog (azimiao. com)] as the chromeMediaSourceId constraint. //The identifier format is: window: XX or screen: XX. XX is a randomly generated number id:"screen:0:0", //The screen source will be named Entire Screen or Screen<index>, and the name of the window source will match the window title name:"Screen 0", //Thumbnail thumbnail:NativeImage, display_id:"0", appIcon:NativeImage }

So, by desktopCapturer You can get the name chromeMediaSourceId , thumbnail , and then the source window list can be generated. The corresponding code is as follows:

 desktopCapturer.getSources({ types: ["window", 'screen'] }).then((sources) => { rtcState.SetAllSources(sources); }).catch((err) => { alert("Error:" + err); })

Then, when clicking the corresponding window navigator.mediaDevices.getUserMedia use chromeMediaSourceId You can get the media stream.

 //rtcState.jsx GetMediaStream : function(){ return  navigator.mediaDevices.getUserMedia({ audio:{ mandatory:{ chromeMediaSource:"desktop" } },//A | z | m | i | a | o |. c-o-m video:{ mandatory:{ chromeMediaSource:"desktop", chromeMediaSourceId:rtcState.sourceId, minWidth:640, maxWidth:1920, minHeight:360, maxHeight:1080 } } }); },

React component

Automatic monitoring through mobx rtcState.sources , render the corresponding list:

 render() { if (! Array.isArray(rtcState.sources) || rtcState.sources.length <= 0) { return ( <div className="content"> <h4><center>Now Fecth All Screen</center></h4> </div> ); } return (<div className="content">{rtcState.sources.map((e, index) => { var thumb = e.thumbnail.toDataURL(); if (thumb) { return <PrevScreen key={e.name} sourceId={index} imgUrl={thumb} title={e.name} onItemClick={this.onItemClick} /> } })} </div>) }

The effect is as follows:

Sub assembly PrevScreen adopt onItemClick The corresponding sourceId Pass it back.

 onItemClick(index) { if(rtcState. SetChoseId(index)){ console.log("try to jump start share"); //The state machine defined in the topmost component is used to switch different sub components this.props.entryCallBack("testshow"); } }

Finally, when rtcState.SetChoseId After success, we jump to testshow Interface. stay testshow In the interface, directly obtain the video stream and play it:

 constructor(props){ super(props); this.state = {}; this.getSomething = this.getSomething.bind(this); this.getSomething();// Zimiao haunting blog (azimiao. com) } render(){ return( <video style={{maxWidth:100 + "%",maxHeight:"auto"}} id="testId"></video> ) } getSomething(){ rtcState.GetMediaStream().then((stream)=>{ document.getElementById("testId").srcObject = stream; document.getElementById("testId").play(); }). catch (e=>{//Zimiao haunting blog (azimiao. com) console.log(e); }) }

The effect is as shown in the following figure (change the audio of the acquired stream to false during the local test, otherwise the sound will be collected and played circularly):

All right, so far, the core content of getting video streams has been covered.

Zimiao haunting blog (azimiao. com) All rights reserved. Please note the link when reprinting: https://www.azimiao.com/6396.html
Welcome to the Zimiao haunting blog exchange group: three hundred and thirteen million seven hundred and thirty-two thousand

Comment

*

*

Comment area

  1. Wait for the owner to update