video-streaming - 添加 ICE 候选者失败:OperationError:无法在“RTCPeerConnection”上执行“addIceCandidate”:处理 ICE 候选者时出错
问题描述
我正在使用Angular 7
,Webrtc
制作简单的视频会议网络应用程序。我正在为 pc1Local、pc1Remote、pc2Local、pc2Remote 创建四个不同的 RTCPeerConnections。在 start() 函数上,我正在访问本地摄像头并在 Html 中的 video1 id 上显示流。在 call() 中,我设置了两个远程用户。一个远程用户正在正确显示,但第三个视频流没有显示。请帮我解决这个问题。
我的代码是:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { ChatWindowService } from '../chat-box/service/chat-window.service';
import { error } from 'util';
@Component({
selector: 'app-test-video-calling',
templateUrl: './test-video-calling.component.html',
styleUrls: ['./test-video-calling.component.scss']
})
export class TestVideoCallingComponent implements OnInit {
@ViewChild('video1', { static: false }) video1: ElementRef;
@ViewChild('video2', { static: false }) video2: ElementRef;
@ViewChild('video3', { static: false }) video3: ElementRef;
public pc1Local;
public pc1Remote;
public pc2Local;
public pc2Remote;
public browser = <any>navigator;
public videoStream;
public audioTracks ;
public videoTracks ;
public localStream;
constructor(){}
public offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
start(){
this.videoStream = this.video1.nativeElement;
this.browser.getUserMedia = this.getAllUserMedia();
console.log('Requesting local stream');
let constraints = { audio: true, video: { minFrameRate: 60, width: 400, height: 300 } };
this.browser.mediaDevices.getUserMedia(constraints).then((stream: any) => {
this.videoStream.srcObject = stream;
this.localStream = stream;
});
}
call(){
`enter code here`this.videoTracks = this.localStream.getVideoTracks();
this.audioTracks = this.localStream.getAudioTracks();
console.log('Starting calls');
if (this.audioTracks.length > 0) {
console.log(`Using audio device: ${this.audioTracks[0].label}`);
}
if (this.videoTracks.length > 0) {
console.log(`Using video device: ${this.videoTracks[0].label}`);
}
const servers = null;
this.pc1Local = new RTCPeerConnection(servers);
this.pc1Remote = new RTCPeerConnection(servers);
this.pc1Local.onicecandidate = (event:any) =>{
this.handleCandidate(event.candidate, this.pc1Remote, 'pc1: ', 'local');
}
this.pc1Remote.onicecandidate = (event:any)=>{
this.handleCandidate(event.candidate, this.pc1Local, 'pc1: ', 'remote');
};
this.pc1Remote.ontrack = (streamData:any)=>{
if (this.video2.nativeElement.srcObject !== streamData.streams[0]) {
this.video2.nativeElement.srcObject = streamData.streams[0];
console.log('pc1: received remote stream');
if (!streamData.stop && streamData.getTracks) {
streamData.stop = function () {
this.getTracks().forEach(function (track: any) {
track.stop();
});
};
}
}
}
this.pc2Local = new RTCPeerConnection(servers);
this.pc2Remote = new RTCPeerConnection(servers);
console.log("****before this.pc2Local.onicecandidate ******");
this.pc2Local.onicecandidate = (event:any) =>{
console.log("**************adding ice candidate : pc2Local***************",event);
this.handleCandidate(event.candidate, this.pc2Remote, 'pc2: ', 'local');
}
console.log("****after this.pc2Local.onicecandidate ******");
this.pc2Remote.onicecandidate = (event:any)=>{
console.log("**************adding ice candidate : pc2Remote***************",event);
this.handleCandidate(event.candidate, this.pc2Local, 'pc2: ', 'remote');
};
this.pc2Remote.ontrack = (streamData1)=>{
if (this.video3.nativeElement.srcObject !== streamData1.streams[0]) {
this.video3.nativeElement.srcObject = streamData1.streams[0];
console.log('pc2: received remote stream');
console.log("****** pc2: remote streamData : ********",streamData1);
if (!streamData1.stop && streamData1.getTracks) {
streamData1.stop = function () {
this.getTracks().forEach(function (track: any) {
track.stop();
});
};
}
}
}
this.localStream.getTracks().forEach((track: any) => {
console.log("************pc1 adding track*************");
this.pc1Local.addTrack(track, this.localStream);
});
console.log('Adding local stream to pc1Local');
this.pc1Local.createOffer(this.offerOptions).then((event:any)=>{
this.pc1Local.setLocalDescription(event);
console.log(`Offer from pc1Local\n${event.sdp}`);
this.pc1Remote.setRemoteDescription(event);
this.pc1Remote.createAnswer().then((desc)=>{
try{
this.pc1Remote.setLocalDescription(desc);
console.log(`Answer from pc1Remote\n${desc.sdp}`);
this.pc1Local.setRemoteDescription(desc);
}catch(error){
console.log(`Failed to create session description: ${error.toString()}`);
}
});
});
this.localStream.getTracks().forEach((track: any) => {
console.log("************pc2 adding track*************");
this.pc2Local.addTrack(track, this.localStream);
});
console.log('Adding local stream to pc2Local');
this.pc2Local.createOffer(this.offerOptions).then((event:any)=>{
this.pc1Local.setLocalDescription(event);
console.log(`Offer from pc1Local\n${event.sdp}`);
this.pc2Remote.setRemoteDescription(event);
this.pc2Remote.createAnswer().then((desc)=>{
try{
this.pc2Remote.setLocalDescription(desc);
console.log(`Answer from pc1Remote\n${desc.sdp}`);
this.pc2Local.setRemoteDescription(desc);
}catch(error){
console.log(`Failed to create session description: ${error.toString()}`);
}
});
});
}
public handleCandidate(candidate, dest, prefix, type) {
dest.addIceCandidate(candidate).then(this.onAddIceCandidateSuccess,this.onAddIceCandidateError);
console.log(`${prefix}New ${type} ICE candidate: ${candidate ? candidate.candidate : '(null)'}`);
}
public onAddIceCandidateSuccess() {
console.log('AddIceCandidate success.');
}
public onAddIceCandidateError(error) {
console.log(`Failed to add ICE candidate: ${error.toString()}`);
}
public getAllUserMedia() {
console.log("*****************Inside getAllUserMedia ************");
return this.browser.getUserMedia ||
this.browser.webkitGetUserMedia ||
this.browser.mozGetUserMedia ||
this.browser.msGetUserMedia;
}
ngOnInit() {
}
}
我的 HTML 文件是
<div class="container">
<video #video1 playsinline autoplay muted></video>
<video #video2 playsinline autoplay></video>
<video #video3 playsinline autoplay></video>
<div>
<button id="startButton" (click)="start()">Start</button>
<button id="callButton" (click)="call()">Call</button>
<button id="hangupButton" (click)="stop()">Hang Up</button>
</div>
</div>
问题是this.pc2Local.onicecandidate
没有执行。我收到一个错误,如下所示
`Failed to add ICE candidate: OperationError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate`
解决方案
推荐阅读
- jquery - Datepicker only on checked checkbox
- mysql - mysql存储过程返回0行受影响
- java - JVM_Read 持续消耗 CPU
- julia - 使用字符串选择函数和/或变量 (Julia)
- git - git svn clone,只包含最后n个版本
- r - Error: No tidy method for objects of class LDA_VEM§
- mysql - 获取从属状态时的 MySQL ER_SPECIFIC_ACCESS_DENIED_ERROR
- java - How to sign with RSASSA-PSS in Java correctly?
- python - Enumerating dataframe based on a column
- c# - 自动将 JSON 属性映射到 C# 属性