我正在使用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上。
我希望有人幫助我。
謝謝你,
達明
看到我的答案https://stackoverflow.com/questions/46725469/opentok-on-streamcreated-subscribe-makes-mobile-chrome-freeze/46731092?noredirect=1#comment80519679_46731092 - 鉻61錯誤,那裏是一種解決方法: -/ –
非常感謝!解決方法運行良好。 –