node.jssocket.iowebrtcscreensharing

Node.js webRTC screen shareing


I have got problem with webRTC screen sharing. When one person shares his screen another person can`t see shared screen stream, and asks him for again sharing screen.I am useing node.js express server with socket.io. I am useing Google chrome. It requires HTTPS connection if it is not local.

This is web application code`

(function() {
      const socket = io.connect(window.location.origin);
      const localVideo = document.querySelector('.localVideo');
      const remoteVideos = document.querySelector('.remoteVideos');
      const peerConnections = {};
      var url_string =window.location.href
      var url = new URL(url_string);
      var de = url.searchParams.get("key");
      let room = de
      let getUserMediaAttempts = 5;
      let gettingUserMedia = false;
      let getdisplaymedia=true;
      const config = {
        'iceServers': [{
          'urls': ['stun:stun.l.google.com:19302']
        }]
      };
      /** @type {MediaStreamConstraints} */
      const constraints = {
        audio: true,
        video: { facingMode: "user" }
      };
      socket.on('bye', function(id) {
        handleRemoteHangup(id);
      });
    
      if (room && !!room) {
        socket.emit('join', room);
      }
    
      window.onunload = window.onbeforeunload = function() {
        socket.close();
      };
    
      socket.on('ready', function (id) {
        if (!(localVideo instanceof HTMLVideoElement) || !localVideo.srcObject) {
          return;
        }
        const peerConnection = new RTCPeerConnection(config);
        peerConnections[id] = peerConnection;
        if (localVideo instanceof HTMLVideoElement) {
          peerConnection.addStream(localVideo.srcObject);
        }
        peerConnection.createOffer()
        .then(sdp => peerConnection.setLocalDescription(sdp))
        .then(function () {
          socket.emit('offer', id, peerConnection.localDescription);
        });
        peerConnection.onaddstream = event => handleRemoteStreamAdded(event.stream, id);
        peerConnection.onicecandidate = function(event) {
          if (event.candidate) {
            socket.emit('candidate', id, event.candidate);
          }
        };
      });
    
      socket.on('offer', function(id, description) {
        const peerConnection = new RTCPeerConnection(config);
        peerConnections[id] = peerConnection;
        if (localVideo instanceof HTMLVideoElement) {
          peerConnection.addStream(localVideo.srcObject);
        }
        peerConnection.setRemoteDescription(description)
        .then(() => peerConnection.createAnswer())
        .then(sdp => peerConnection.setLocalDescription(sdp))
        .then(function () {
          socket.emit('answer', id, peerConnection.localDescription);
        });
        peerConnection.onaddstream = event => handleRemoteStreamAdded(event.stream, id);
        peerConnection.onicecandidate = function(event) {
          if (event.candidate) {
            socket.emit('candidate', id, event.candidate);
          }
        };
      });
    
      socket.on('candidate', function(id, candidate) {
        peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate))
        .catch(e => console.error(e));
      });
    
      socket.on('answer', function(id, description) {
        peerConnections[id].setRemoteDescription(description);
      });
    
      function getUserMediaSuccess(stream) {
        gettingUserMedia = false;
        if (localVideo instanceof HTMLVideoElement) {
          !localVideo.srcObject && (localVideo.srcObject = stream);
        }
        socket.emit('ready');
      }
    
      function handleRemoteStreamAdded(stream, id) {
        const remoteVideo = document.createElement('video');
        remoteVideo.srcObject = stream;
        remoteVideo.setAttribute("id", id.replace(/[^a-zA-Z]+/g, "").toLowerCase());
        remoteVideo.setAttribute("playsinline", "true");
        remoteVideo.setAttribute("autoplay", "true");
        remoteVideos.appendChild(remoteVideo);
        if (remoteVideos.querySelectorAll("video").length === 1) {
          remoteVideos.setAttribute("class", "one remoteVideos");
        } else {
          remoteVideos.setAttribute("class", "remoteVideos");
        }
      }
    
      function getUserMediaError(error) {
        console.error(error);
    
        gettingUserMedia = false;
        (--getUserMediaAttempts > 0) && setTimeout(getUserMediaDevices, 1000);
      }
    
      function getUserMediaDevices() {
        if (localVideo instanceof HTMLVideoElement) {
    
          if (localVideo.srcObject) {
            getUserMediaSuccess(localVideo.srcObject);
          } else if (!gettingUserMedia && !localVideo.srcObject) {
            gettingUserMedia = true;
            navigator.mediaDevices.getDisplayMedia(constraints)
            .then(getUserMediaSuccess)
            .catch(getUserMediaError);
          }
        }
      }
    
      function handleRemoteHangup(id) {
        peerConnections[id] && peerConnections[id].close();
        delete peerConnections[id];
        document.querySelector("#" + id.replace(/[^a-zA-Z]+/g, "").toLowerCase()).remove();
        if (remoteVideos.querySelectorAll("video").length === 1) {
          remoteVideos.setAttribute("class", "one remoteVideos");
        } else {
          remoteVideos.setAttribute("class", "remoteVideos");
        }
      }
    
      getUserMediaDevices();
    })();

