我正在使用WebRTC在Angular 2应用程序上创建通信。此应用程序用于具有CSS规则的笔记本电脑和智能手机,以处理响应。
我有一个特定问题:我的应用程序在笔记本电脑上的两个网页之间完美地工作,但是当我在智能手机上打开网页时,页面会在通信开始时冻结(智能手机和笔记本电脑之间)。该页面仅在智能手机端冻结,所有这些都在笔记本电脑上正常工作。
我仅在Chrome上有这种行为。一切都适用于Firefox。
问题是解决了#34;当我评论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上使用。
我希望有人帮助我。
谢谢,
达明
答案 0 :(得分:0)
有一个chrome 61 bug。
要解决此问题,请参阅Philipp Hancke(Opentok on streamCreated subscribe makes mobile chrome freeze)
的答案错误的详细信息:https://bugs.chromium.org/p/chromium/issues/detail?id=769148
解决方法:在每个html视频上放置border-radius: 1px;
。