RTCPeerConnection 未侦听远程的跟踪事件

问题描述 投票:0回答:2

我正在尝试使用WebRTC在应用程序中实现视频通话。共享offer、answer和ice-candidate后,点对点之间已成功建立连接。

远程对等点正在发送轨道(视频、音频),但本地对等点(接收对等点)未列出远程对等点连接的轨道。

将轨迹添加到对等连接:

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);
        });
  1. 如何接收并显示远端对端的视频?
  2. 有什么方法可以检查 RTCPeerConnection 的流/轨道吗?

我们在我们的应用程序中使用 Angular。这是完整的 JS 代码:

  1. 触发视频通话组件提供通话
  makeVideoCall(){
    var videoCallDialog = this.matDialog.open(VideoCallComponent, { 
      height: '600px', 
      width: '700px', 
      data : { 
        'friendUser' : this.friendUser
      }
    });
  }
  1. 监听视频通话报价并触发视频通话组件
    if (chatMessage.type == ChatType.VIDEO_CALL_OFFER){
      this.userChatService.findFriend(chatMessage.textFrom).subscribe(user=>{
        chatMessage.data = JSON.parse(chatMessage.data);
        var videoCallDialog = this.matDialog.open(VideoCallComponent, { 
          height: '600px', 
          width: '700px', 
          data : { 
            'friendUser' : user,
            'videoCallOfferChat' : chatMessage
          }
        });    
      });
    }
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);
      }
    }
  }

}
javascript angular webrtc
2个回答
0
投票
  1. 请尝试
this.peerConnection.addEventListener('track',function(event){
remoteVideo=document.getElementById('remoteVideo'); //Change your remote 'video element' id here
remoteVideo.srcObject = event.streams[0];
});
  1. 由于 WebRTC 连接是点对点的,我们无法检查或监控来自服务器的视频。信号服务器唯一知道的是通过它们共享的 SDP 和ice候选者。

0
投票

我必须以不同的方式创建报价 SDP。

const offer = await peerConnection.createOffer({
    offerToReceiveAudio: true,
    offerToReceiveVideo: true,
});
© www.soinside.com 2019 - 2024. All rights reserved.