为什么在chrome中建立webrtc连接需要两次报价



我正试图使用webrtc构建一个视频和音频呼叫应用程序,但我在这里遇到了一个奇怪的问题,即连接不是第一次建立的,而是在我再次发送报价时建立的。我已尝试打印对等方的connectionState,它在第一次单击时保持"新"状态,但在再次发送报价时更改为连接并已连接。我是webrtc的新手,我就是完全搞不明白。

以下是代码

import socketContext from '../components/socketContext';
import fetch from 'isomorphic-unfetch';
import params from '../config/params';
import SearchBar from '../components/SearchBar';
import withAuth from '../components/withAuth';
import Cookie from 'js-cookie';
class VideoConf extends React.Component{
constructor(props){
super(props);
this.state = {
friends: [],
cameraStream: undefined,
screenStream: undefined
}
this.RTCPeerConnection = undefined;
this.RTCSessionDescription = undefined;
this.peerConnection = undefined;
this.configuration = {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]};
}
static contextType = socketContext;
startConnection = async ()=>{
try{
const mediaStream = await navigator.mediaDevices.getUserMedia({audio:true,video:true});
const localVideo = document.getElementById('local-video');
localVideo.srcObject = mediaStream;
localVideo.onloadedmetadata = function(e){
localVideo.play();
}
this.peerConnection.ontrack = function ({ streams: [stream] }) {
const remoteVideo = document.getElementById("remote-video");
if (remoteVideo) {
remoteVideo.srcObject = stream;
remoteVideo.onloadedmetadata = function(e){
remoteVideo.play();
}
}
};
mediaStream.getTracks().forEach(track => this.peerConnection.addTrack(track, mediaStream));
window.videoStream = mediaStream;
window.pc = this.peerConnection;
this.setState({
cameraStream: mediaStream
})
}catch(err){
alert(err.message);
}
}
shareScreen =  async ()=>{
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: 'always',
displaySurface: 'browser'
}
});
const localVideo = document.getElementById('local-video');
localVideo.srcObject = mediaStream;
localVideo.onloadedmetadata = function(e){
localVideo.play();
}
this.peerConnection.getSenders().map(sender =>{
if(sender.track.kind == 'video'){
sender.replaceTrack(mediaStream.getTracks()[0]);
}
});
this.setState({
screenStream: mediaStream
});
}
componentDidMount = async ()=>{
const response = await fetch(`${params.hostname}/api/get-friends`,{
headers:{
Authorization:`Bearer ${Cookie.get('token')}`
}
})
if(response.ok){
const json = await response.json();
this.setState({
friends: json.data
});
}
this.RTCPeerConnection = window.RTCPeerConnection;
this.RTCSessionDescription = window.RTCSessionDescription;
this.peerConnection = new this.RTCPeerConnection(this.configuration);
let socket = this.context.socket;
socket.on("call-made", async data => {
await this.peerConnection.setRemoteDescription(
new this.RTCSessionDescription(data.offer)
);
const answer = await this.peerConnection.createAnswer();
await this.peerConnection.setLocalDescription(new this.RTCSessionDescription(answer));
socket.emit("make-answer", {
answer,
to: data.socket
});
});
socket.on("answer-made", async data => {
await this.peerConnection.setRemoteDescription(
new this.RTCSessionDescription(data.answer)
);
});
// this.peerConnection.addEventListener("negotiationneeded", ev => {
//     alert('ping it on');
//     this.callUser(0);
// });
this.startConnection();
}
callUser = async (i) => {
let socket = this.context.socket;
let frndId = this.state.friends[i];
const offer = await this.peerConnection.createOffer();
await this.peerConnection.setLocalDescription(new this.RTCSessionDescription(offer));
socket.emit('call-user',{
offer,
to: frndId.id
});
}
render(){
let {friends} = this.state;
return(
<div>
<div className="container">
<div className = "row no-gutters">
<div className = "col-12 col-md-3 text-center p-3 border" style = {{minHeight:'60vh'}}>
<SearchBar handleSearch = {this.handleSearch} />
<div>
{
friends.map((frnd,i)=>{
return (
<div key = {i} onClick = {()=>this.callUser(i)} style = {{cursor:'pointer'}}>
{frnd.name}
</div>
);                                        
})
}
</div>
</div>
<div className = "col-12 col-md-9 text-center">
<div>
<button className = "btn btn-success" onClick = {this.shareScreen}>Share screen</button>
</div>
<div className="video-container">
<video autoPlay id="remote-video" style={{width:'25vw',height:'25vh'}} ></video>
<video autoPlay muted id="local-video" style={{width:'25vw',height:'25vh'}} ></video>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default withAuth(VideoConf);

我正在使用套接字发送和回答报价,我确信后端部分没有问题。如果有人能弄清楚,那将是一个很大的帮助。

您没有一个处理程序,所以您的浏览器不知道要通信的远程地址。

它第二次起作用,因为已经收集了一些候选人,这个过程被称为涓滴冰

最新更新