2017-10-17 3 views
0

저는 WebRTC를 사용하여 Angular 2 응용 프로그램에서 통신을 만들고 있습니다. 이 응용 프로그램은 응답 성을 처리하기 위해 CSS 규칙이있는 랩톱 및 스마트 폰에서 사용됩니다.WebRTC 화면이 모바일에서 고정되었습니다.

다음과 같은 특정 문제가 있습니다. 응용 프로그램이 랩톱의 두 웹 페이지간에 완벽하게 작동하지만 스마트 폰에서 웹 페이지를 열면 통신이 시작될 때 스마트 폰과 랩톱간에 페이지가 고정됩니다. 페이지는 스마트 폰 쪽에서 만 고정되며 노트북에서 모두 정상적으로 작동합니다.

이 문제는 Chrome에서만 발생합니다. Firefox에서 모두 정상적으로 작동합니다.

addStream() 함수에 주석을 달면 문제가 "해결되었습니다". 이제 addStream() 대신 addTrack() 함수를 사용하지만 문제는 여전히 여기에 있습니다.

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에 있습니다.

누구든지 도와 주길 바랍니다.

데미안 크롬 61 버그가 있습니다

+1

는 https://stackoverflow.com/questions/46725469/opentok-on-streamcreated-subscribe-makes-mobile-chrome-freeze/46731092?noredirect=1#comment80519679_46731092 에 대한 내 대답을 참조 해결 방법 : -/ –

+0

대단히 감사합니다! 해결 방법이 효과적입니다. –

답변

관련 문제