저는 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 버그가 있습니다
는 https://stackoverflow.com/questions/46725469/opentok-on-streamcreated-subscribe-makes-mobile-chrome-freeze/46731092?noredirect=1#comment80519679_46731092 에 대한 내 대답을 참조 해결 방법 : -/ –
대단히 감사합니다! 해결 방법이 효과적입니다. –