Feature screen sharing

- Send stream of screen sharing in peer connexion
 - Add button for share your screen
This commit is contained in:
Gregoire Parant 2020-06-06 17:03:10 +02:00 committed by David Négrier
parent e1989c1c21
commit 208b91e52a
6 changed files with 174 additions and 31 deletions

View file

@ -5,6 +5,9 @@ const videoConstraint: boolean|MediaTrackConstraints = {
height: { ideal: 720 },
facingMode: "user"
};
interface MediaServiceInterface extends MediaDevices{
getDisplayMedia(constrain: any) : Promise<any>;
}
type UpdatedLocalStreamCallback = (media: MediaStream) => void;
@ -12,10 +15,13 @@ type UpdatedLocalStreamCallback = (media: MediaStream) => void;
// TODO: verify that microphone event listeners are not triggered plenty of time NOW (since MediaManager is created many times!!!!)
export class MediaManager {
localStream: MediaStream|null = null;
localScreenCapture: MediaStream|null = null;
private remoteVideo: Map<string, HTMLVideoElement> = new Map<string, HTMLVideoElement>();
myCamVideo: HTMLVideoElement;
cinemaClose: HTMLImageElement;
cinema: HTMLImageElement;
monitorClose: HTMLImageElement;
monitor: HTMLImageElement;
microphoneClose: HTMLImageElement;
microphone: HTMLImageElement;
webrtcInAudio: HTMLAudioElement;
@ -57,6 +63,21 @@ export class MediaManager {
this.disabledCamera();
//update tracking
});
this.monitorClose = document.getElementById('monitor-close');
this.monitorClose.style.display = "block";
this.monitorClose.addEventListener('click', (e: any) => {
e.preventDefault();
this.enabledMonitor();
//update tracking
});
this.monitor = document.getElementById('monitor');
this.monitor.style.display = "none";
this.monitor.addEventListener('click', (e: any) => {
e.preventDefault();
this.disabledMonitor();
//update tracking
});
}
onUpdateLocalStream(callback: UpdatedLocalStreamCallback): void {
@ -126,6 +147,58 @@ export class MediaManager {
});
}
enabledMonitor() {
this.monitorClose.style.display = "none";
this.monitor.style.display = "block";
this.getScreenMedia().then((stream) => {
this.updatedLocalStreamCallBack(stream);
});
}
disabledMonitor() {
this.monitorClose.style.display = "block";
this.monitor.style.display = "none";
this.localScreenCapture?.getTracks().forEach((track: MediaStreamTrack) => {
track.stop();
});
this.localScreenCapture = null;
this.getCamera().then((stream) => {
this.updatedLocalStreamCallBack(stream);
});
}
//get screen
getScreenMedia() : Promise<MediaStream>{
try {
return this._startScreenCapture()
.then((stream: MediaStream) => {
this.localScreenCapture = stream;
return stream;
})
.catch((err: any) => {
console.error("Error => getScreenMedia => " + err);
throw err;
});
}catch (err) {
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
reject(err);
});
}
}
private _startScreenCapture() {
if ((navigator as any).getDisplayMedia) {
return (navigator as any).getDisplayMedia({video: true});
} else if ((navigator.mediaDevices as any).getDisplayMedia) {
return (navigator.mediaDevices as any).getDisplayMedia({video: true});
} else {
//return navigator.mediaDevices.getUserMedia(({video: {mediaSource: 'screen'}} as any));
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
reject("error sharing screen");
});
}
}
//get camera
async getCamera(): Promise<MediaStream> {
if (navigator.mediaDevices === undefined) {

View file

@ -156,22 +156,11 @@ export class SimplePeer {
videoActive = true;
}
});
if(microphoneActive){
mediaManager.enabledMicrophoneByUserId(user.userId);
}else{
mediaManager.disabledMicrophoneByUserId(user.userId);
}
if(videoActive){
mediaManager.enabledVideoByUserId(user.userId);
}else{
mediaManager.disabledVideoByUserId(user.userId);
}
this.stream(user.userId, stream);
});
/*peer.on('track', (track: MediaStreamTrack, stream: MediaStream) => {
this.stream(user.userId, stream);
});*/
peer.on('close', () => {
@ -190,9 +179,19 @@ export class SimplePeer {
});
peer.on('data', (chunk: Buffer) => {
const data = JSON.parse(chunk.toString('utf8'));
if(data.type === "stream"){
this.stream(user.userId, data.stream);
let constraint = JSON.parse(chunk.toString('utf8'));
if (constraint.audio) {
mediaManager.enabledMicrophoneByUserId(user.userId);
} else {
mediaManager.disabledMicrophoneByUserId(user.userId);
}
if (constraint.video) {
mediaManager.enabledVideoByUserId(user.userId);
} else {
this.stream(user.userId);
mediaManager.disabledVideoByUserId(user.userId);
}
});
@ -279,7 +278,7 @@ export class SimplePeer {
* @param userId
* @param stream
*/
private stream(userId : string, stream: MediaStream) {
private stream(userId : string, stream?: MediaStream) {
if(!stream){
mediaManager.disabledVideoByUserId(userId);
mediaManager.disabledMicrophoneByUserId(userId);
@ -294,24 +293,21 @@ export class SimplePeer {
*/
private addMedia (userId : string) {
try {
const localStream: MediaStream|null = mediaManager.localStream;
const peer = this.PeerConnectionArray.get(userId);
if(localStream === null) {
//send fake signal
if(peer === undefined){
return;
}
peer.write(new Buffer(JSON.stringify({
type: "stream",
stream: null
})));
return;
}
let localStream: MediaStream | null = mediaManager.localStream;
let localScreenCapture: MediaStream | null = mediaManager.localScreenCapture;
let peer = this.PeerConnectionArray.get(userId);
if (peer === undefined) {
throw new Error('While adding media, cannot find user with ID '+userId);
throw new Error('While adding media, cannot find user with ID ' + userId);
}
for (const track of localStream.getTracks()) {
peer.addTrack(track, localStream);
peer.write(new Buffer(JSON.stringify(mediaManager.constraintsMedia)));
if (localScreenCapture !== null) {
for (const track of localScreenCapture.getTracks()) {
peer.addTrack(track, localScreenCapture);
}
} else if (localStream) {
for (const track of localStream.getTracks()) {
peer.addTrack(track, localStream);
}
}
}catch (e) {
console.error(`addMedia => addMedia => ${userId}`, e);