0

在刚刚添加之前是否有通知提供者不存在的轨道,以便从下面的代码中从应答者那里获取新的流?

对于我现在的当前问题,提供者可以添加新的不存在的轨道,并且 onnegotiationneeded 将被触发,并且还能够成功地创建报价和更新媒体,但是当回答者执行相同的过程时,onnegotiationneeded 也从回答者正常触发但没有媒体因为offerer端没有新的track就被交换了!

我用于replaceOrAddTrack(remotePartiID, track, TrackKind)添加和替换曲目

如果与初始连接具有相同的轨道类型,则只有替换适用于任一端

_cfg = {
   sdpConstraints: {
     mandatory: {
       OfferToReceiveAudio: true,
       OfferToReceiveVideo: true,
       VoiceActivityDetection: true,
       IceRestart: true
     },
     optional: []
   }
   ...
 };



 var channels_wrap = (function() {
   return {
     ...
     init: function() {

       _cfg.defaultChannel.on('message', (message) => {
         if (_cfg.enableLog) {
           console.log('Client received message:', message);
         }
         if (message.type === 'newparticipant') {
           var partID = message.from;
           var partData = message.fromData;

           // Open a new communication channel to the new participant
           _cfg.offerChannels[partID] = this.openSignalingChannel(partID);

           // Wait for answers (to offers) from the new participant
           _cfg.offerChannels[partID].on('message', (msg) => {
             if (msg.dest === _cfg.myID) {

               if (msg.type === 'reoffer') {
                 if (_cfg.opc.hasOwnProperty(msg.from)) {
                   console.log('reoffering')
                   _cfg.opc[msg.from].negotiationNeeded();
                 }

               } else
               if (msg.type === 'answer') {
                 _cfg.opc[msg.from].peer.setRemoteDescription(new RTCSessionDescription(msg.snDescription),
                   handlers_wrap.setRemoteDescriptionSuccess,
                   handlers_wrap.setRemoteDescriptionError);
               } else if (msg.type === 'candidate') {
                 var candidate = new RTCIceCandidate({
                   sdpMLineIndex: msg.label,
                   candidate: msg.candidate
                 });
                 if (_cfg.enableLog) {
                   console.log('got ice candidate from ' + msg.from);
                 }
                 _cfg.opc[msg.from].peer.addIceCandidate(candidate, handlers_wrap.addIceCandidateSuccess, handlers_wrap.addIceCandidateError);
               }
             }
           });

           // Send an offer to the new participant
           dialogs_wrap.createOffer(partID, partData);

         } else if (message.type === 'bye') {
           handlers_wrap.hangup(message.from, message.fromData);
         }
       });
     },
     initPrivateChannel: function() {
       // Open a private channel (namespace = _cfg.myID) to receive offers
       _cfg.privateAnswerChannel = this.openSignalingChannel(_cfg.myID);

       // Wait for offers or ice candidates
       _cfg.privateAnswerChannel.on('message', (message) => {
         if (message.dest === _cfg.myID) {
           if (message.type === 'offer') {
             var to = message.from;

             dialogs_wrap.createAnswer(message.snDescription, _cfg.privateAnswerChannel, to, message.fromData);
           } else if (message.type === 'candidate') {
             var candidate = new RTCIceCandidate({
               sdpMLineIndex: message.label,
               candidate: message.candidate
             });
             _cfg.apc[message.from].peer.addIceCandidate(candidate, handlers_wrap.addIceCandidateSuccess, handlers_wrap.addIceCandidateError);
           }
         }
       });
     }
   };
 })();

 var tracks_wrap = (function() {
   return {
     getParticipants: function(partID = null) {
       var participants = {};
       if (partID) {
         if (_cfg.opc.hasOwnProperty(partID)) {
           participants[partID] = {
             ID: partID,
             type: 'opc'
           };
         } else
         if (_cfg.apc.hasOwnProperty(partID)) {
           participants[partID] = {
             ID: partID,
             type: 'apc'
           };
         }
       } else {
         for (let key in _cfg.opc) {
           participants[key] = {
             ID: key,
             type: 'opc'
           };
         }
         for (let key in _cfg.apc) {
           participants[key] = {
             ID: key,
             type: 'apc'
           };
         }
       }
       return participants;
     },
     replaceOrAddTrack: function(remotePartiID, track, TrackKind) {
       if (!TrackKind) {
         return;
       }
       var participants = this.getParticipants(remotePartiID);
       for (var partiID in participants) {
         var peer = null;
         if (participants[partiID].type === 'apc' && _cfg.apc.hasOwnProperty(partiID)) {
           peer = _cfg.apc[partiID].peer;
         } else if (participants[partiID].type === 'opc' && _cfg.opc.hasOwnProperty(partiID)) {
           peer = _cfg.opc[partiID].peer;
         } else {
           continue;
         }
         var foundTrack = null;
         peer.getSenders().forEach(function(rtpSender) {
           if (rtpSender.track && TrackKind === rtpSender.track.kind) {
             foundTrack = true;
             rtpSender.replaceTrack(track);
           }
         });
         if (!foundTrack) {
           peer.addTrack(track, _cfg.localStream); //This work only if it is offerrer that add track but not working with answerer even if i tell the offerer to send offer again
         }
       }
     }
   };
 })();

 var dialogs_wrap = (function() {
   return {

     /**
      *
      * Send an offer to peer with id partID and metadata as partData
      *
      */
     createOffer: function(partID, partData) {
       if (_cfg.enableLog) {
         console.log('Creating offer for peer ' + partID, partData);
       }
       var opcPeer = new RTCPeerConnection(_cfg.pcConfig, _cfg.peerSetup);
       _cfg.opc[partID] = {};
       _cfg.opc[partID].peer = opcPeer;
       _cfg.opc[partID].peer.onicecandidate = handlers_wrap.handleIceCandidateAnswer(_cfg.offerChannels[partID], partID, partData);
       _cfg.opc[partID].peer.ontrack = handlers_wrap.handleRemoteStreamAdded(partID, partData);
       _cfg.opc[partID].peer.onremovetrack = handlers_wrap.handleRemoteStreamRemoved(partID, partData);
       _cfg.localStream.getTracks().forEach(track => _cfg.opc[partID].peer.addTrack(track, _cfg.localStream));

       try {
         _cfg.sendChannel[partID] = _cfg.opc[partID].peer.createDataChannel("sendDataChannel", {
           reliable: false
         });
         _cfg.sendChannel[partID].onmessage = handlers_wrap.handleMessage;
         if (_cfg.enableLog) {
           console.log('Created send data channel');
         }
       } catch (e) {
         alert('Failed to create data channel.  \n You need supported RtpDataChannel enabled browser');
         console.log('createDataChannel() failed with exception: ', e.message);
       }
       _cfg.sendChannel[partID].onopen = handlers_wrap.handleSendChannelStateChange(partID);
       _cfg.sendChannel[partID].onclose = handlers_wrap.handleSendChannelStateChange(partID);

       var onSuccess = (partID, partData) => {
         var channel = _cfg.offerChannels[partID];
         if (_cfg.enableLog) {
           console.log('Sending offering');
         }
         channel.emit('message', {
           snDescription: _cfg.opc[partID].peer.localDescription,
           from: _cfg.myID,
           fromData: _cfg.myData,
           type: 'offer',
           dest: partID,
           destData: partData
         });

       }
       _cfg.opc[partID].negotiationNeeded = () => {

         _cfg.opc[partID].peer.createOffer(_cfg.sdpConstraints).then(offer => {
             offer.sdp = sdp_wrap.SDPController(offer.sdp);
             return _cfg.opc[partID].peer.setLocalDescription(offer)
           })
           .then(() => onSuccess(partID, partData)).catch(handlers_wrap.handleCreateOfferError);
       }
       _cfg.opc[partID].peer.onnegotiationneeded = () => {
         _cfg.opc[partID].negotiationNeeded();
       }
     },

     createAnswer: function(snDescription, cnl, to, toData) {
       if (_cfg.enableLog) {
         console.log('Creating answer for peer ' + to);
       }
       if (!_cfg.apc.hasOwnProperty(to)) {
         var apcPeer = new RTCPeerConnection(_cfg.pcConfig, _cfg.peerSetup);
         //apcPeer.setConfiguration(_cfg.pcConfig);
         _cfg.apc[to] = {};
         _cfg.apc[to].peer = apcPeer;
         _cfg.apc[to].peer.onicecandidate = handlers_wrap.handleIceCandidateAnswer(cnl, to, toData);
         _cfg.apc[to].peer.ontrack = handlers_wrap.handleRemoteStreamAdded(to, toData);
         _cfg.apc[to].peer.onremovetrack = handlers_wrap.handleRemoteStreamRemoved(to, toData);
         _cfg.localStream.getTracks().forEach(track => _cfg.apc[to].peer.addTrack(track, _cfg.localStream));
         _cfg.apc[to].peer.ondatachannel = handlers_wrap.gotReceiveChannel(to);
       }
       _cfg.apc[to].peer.setRemoteDescription(new RTCSessionDescription(snDescription), handlers_wrap.setRemoteDescriptionSuccess, handlers_wrap.setRemoteDescriptionError);

       var onSuccess = (channel) => {
         if (_cfg.enableLog) {
           console.log('Sending answering');
         }
         channel.emit('message', {
           snDescription: _cfg.apc[to].peer.localDescription,
           from: _cfg.myID,
           fromData: _cfg.myData,
           type: 'answer',
           dest: to,
           destData: toData
         });

       }
       _cfg.apc[to].peer.createAnswer().then(function(answer) {
           answer.sdp = sdp_wrap.SDPController(answer.sdp);
           return _cfg.apc[to].peer.setLocalDescription(answer);
         })
         .then(() => onSuccess(cnl))
         .catch(handlers_wrap.handleCreateAnswerError);
       var negotiationNeeded = false;
       _cfg.apc[to].peer.onnegotiationneeded = (ev) => {
         if (!negotiationNeeded) {
           negotiationNeeded = true;
           return;
         }
         //So i tried to create this to tell the offerer to do offer again, offerer do resend offer but nothing seem to happen
         cnl.emit('message', {
           from: _cfg.myID,
           fromData: _cfg.myData,
           type: 'reoffer',
           dest: to,
           destData: toData
         });
       }
     }
   };
 })();
4

0 回答 0