视频/音频通讯

问题描述

我正在尝试使用peer / getUserMedia创建视频会议Web应用。

当前,当我向视频会议发送唯一ID时,我能够听到/看到任何参加我的会议的人。

但是,只有第一个参加我的会议的人可以交流/见我。

我想这样做,以便其他用户也可以看到/听到视频会议中的每个用户

到目前为止,这是我到目前为止的工作。还有当前编写的代码,只要有新用户加入,我的视频就会再次添加,因此我可以看到自己的两个视频(如果是主持人),但这对我来说很容易

<html>
   <body>
      <h3 id="show-peer"></h3>
      <div style="display: grid; justify-content: space-around; margin:10px;">
         <div style="width: 300px;height: 200px;transform: scale(-1,1);border: 2px solid; display:grid; margin-bottom: 5%;" id="ourVideo"></div>
         <div style="width: 300px;height: 200px;transform: scale(-1,1);border: 2px solid; display: grid;" id="remoteVideo"></div>
      </div>
      <input id="peerID" placeholder="Peer ID">
      <button id="call-peer" onclick="callPeer()">Call Peer</button>
      <br>
      <button id="screenShare"onclick="shareScreen()">Share Screen</button>
   </body>
   <script src="https://unpkg.com/peerjs@1.3.1/dist/peerjs.min.js"></script>
   <script>
      window.addEventListener('load',(event)=>{
          var peer= new Peer()
          var myStream;
          var currentPeer;
          var peerList=[];
          peer.on('open',function(id){
              document.getElementById("show-peer").innerHTML=id
          })
          peer.on('call',function(call){
              navigator.mediaDevices.getUserMedia({
                  video:true,audio:true
              }).then((stream)=>{
                  myStream = stream
                  addOurVideo(stream)
                  call.answer(stream)
                  call.on('stream',function(remoteStream){
                      if(!peerList.includes(call.peer)){
                          addRemoteVideo(remoteStream)
                          currentPeer = call.peerConnection
                          peerList.push(call.peer)
                      }
                      
                  })
              }).catch((err)=>{
                  console.log(err+" unable to get media")
              })
          })
          function stopScreenShare(){
              let videoTrack = myStream.getVideoTracks()[0];
              var sender = currentPeer.getSenders().find(function(s){
                  return s.track.kind ==videoTrack.kind;
              })
              sender.replaceTrack(videoTrack)
          };
          document.getElementById("call-peer").addEventListener('click',(e)=>{
              let remotePeerId= document.getElementById("peerID").value;
              document.getElementById("show-peer").innerHTML= "connecting "+remotePeerId;
              console.log(remotePeerId)
              callPeer(remotePeerId);
          })
          document.getElementById("screenShare").addEventListener('click',(e)=>{
              navigator.mediaDevices.getdisplayMedia({
                  video: {
                      cursor: "always"
                  },audio:{  
                      autoGainControl: false,echoCancellation: false,googAutoGainControl: false,noiseSuppression: false 
                  }
              }).then((stream)=>{
                      let videoTrack = stream.getVideoTracks()[0];
      
                      videoTrack.onended = function(){
                          stopScreenShare()
                      }
                      let sender = currentPeer.getSenders().find(function(s){
                          return s.track.kind == videoTrack.kind
                      })
                      sender.replaceTrack(videoTrack)
                  }).catch((err)=>{
                      console.log("unable to get display media"+err)
                  })
              })
          function callPeer(id){
              navigator.mediaDevices.getUserMedia({
                  video:true,audio:true
              }).then((stream)=>{
                  myStream = stream
                  addOurVideo(stream)
                  let call = peer.call(id,stream)
                  call.on('stream',function(remoteStream){
                      if(!peerList.includes(call.peer)){
                          addRemoteVideo(remoteStream)
                          currentPeer = call.peerConnection
                          peerList.push(call.peer)
                      }
                      
                  })
              }).catch((err)=>{
                  console.log(err+" unable to get media")
              })
          }
          function addRemoteVideo(stream){
              let video = document.createElement("video");
              video.classList.add("video")
              video.srcObject = stream;
              video.play()
              document.getElementById("remoteVideo").append(video)
          }
          function addOurVideo(stream){
              let video = document.createElement("video");
              video.classList.add("video")
              video.srcObject = stream;
              video.play()
              video.muted=true;
              document.getElementById("ourVideo").append(video)
          }
      });
   </script>
</html>

解决方法

我认为您将需要创建一个“网格”。因此,在3个对等方的情况下,每个用户(对等方)都建立了两个连接,一个连接至其他两个用户。在每个客户端的一端,都有两个完全不同的连接。

用户@daGrevis在PeerJs GitHub上问this question。最终,这是他们用于多点聊天的实现,可能会有所帮助:

Chat = React.createClass
    displayName: "Foo"

    getInitialState: ->
        messages: []

    connectionsToPeerIds: (connections) ->
        _.map connections,(connection) => connection.peer

    componentWillMount: ->
        who = getSegments()[1]
        peer = new Peer who,key: PEER_KEY,debug: 2
        @connections = []

        peer.on "error",(error) =>
            alert error.type

        peer.on "open",(peerId) =>
            if who == "x"
                peer.on "connection",(connection) =>
                    @connections.push connection

                    @listenForMessage connection

                    peerIds = @connectionsToPeerIds @connections

                    connection.on "open",=>
                        connectionsWithoutNewConnection = _.filter @connections,(c) -> c.peer != connection.peer
                        peerIdsWithoutNewConnection = @connectionsToPeerIds connectionsWithoutNewConnection

                        if peerIdsWithoutNewConnection.length
                            connection.send type: "newConnection",peerIds: peerIdsWithoutNewConnection

            if who != "x"
                connection = peer.connect "x"

                connection.on "error",(error) =>
                    alert error

                connection.on "open",=>
                    @connections.push connection

                    @listenForMessage connection

                    connection.on "data",(data) =>
                        if data.type == "newConnection"
                            peerIds = data.peerIds
                            _.forEach peerIds,(peerId) =>
                                connection = peer.connect peerId

                                do (connection) =>
                                    connection.on "error",(error) =>
                                        alert error.type

                                    connection.on "open",=>
                                        @connections.push connection
                                        @listenForMessage connection

                peer.on "connection",(connection) =>
                    connection.on "open",=>
                        @connections.push connection

                        @listenForMessage connection

然后我找到了一个实例,其中用户@mluketin使用peerjs-server,并创建了电话会议示例https://github.com/mluketin/peerjs-helloworld-conference

根据我所了解和阅读的内容,看起来网状设计是最简单的方法,但仅限于速度最慢的同级对象。因此,如果您只需要3-5个人,那应该没问题。否则,您可能必须遵循mluketin布置的示例。


更多可能有用的链接:

  1. Having multiple peers PeerJS?
  2. Multiple party peer.js application