Javascript react.js和WebRTC RTPeerConnection.addStream不是对象

Javascript react.js和WebRTC RTPeerConnection.addStream不是对象,javascript,node.js,reactjs,meteor,webrtc,Javascript,Node.js,Reactjs,Meteor,Webrtc,我想在react.js和WebRTC上做一个简单的视频聊天。但是在第pc.addStream(localStream)行中发生错误: TypeError:RTCPeerConnection.addStream的参数1不是对象 我不明白为什么我看不到行中的日志: pc.onicecandidate=(e)=>{ console.log('onicecandidate'); 这就是全部代码: class App extends Component { constructor(props) {

我想在
react.js
WebRTC
上做一个简单的视频聊天。但是在第
pc.addStream(localStream)
行中发生错误:

TypeError:RTCPeerConnection.addStream的参数1不是对象

我不明白为什么我看不到行中的日志:

pc.onicecandidate=(e)=>{
console.log('onicecandidate');

这就是全部代码:

class App extends Component {
  constructor(props) {
    super(props);
  }
  componentDidUpdate(){
    loadScript("https://webrtc.github.io/adapter/adapter-latest.js");
    let localVideo, remoteVideo, peerConnection, localStream;
    $('#start').on('click', ()=>{ start(true) });

    let id = uuid();
    localVideo = document.getElementById('localVideo');
    remoteVideo = document.getElementById('remoteVideo');


    if(navigator.mediaDevices.getUserMedia) {
       navigator.mediaDevices.getUserMedia( { video:true, audio:true}).then( ( stream )=> {
          localStream = stream;
          localVideo.src = window.URL.createObjectURL(stream);
       }).catch(errorHandler);
   }else{ alert('Your browser does not support getUserMedia API'); }

   function start(isCaller) {
      peerConnection = new RTCPeerConnection( { 'iceServers':  [{'urls': 'stun:stun.services.mozilla.com'}, {'urls': 'stun:stun.l.google.com:19302'},]});
      peerConnection.onicecandidate = ( e ) => {
        if(e.candidate != null) {
           Meteor.call('addMsgRtc', JSON.stringify({'ice': e.candidate, '_id':id}), id);
        }
     };
      peerConnection.onaddstream = ( e )=>{
         remoteVideo.src = window.URL.createObjectURL(e.stream);
      };
      peerConnection.addStream(localStream);
      if(isCaller) { 
        peerConnection.createOffer().then(
          createdDescription).catch(errorHandler);
      }
   }
   if (!this.props.loadingRtc) {
      for(let i of this.props.messagesRtc){        
        if(!peerConnection) start(false);
        let signal = JSON.parse(i.text);
        if(signal._id == id) return;
        if(signal.sdp) {
             peerConnection.setRemoteDescription(new   RTCSessionDescription(signal.sdp)).then(()=> {
            if(signal.sdp.type == 'offer') {             peerConnection.createAnswer().then(createdDescription).catch(errorHandler);
            }
        }).catch(errorHandler);
      }else if(signal.ice) {
        peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
      }
    }
  }


  function createdDescription(description) {
    peerConnection.setLocalDescription(description).then(()=> {        
       Meteor.call('addMsgRtc', JSON.stringify({'sdp':peerConnection.localDescription, '_id':id}), id);
    }).catch(errorHandler);
  }
  function errorHandler(error) { console.log(error); }
}

  }
  render() {
    return (
        <div id="container">
          <video id="localVideo" autoPlay muted style={{width:"40%"}}></video>
          <video id="remoteVideo" autoPlay style={{width:"40%"}}></video>
          <br/>
        </div>
    );
  }
}

export default createContainer( ()=> {
  const subscriptionRtc = Meteor.subscribe('rtc');
  const loadingRtc = !subscriptionRtc.ready();
  return {
    loadingRtc:loadingRtc,
    messagesRtc: msgRtc.find().fetch(),
  };
}, App);
类应用程序扩展组件{
建造师(道具){
超级(道具);
}
componentDidUpdate(){
加载脚本(“https://webrtc.github.io/adapter/adapter-latest.js");
让本地视频、远程视频、对等连接、本地流;
$('#start')。on('click',()=>{start(true)});
设id=uuid();
localVideo=document.getElementById('localVideo');
remoteVideo=document.getElementById('remoteVideo');
if(navigator.mediaDevices.getUserMedia){
navigator.mediaDevices.getUserMedia({video:true,audio:true})。然后((stream)=>{
localStream=stream;
localVideo.src=window.URL.createObjectURL(流);
}).catch(errorHandler);
}else{alert('您的浏览器不支持getUserMedia API');}
功能启动(isCaller){
peerConnection=new-RTCPeerConnection({'iceServers':[{'url':'stun:stun.services.mozilla.com'},{'url':'stun:stun.l.google.com:19302'},]});
peerConnection.onicecandidate=(e)=>{
如果(例如,候选者!=null){
Meteor.call('addMsgRtc',JSON.stringify({'ice':e.candidate,'u id':id}),id);
}
};
peerConnection.onaddstream=(e)=>{
remoteVideo.src=window.URL.createObjectURL(e.stream);
};
peerConnection.addStream(localStream);
如果(isCaller){
peerConnection.createOffer()。然后(
createdDescription).catch(errorHandler);
}
}
如果(!this.props.loadingRtc){
对于(让我来看看这个.props.messagesRtc){
如果(!peerConnection)启动(false);
让signal=JSON.parse(i.text);
if(signal.\u id==id)返回;
中频(信号sdp){
peerConnection.setRemoteDescription(新的RTCSessionDescription(signal.sdp))。然后(()=>{
如果(signal.sdp.type='offer'){peerConnection.createAnswer().then(createdDescription.catch)(errorHandler);
}
}).catch(errorHandler);
}else if(signal.ice){
peerConnection.addIceCandidate(新的RTCIceCandidate(signal.ice)).catch(errorHandler);
}
}
}
函数createdDescription(描述){
peerConnection.setLocalDescription(description).then(()=>{
Meteor.call('addMsgRtc',JSON.stringify({'sdp':peerConnection.localDescription,'u id':id}),id);
}).catch(errorHandler);
}
函数errorHandler(错误){console.log(错误);}
}
}
render(){
返回(

); } } 导出默认createContainer(()=>{ const subscriptionRtc=Meteor.subscribe('rtc'); const loadingRtc=!subscriptionRtc.ready(); 返回{ loadingRtc:loadingRtc, messagesRtc:msgRtc.find().fetch(), }; },App);
getUserMedia
是一个返回承诺的异步操作。在调用
pc.addStream
时,尚未执行设置
localStream
.then()
。 您可能希望将
start()
移动到
中。然后()


ontrack事件没有
e.stream
btw。您可能希望改用
onaddstream
。另外,请设置
srobject=e.stream
而不是使用
URL。createObjectURL
getUserMedia
是一个返回承诺的异步操作。在调用
pc.addStream
时,尚未执行设置
localStream
.then()
。 您可能希望将
start()
移动到
中。然后()


ontrack事件没有
e.stream
btw。您可能希望改用
onaddstream
。另外,请设置
srobject=e.stream
而不是使用
URL.createObjectURL

如果我在
中删除start函数,那么开始userMedia的
将在无限循环中运行。如果您可以给出一个示例代码。如果我在
中删除start函数,那么开始userMedia的
将在无限循环中运行。如果你能给出一个示例代码。