Javascript RTPeerConnection未侦听远程端口的跟踪事件
我正在尝试使用WebRTC在应用程序中实现视频调用。共享报价、答案和ice候选人后,对等方之间的连接正在成功建立 远程对等方正在发送曲目(视频、音频),但本地对等方(接收对等方)未列出远程对等方连接的曲目 向对等连接添加跟踪:Javascript RTPeerConnection未侦听远程端口的跟踪事件,javascript,angular,webrtc,Javascript,Angular,Webrtc,我正在尝试使用WebRTC在应用程序中实现视频调用。共享报价、答案和ice候选人后,对等方之间的连接正在成功建立 远程对等方正在发送曲目(视频、音频),但本地对等方(接收对等方)未列出远程对等方连接的曲目 向对等连接添加跟踪: const localStream = await window.navigator.mediaDevices.getUserMedia({video: true, audio: true}); localStream.getTracks().forEach(track
const localStream = await window.navigator.mediaDevices.getUserMedia({video: true, audio: true});
localStream.getTracks().forEach(track => {
this.peerConnection.addTrack(track, localStream);
});
this.peerConnection.addEventListener('track', async (event) => {
console.log("Remote video stream added to the video element...");
remoteStream.addTrack(event.track);
});
另一侧收听曲目事件:
const localStream = await window.navigator.mediaDevices.getUserMedia({video: true, audio: true});
localStream.getTracks().forEach(track => {
this.peerConnection.addTrack(track, localStream);
});
this.peerConnection.addEventListener('track', async (event) => {
console.log("Remote video stream added to the video element...");
remoteStream.addTrack(event.track);
});
从'@angular/core'导入{Component,OnInit,Inject};
从“@angular/material/DIALOG”导入{MAT_DIALOG_DATA};
从'src/app/User/model/User'导入{User};
从'@stomp/ng2 stompjs'导入{RxStompService};
从“rxjs”导入{Subscription};
从'src/app/login/service/login.service'导入{LoginService};
从'src/app/chats/model/Chat'导入{Chat};
从'src/app/chats/model/chat type'导入{ChatType};
从“uuid”导入{v4作为uuidv4};
从'src/app/crypto/service/crypto.service'导入{CryptoService};
@组成部分({
选择器:“应用程序视频呼叫”,
templateUrl:'./video call.component.html',
样式URL:['./video call.component.css']
})
导出类VideoCallComponent实现OnInit{
当前用户:用户;
friendUser:用户;
订阅:订阅;
peerConnection:RTCPeerConnection;
提供:聊天;
答:聊天;
候选人:聊天;
generatedIceCandidateCount=0;
receivedIceCandidateCount=0;
iceCandidates=新数组();
建造师(
私人登录服务:登录服务,
@注入(MAT_DIALOG_DATA)公共数据:任意,
私有stompService:RxStompService,
私有加密服务:加密服务
) {
this.currentUser=this.loginService.getCurrentUser();
if(data.friendUser){
this.friendUser=data.friendUser;
const配置={'iceServers':[{'url':'stun:stun.l.google.com:19302'}]};
this.peerConnection=新的RTCPeerConnection(配置);
这是.startReceivingStreams();
//在本地RTPeerConnection上侦听本地ICE候选者
this.peerConnection.addEventListener('icecandidate',事件=>{
if(事件候选){
//console.log('ICE候选者生成',event.候选者);
log(“Genrated候选者”++this.generatedecandidateCount);
this.iceCandidates.push(event.candidate);
//this.sendToSocket(this.createChat(null,ChatType.ICE_-CANDIDATE,{'iceCandidate':event.CANDIDATE}));
}否则{
log(“缓冲区中的候选项:”,this.generatedecandidateCount);
this.iceCandidates.forEach((candidate)=>{
this.sendToSocket(this.createChat(null,ChatType.ICE_-CANDIDATE,{'iceCandidate':CANDIDATE}))
});
如果(此.ICE.length>0)
this.startTransmittingStreams();
}
});
//侦听本地RTPeerConnection上的connectionstatechange
this.peerConnection.addEventListener('connectionstatechange',事件=>{
if(this.peerConnection.connectionState==='connected'){
日志(“连接完成…”);
}
});
}
这个.startListeningVideoCalls();
if(data.videoCallOfferChat){
这是.startReceivingStreams();
这个.answerVideoCall(data.videoCallOfferChat);
}
否则{
this.offerVideoCall();
}
}
ngOnInit():void{}
异步startTransmittingStreams(){
const localStream=wait window.navigator.mediaDevices.getUserMedia({video:true,audio:true});
localStream.getTracks().forEach(异步跟踪=>{
日志(“添加跟踪…”,跟踪);
等待这个.peerConnection.addTrack(track,localStream);
});
}
startReceivingStreams(){
日志(“开始接收…”);
让remoteStream=new MediaStream();
this.peerConnection.ontrack=事件=>{
console.log(“[addEventListener]远程视频流添加到视频元素…”,事件);
让remoteVideo:any=document.getElementById('friendUserVideoTrack');
remoteVideo.srcObject=remoteStream;
remoteStream.addTrack(event.track);
}
}
私人监听视频通话(){
if(this.stompService.connected()){
this.chatSubscription=this.stompService.watch('/text/'+this.currentUser.id).订阅((数据:any)=>{
让chat=JSON.parse(data.body);
if(chat.data)
chat.data=JSON.parse(chat.data);
if(chat.type==ChatType.VIDEO\u CALL\u ANSWER){
console.log('Video Call-Answer…',chat);
if(chat.data.answer){
//包含RTCConnection应答,然后连接
console.log('Call accepted',chat.data.answer);
这个。视频电话应答(聊天);
}否则{
//不包含RTCConnection应答:呼叫被收件人拒绝
log('呼叫被拒绝…');
}
}
if(chat.type==ChatType.ICE_候选者){
console.log(“与ICE候选人聊天”,聊天);
this.iceCandidateReceived(chat.data.iceCandidate);
}
});
}
}
异步offerVideoCall(){
var options={offerToReceiveVideo:true,offerToReceiveAudio:true};
const offer=wait this.peerConnection.createOffer(选项);
等待这个.peerConnection.setLocalDescription(offer);
this.sendToSocket(this.createChat(null,ChatType.VIDEO_CALL_OFFER,{'OFFER':OFFER}));
}
专用异步应答视频呼叫(receivedChat:Chat){
如果(收到Chat.data.offer){
让remoteDescription=新的RTCSessionDescription(receivedChat.data.offer);
等着吧
import { Component, OnInit, Inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { User } from 'src/app/user/model/user';
import { RxStompService } from '@stomp/ng2-stompjs';
import { Subscription } from 'rxjs';
import { LoginService } from 'src/app/login/service/login.service';
import { Chat } from 'src/app/chats/model/chat';
import { ChatType } from 'src/app/chats/model/chat-type';
import { v4 as uuidv4 } from 'uuid';
import { CryptoService } from 'src/app/crypto/service/crypto.service';
@Component({
selector: 'app-video-call',
templateUrl: './video-call.component.html',
styleUrls: ['./video-call.component.css']
})
export class VideoCallComponent implements OnInit {
currentUser : User;
friendUser : User;
chatSubscription : Subscription;
peerConnection : RTCPeerConnection;
offer : Chat;
answer : Chat;
iceCandidate : Chat;
generatedIceCandidateCount = 0;
receivedIceCandidateCount = 0;
iceCandidates = new Array<any>();
constructor(
private loginService : LoginService,
@Inject(MAT_DIALOG_DATA) public data: any,
private stompService : RxStompService,
private cryptoService : CryptoService
) {
this.currentUser = this.loginService.getCurrentUser();
if(data.friendUser){
this.friendUser = data.friendUser;
const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]};
this.peerConnection = new RTCPeerConnection(configuration);
this.startReceivingStreams();
// Listen for local ICE candidates on the local RTCPeerConnection
this.peerConnection.addEventListener('icecandidate', event => {
if (event.candidate) {
// console.log('ICE Candidate generated', event.candidate);
console.log("Genrated Candidate ", ++this.generatedIceCandidateCount);
this.iceCandidates.push(event.candidate);
// this.sendToSocket(this.createChat(null, ChatType.ICE_CANDIDATE, {'iceCandidate' : event.candidate}));
}else{
console.log("Candidates in buffer : ", this.generatedIceCandidateCount);
this.iceCandidates.forEach((candidate) => {
this.sendToSocket(this.createChat(null, ChatType.ICE_CANDIDATE, {'iceCandidate' : candidate}))
});
if(this.iceCandidates.length>0)
this.startTransmittingStreams();
}
});
// Listen for connectionstatechange on the local RTCPeerConnection
this.peerConnection.addEventListener('connectionstatechange', event => {
if (this.peerConnection.connectionState === 'connected') {
console.log("Connection done...");
}
});
}
this.startListeningVideoCalls();
if (data.videoCallOfferChat){
this.startReceivingStreams();
this.answerVideoCall(data.videoCallOfferChat);
}
else{
this.offerVideoCall();
}
}
ngOnInit(): void {}
async startTransmittingStreams(){
const localStream = await window.navigator.mediaDevices.getUserMedia({video: true, audio: true});
localStream.getTracks().forEach(async track => {
console.log("Adding track...", track);
await this.peerConnection.addTrack(track, localStream);
});
}
startReceivingStreams(){
console.log("Start receiving...");
let remoteStream = new MediaStream();
this.peerConnection.ontrack = event => {
console.log("[addEventListener] Remote video stream added to the video element...", event);
let remoteVideo : any = document.getElementById('friendUserVideoTrack');
remoteVideo.srcObject = remoteStream;
remoteStream.addTrack(event.track);
}
}
private startListeningVideoCalls(){
if(this.stompService.connected()){
this.chatSubscription = this.stompService.watch('/text/'+this.currentUser.id).subscribe((data:any)=>{
let chat = JSON.parse(data.body);
if(chat.data)
chat.data = JSON.parse(chat.data);
if (chat.type == ChatType.VIDEO_CALL_ANSWER) {
console.log('Video Call Answer ...', chat);
if (chat.data.answer) {
// Contains RTCConnection answer then connect
console.log('Call accepted', chat.data.answer);
this.videoCallAnswered(chat);
}else{
// Doesn't contains RTCConnection answer : call rejected by recipient
console.log('Call rejected...');
}
}
if(chat.type == ChatType.ICE_CANDIDATE){
console.log('Chat with ICE Candidate ', chat);
this.iceCandidateReceived(chat.data.iceCandidate);
}
});
}
}
async offerVideoCall() {
var options = { offerToReceiveVideo: true, offerToReceiveAudio: true };
const offer = await this.peerConnection.createOffer(options);
await this.peerConnection.setLocalDescription(offer);
this.sendToSocket(this.createChat(null, ChatType.VIDEO_CALL_OFFER, {'offer' : offer}));
}
private async answerVideoCall(receivedChat : Chat){
if (receivedChat.data.offer) {
let remoteDescription = new RTCSessionDescription(receivedChat.data.offer);
await this.peerConnection.setRemoteDescription(remoteDescription);
var options = { offerToReceiveVideo: true, offerToReceiveAudio: true };
const answer = await this.peerConnection.createAnswer(options);
await this.peerConnection.setLocalDescription(answer);
this.sendToSocket(this.createChat(receivedChat.id, ChatType.VIDEO_CALL_ANSWER, {'answer' : answer}));
}
}
private async videoCallAnswered(chat : Chat){
const remoteDesc = new RTCSessionDescription(chat.data.answer);
await this.peerConnection.setRemoteDescription(remoteDesc);
}
private createChat(id : string, chatType : ChatType, data : any){
let chat : Chat = new Chat();
chat.id = uuidv4();
chat.textFrom = this.currentUser.id;
chat.textTo = this.friendUser.id;
chat.textFromName = this.currentUser.name;
chat.textToName = this.friendUser.name;
chat.date = new Date().getTime();
chat.type = chatType;
chat.message = this.cryptoService.encrypt(chat.message, this.friendUser.userChat.sk);
chat.data = JSON.stringify(data);
return chat;
}
private sendToSocket(chat : Chat){
if(this.stompService.connected()){
this.stompService.publish({
destination : "/app/text/"+this.friendUser.id,
body : JSON.stringify(chat)
});
}
}
private async iceCandidateReceived(iceCandidate : any){
if(this.peerConnection.remoteDescription){
try {
await this.peerConnection.addIceCandidate(new RTCIceCandidate(iceCandidate));
console.log("Received Count ", ++this.receivedIceCandidateCount);
} catch (e) {
console.error('Error adding received ice candidate', e);
}
}
}
}