This is node.js code`

const credentials = require('./credentials');
const express = require('express');
const app = express();
let server;
let port;
if (credentials.key && credentials.cert) {
  const https = require('https');
  server = https.createServer(credentials, app);
  port = 443;
} else {
  const http = require('http');
  server = http.createServer(app);
  port = 1517;
}
const io = require('socket.io')(server);
const RoomService = require('./RoomService')(io);
io.sockets.on('connection', RoomService.listen);
io.sockets.on('error', e => console.log(e));
app.use(express.static(__dirname + '/public'));
app.get('*', function(req, res) {
    res.sendFile(${__dirname}/public/index.html);
});
server.listen(port, () => console.log(Server is running on port ${port}));

Solution

  • ok man this is fixed code you can use yuu need just stream getDisplayMedia value

      (function() {
      const socket = io.connect(window.location.origin);
      const localVideo = document.querySelector('.localVideo');
      const remoteVideos = document.querySelector('.remoteVideos');
      const peerConnections = {};
      var url_string =window.location.href
      var url = new URL(url_string);
      var de = url.searchParams.get("key");
      let room = de
      let getUserMediaAttempts = 5;
      let gettingUserMedia = false;
      let getdisplaymedia=true;
      /** @type {RTCConfiguration} */
      const config = {
        'iceServers': [{
          'urls': ['stun:stun.l.google.com:19302']
        }]
      };
      /** @type {MediaStreamConstraints} */
      const constraints = {
        audio: true,
        video: { facingMode: "user" }
      };
      socket.on('full', function(room) {
        alert('Room ' + room + ' is full');
      });
      socket.on('bye', function(id) {
        handleRemoteHangup(id);
      });
    
      if (room && !!room) {
        socket.emit('join', room);
      }
    
      window.onunload = window.onbeforeunload = function() {
        socket.close();
      };
    
      socket.on('ready', function (id) {
        if (!(localVideo instanceof HTMLVideoElement) || !localVideo.srcObject) {
          return;
        }
        const peerConnection = new RTCPeerConnection(config);
        peerConnections[id] = peerConnection;
        if (localVideo instanceof HTMLVideoElement) {
          peerConnection.addStream(localVideo.srcObject);
        }
        peerConnection.createOffer()
        .then(sdp => peerConnection.setLocalDescription(sdp))
        .then(function () {
          socket.emit('offer', id, peerConnection.localDescription);
        });
        peerConnection.onaddstream = event => handleRemoteStreamAdded(event.stream, id);
        peerConnection.onicecandidate = function(event) {
          if (event.candidate) {
            socket.emit('candidate', id, event.candidate);
    
          }
        };
      });
    
      socket.on('offer', function(id, description) {
        const peerConnection = new RTCPeerConnection(config);
        peerConnections[id] = peerConnection;
        if (localVideo instanceof HTMLVideoElement) {
          peerConnection.addStream(localVideo.srcObject);
        }
        peerConnection.setRemoteDescription(description)
        .then(() => peerConnection.createAnswer())
        .then(sdp => peerConnection.setLocalDescription(sdp))
        .then(function () {
          socket.emit('answer', id, peerConnection.localDescription);
        });
        peerConnection.onaddstream = event => handleRemoteStreamAdded(event.stream, id);
        peerConnection.onicecandidate = function(event) {
          if (event.candidate) {
            socket.emit('candidate', id, event.candidate);
          }
        };
      });
    
      socket.on('candidate', function(id, candidate) {
        peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate))
        .catch(e => console.error(e));
      });
    
      socket.on('answer', function(id, description) {
        peerConnections[id].setRemoteDescription(description);
      });
    
      function getUserMediaSuccess(stream) {
        gettingUserMedia = false;
        if (localVideo instanceof HTMLVideoElement) {
          !localVideo.srcObject && (localVideo.srcObject = stream);
        }
        socket.emit('ready');
      }
    
      function handleRemoteStreamAdded(stream, id) {
        const remoteVideo = document.createElement('video');
        remoteVideo.srcObject = stream;
        remoteVideo.setAttribute("id", id.replace(/[^a-zA-Z]+/g, "").toLowerCase());
        remoteVideo.setAttribute("playsinline", "true");
        remoteVideo.setAttribute("autoplay", "true");
        remoteVideos.appendChild(remoteVideo);
        if (remoteVideos.querySelectorAll("video").length === 1) {
          remoteVideos.setAttribute("class", "one remoteVideos");
        } else {
          remoteVideos.setAttribute("class", "remoteVideos");
        }
      }
    
      function getUserMediaError(error) {
        console.error(error);
    
        gettingUserMedia = false;
        (--getUserMediaAttempts > 0) && setTimeout(getUserMediaDevices, 1000);
      }
    
    function getUserMediaDevices() {
    var constraints = { audio: true, video: { width: 1280, height: 720 } }; 
    
    navigator.mediaDevices.getDisplayMedia(constraints)
    .then(function(mediaStream) {
      var video = document.querySelector('video');
      video.srcObject = mediaStream;
      video.onloadedmetadata = function(e) {
        video.play();
        getUserMediaSuccess(video.srcObject)  
      };
    })
    .catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.
    }
    
      function handleRemoteHangup(id) {
        peerConnections[id] && peerConnections[id].close();
        delete peerConnections[id];
        document.querySelector("#" + id.replace(/[^a-zA-Z]+/g, "").toLowerCase()).remove();
        if (remoteVideos.querySelectorAll("video").length === 1) {
          remoteVideos.setAttribute("class", "one remoteVideos");
        } else {
          remoteVideos.setAttribute("class", "remoteVideos");
        }
      }
    
      getUserMediaDevices();
    })();