我希望能够在与WebRTC的对话过程中切换相机,而无需重新协商呼叫.
假设我们使用以下MediaStreamTrack.getSources方法有2个"mediaSources"对象:
{
id: "id_source_1" | "id_source_2",
facing: "user" | "environment",
kind: "kind_1" | "kind_2",
label: "label_1" | "label_2"
}
Run Code Online (Sandbox Code Playgroud)
我们用"source_1"(面向"用户")开始呼叫,我们希望用户能够切换到"source_2"(面向"环境").
在我当前的代码中,当用户单击"切换摄像机"按钮时,执行以下操作:( callingSession是当前的WebRTC会话)
var mediaParams = {
audio: true,
video: { deviceId : source_2.id},
options: {
muted: true,
mirror: true
},
elemId: 'localVideo'
};
callingSession.getUserMedia(mediaParams, function (error, stream) {
if (error) {
console.error('error getting user media');
} else {
var oldVideoTracks = callingSession.localStream.getVideoTracks();
var newVideoTracks = stream.getVideoTracks();
if (oldVideoTracks.length > 0 && newVideoTracks.length > 0) {
callingSession.localStream.removeTrack(oldVideoTracks[0]);
callingSession.localStream.addTrack(newVideoTracks[0]);
}
}
});
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,mediaParams约束现在设置为"source_2",我们将mediaParams新约束传递给该getUserMedia方法.然后我们从旧流和新流中获取视频轨道.
这段代码的主要问题是老流仍然与新流完全相同,即使传递给getUserMedia方法的新约束,所以显然是相同的视频轨道,当然没有任何反应,相机不是切换!!!
我在这段代码中做错了吗?有没有办法在没有重新协商 WebRTC的情况下切换相机?怎么样的实验方法applyConstraint()我无法在chrome中看到它?
谢谢.
更新 我的WebRTC应用程序是一个带有人行横道的离子应用程序=> webview是chrome
小智 7
为了替换当前相机,而不丢失候选进程,您必须使用以下示例代码,显然替换您自己的变量:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream){
localVideo.srcObject = stream;
stream.getVideoTracks().forEach(function(track) {
var sender = peerConnCallee.getSenders().find(function(s) {
return s.track.kind == track.kind;
});
sender.replaceTrack(track);
});
})
.catch(function(e) { });
Run Code Online (Sandbox Code Playgroud)
您可以在下一个站点中看到它的工作原理: Can Peek
在撰写本文时,WebRTC 规范非常有前景,但该规范的实现仍然因浏览器而异.目前Chrome的实施仍然很旧.不过感谢jib的评论和这个SO答案以及对SDP(会话描述协议)的更多理解,我现在可以使用Chrome切换摄像头了.
首先,我的getUserMedia方法的约束是错误的,这是我设法传递正确的约束:
var mediaParams = {
// the other constraints
video: {mandatory: {sourceId: source_2.id}}
// ...
};
Run Code Online (Sandbox Code Playgroud)
在getUserMedia使用mediaParams参数调用后,我们需要从对等连接中删除当前流,然后像这样添加新的:
peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
peerConnection.addLocalStream(stream);
Run Code Online (Sandbox Code Playgroud)
的代码这两行会触发onnegotiationneeded的上peerConnection对象,是指对等体1必须告诉对端2他改变的流,以便他需要一个新的说明.这就是我们需要创建商品,设置新描述并将此新描述发送给同行的原因:
peerConnection.createOffer()
.then(function (offer) {
peerConnection.setLocalDescription(offer);
})
.then(function () {
send(JSON.stringify({ "sdp": peerConnection.localDescription }));
});
Run Code Online (Sandbox Code Playgroud)
在这一点上,它取决于您send对SDP的期望.(在我的用例中,我必须使用WebSockets发送它们.)
一旦另一个对等体收到新的SDP,他必须在自己的对等连接中设置它:
var obj = JSON.parse(answer).sdp;
peerConnection.setRemoteDescription(new RTCSessionDescription(obj));
Run Code Online (Sandbox Code Playgroud)
我希望有一天这会有所帮助.
ReplaceTrack API 就是为此而定义的。
最终chrome将支持RTCRtpSender.replaceTrack方法(http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface),该方法可用于替换轨道而无需重新协商。您可以在此处跟踪 Chrome 中该功能的开发情况:https://www.chromestatus.com/feature/5347809238712320
它已经在某种程度上在本机 API 中可用。但它目前正在开发中,因此使用需要您自担风险。
| 归档时间: |
|
| 查看次数: |
7403 次 |
| 最近记录: |