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的
将在无限循环中运行。如果你能给出一个示例代码。