2017-10-17 188 views
0

我正在使用WebRTC在Angular 2應用程序上創建通信。此應用程序用於筆記本電腦和智能手機與CSS規則來處理響應。WebRTC屏幕在手機上凍結

我有一個特定的問題:我的應用程序完全可以在筆記本電腦上的2個網頁之間工作,但是當我在智能手機上打開網頁時,頁面在通信開始時(智能手機和筆記本電腦之間)凍結。該頁面只在智能手機端凍結,在筆記本電腦端工作良好。

我只在Chrome上有此行爲。所有在Firefox上運行良好。

當我評論addStream()函數時,問題「已解決」。現在,我使用addTrack()函數代替addStream(),但問題仍然存在。

這是我的服務來創建和管理WebRTC通信。我使用visioApi通過信令服務器發送數據。

interface IceCandidateObject { 
    candidate: string 
    sdpMid: string 
    sdpMLineIndex: number 
    } 

@Injectable() 
export class VisioService { 
    conf: RTCConfiguration = { 
     iceServers: [ 
      // Peer Configuration 
      { 
      urls: 'xxxxxx', 
      credential: 'xxxxxx', 
      username: 'xxxxxx', 
      }, 
      { 
      urls: 'xxxxx', 
      credential: 'xxxxxx', 
      username: 'xxxxxx', 
      }, 
      { 
      urls: 'xxxxxxxx', 
      credential: 'xxxxxx', 
      username: 'xxxxx', 
      }, 
     ], 
     } 
     pc: any                    // Peer connection 
     stream: any                   // Video stream 
     target: string                  // target userkey 
     remoteVideo = undefined 
     constraints = { 
     mandatory: [{ OfferToReceiveAudio: true }, { OfferToReceiveVideo: true }], 
     optional: [{ DtlsSrtpKeyAgreement: true }], 
     } 
     callId: string 
     caller = false 
     videoRunning = true 
     audioRunning = true 

    constructor(
     private visioApi: ApiVisio, 
     private zpConnection: ZetaPushConnection, 
    ) { 
     this.visioApi.onReplyToCall.subscribe((onReplyToCallMsg) => { 
      console.log('VisioService::OnReplyToCall') 
      this.callId = onReplyToCallMsg.result.id 
     }) 

     this.visioApi.onCallUser.subscribe((onCallUserMsg) => { 
      console.log('VisioService::OnCallUser') 
      this.callId = onCallUserMsg.result.callObject.id 
     }) 

     this.visioApi.onSendVisioMessage.subscribe((onSendVisioMsg) => { 
      const message = onSendVisioMsg.result.message 

      switch (message.type) { 

       case 'offer': 
        this.pc.setRemoteDescription(new RTCSessionDescription(message),() => { 
         this.pc.createAnswer().then((answer) => { 
          this.visioApi.sendVisioMessage(this.target, answer) 
          return this.pc.setLocalDescription(answer) 
         }).catch((err) => { 
          console.log('FailedCreateAnswer', err) 
         }) 
        }, (err) => { 
         console.log('SetRemoteDescriptionFailed', err) 
        }) 
        break 

       case 'answer': 
        const answerSessionDescription: RTCSessionDescriptionInit = { 
         sdp: message.sdp, 
         type: message.type 
        } 

        this.pc.setRemoteDescription(new RTCSessionDescription(answerSessionDescription)) 
        break 

       case 'icecandidate': 
        const ice: RTCIceCandidateInit = { 
         candidate: message.candidate, 
         sdpMid: message.sdpMid, 
         sdpMLineIndex: message.sdpMLineIndex 
        } 

        this.pc.addIceCandidate(new RTCIceCandidate(ice)) 
        break 
      } 
     }) 
    } 

    /** 
    * Method used to launch a visio call with the other user 
    * @param target : userKey of the target 
    */ 
    launchVisioCall(target: string): void { 
     this.target = target 
     this.visioApi.callUser(this.target) 
    } 

    /** 
    * Stop the call 
    */ 
    stopCall(): void { 
     if (this.pc && this.pc.signalingState !== 'closed') { 
      this.pc.close() 
     } 
    } 

    /** 
    * Method to reply to an incoming call 
    */ 
    ReplyToIncomingCall(): void { 
     this.visioApi.replyToCall(this.callId, this.target) 
    } 

    /** 
    * Method to refuse an incoming call 
    */ 
    refuseIncomingCall(): void { 
     this.visioApi.refuseCall(this.callId, this.target) 
    } 

    /** 
    * Method to set the call id 
    * @param id : Id of the call 
    */ 
    setCallId(id: string): void { 
     this.callId = id 
    } 

    /** 
    * Method to set the target 
    * @param target : userKey of the target 
    */ 
    setTarget(target: string): void { 
     this.target = target 
    } 

    /** 
    * Init 
    * @param videoElement : remote video 
    * @param videoRemote : local video 
    */ 
    init(videoElement: HTMLVideoElement, videoRemote: HTMLVideoElement, caller: boolean): void { 
     this.caller = caller 
     this.startLocalVideo(videoElement) 
     this.remoteVideo = videoRemote 
    } 

    /** 
    * Start the local video 
    */ 
    startLocalVideo(videoElement: HTMLVideoElement): void { 
     videoElement.volume = 0; 
     videoElement.muted = false; 
     videoElement.load(); 
     videoElement.play().then((result) => { 
      console.log('==> video played', result) 
     }).catch((err) => { 
      console.error('==> video error', err) 
     }); 

     navigator.mediaDevices.getUserMedia({ 
      audio: true, 
      video: true 
     }).then((stream) => { 
      videoElement.srcObject = stream 
      this.stream = stream 
      this.initPeerConnection() 
     }).catch((err) => { 
      console.error('err local video', err) 
     }) 
    } 

    /** 
    * Init peer connection 
    */ 
    initPeerConnection(): void { 
     this.pc = new RTCPeerConnection(this.conf) 

     this.stream.getTracks().forEach(element => { 
      this.stream.addTrack(element); 
      if (this.pc.addTrack) { 
       this.pc.addTrack(element, this.stream); 
      } else { 
       setTimeout(() => this.pc.dispatchEvent(new Event('negociationneeded'))) 
      } 
     }); 

     this.pc.onnegociationneeded = event => { 
      this.pc.createOffer().then((offer) => { 
       this.pc.setLocalDescription(offer) 
      }).then(() => { 
       const offerMsg: Message = { 
        sdp: this.pc.localDescription, 
        type: 'offer' 
       } 
       this.visioApi.sendVisioMessage(this.target, offerMsg) 
      }) 
     } 


     this.pc.addStream(this.stream) 
     // Handle ICE Candidates 
     this.pc.onicecandidate = event => { 
      const iceMessage: Message = { 
      candidate: event.candidate.candidate, 
      sdpMid: event.candidate.sdpMid, 
      sdpMLineIndex: event.candidate.sdpMLineIndex, 
      type: event.type, 
      } 

      if (event.candidate != null) { 
      this.visioApi.sendVisioMessage(this.target, iceMessage) 
      } 
     } 

     // Handle new stream added 
     this.pc.onaddstream = event => { 
      console.log('onAddStream::Event', event) 

      const video = this.remoteVideo 
      video.srcObject = event.stream 
      video.load(); 
      video.play() 
     } 

     if (!this.caller) { 
      this.sendOffer() 
     } 
    } 

    sendOffer(): void { 
     // We create an offer when the target accept the call 
     this.pc.createOffer(offer => { 
      this.pc.setLocalDescription(new RTCSessionDescription(offer)).then(() => { 
       const offerMsg: Message = { 
        sdp: offer.sdp, 
        type: offer.type 
       } 
       this.visioApi.sendVisioMessage(this.target, offerMsg) 
      }) 
     }, (err) => { 
      console.log('ErrorCreateOffer', err) 
     }, this.constraints) 
    } 

    toggleAudio(): void { 
     this.stream.getTracks().forEach(element => { 
      if (element.kind === 'audio') { 
       element.enabled = !element.enabled 
      } 
     }) 
    } 

    toggleVideo(): void { 
     this.stream.getTracks().forEach(element => { 
      if (element.kind === 'video') { 
       element.enabled = !element.enabled 
      } 
     }) 
    } 

    terminateCall(): void { 
     this.visioApi.terminateCall(this.callId, this.target) 
    } 

    stopWebcam(): void { 
     this.stream.getTracks().forEach(track => { 
      track.stop() 
     }) 

我在每個平臺上使用Chrome 61,而我的智能手機在Android上。

我希望有人幫助我。

謝謝你,

達明

+1

看到我的答案https://stackoverflow.com/questions/46725469/opentok-on-streamcreated-subscribe-makes-mobile-chrome-freeze/46731092?noredirect=1#comment80519679_46731092 - 鉻61錯誤,那裏是一種解決方法: -/ –

+0

非常感謝!解決方法運行良好。 –

回答