WebRTC:切换摄像头
我希望能够在与WebRTC对话的同时切换摄像头,而不需要重新协商的调用。WebRTC:切换摄像头
假设我们有2个“mediaSources”使用MediaStreamTrack.getSources
方法对象:
{
id: "id_source_1" | "id_source_2",
facing: "user" | "environment",
kind: "kind_1" | "kind_2",
label: "label_1" | "label_2"
}
我们先从“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]);
}
}
});
正如你可以看到mediaParams
限制现在设置为“source_2”,我们通过这个mediaParams
新的约束到getUserMedia
方法。然后我们从旧流和新流获取视频轨道。
这段代码中的主要问题是,即使新的约束传递给getUserMedia
方法,旧的流仍然与新流完全相同,所以显然是相同的视频轨道,当然没有任何反应,并且相机不能切换!
我在这段代码中做错了什么?有什么方法可以在没有的情况下重新协商 WebRTC中的呼叫吗?那么实验方法applyConstraint()
我无法在Chrome中看到它?
谢谢。
UPDATE 我的WebRTC应用是离子应用程式人行横道=> web视图是铬
replaceTrack API只是此定义。
最终,Chrome将支持RTCRtpSender.replaceTrack方法(http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface),该方法可用于替换音轨而无需重新协商。您可以在Chrome浏览器中查看该功能的开发情况:https://www.chromestatus.com/feature/5347809238712320
它在本机API中已经在某种程度上可用。但它目前正在开发中,所以请自担风险。
我不知道如何使用'replaceTrack',因为'getUserMedia'中的'stream'与'callingSession.localStream'完全相同。 – dafriskymonkey
在写这篇文章的时候,WebRTC specification是非常有希望的,但是这个规范的实现在浏览器之间是不一样的。目前Chrome的实施仍然很久。尽管如此,多亏了臂架评论和SO answer以及SDP (Session Description Protocol)的更多了解,我现在可以使用Chrome切换摄像机。
首先,制约我getUserMedia
方法是错误的,这里是我如何成功地传递正确的约束:
var mediaParams = {
// the other constraints
video: {mandatory: {sourceId: source_2.id}}
// ...
};
调用getUserMedia
与mediaParams
参数后,我们需要从对等连接删除当前流然后添加新的一个是这样的:
peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
peerConnection.addLocalStream(stream);
的代码这两行会触发onnegotiationneeded
的peerConnection
物体上时,意味着对等体1个必须告诉同伴2他改变了流,所以他需要一个新的描述。为什么我们需要创建一个报价多数民众赞成,设置新的描述,并将其发送新的描述的同行:要如何send
的SDP
peerConnection.createOffer()
.then(function (offer) {
peerConnection.setLocalDescription(offer);
})
.then(function() {
send(JSON.stringify({ "sdp": peerConnection.localDescription }));
});
在这一点上它给你。 (在我的使用情况下,我不得不使用WebSockets向他们发送。)
一旦其他同行接受新的SDP,他必须将其在自己的对等连接:
var obj = JSON.parse(answer).sdp;
peerConnection.setRemoteDescription(new RTCSessionDescription(obj));
我希望这会帮助别人一天。
谢谢! 我浪费了我12小时的时间,你的回答让我感到很开心。但切换相机脸部时遇到了一个问题。如果我切换相机3-4次,我的视频通话就会中断。 问题出在oniceconnectionstatechanged。 – hamzox
@hamzox我不记得确切的细节,但由于某种原因'onnegotiationneeded'被触发两次。我刚刚创建了一个布尔值,我在'onnegotiationneeded'回调中切换了布尔的状态,如果布尔值为'true',那么我执行'peerConnection.createOffer',这确保'createOffer'被执行1 2.它确实是一个黑客,但我不想浪费更多时间在这上面;)希望这会有所帮助 – dafriskymonkey
我会隔离并确保您可以在本地首先同时查看两个摄像头(许多手机不允许在同一时间使用前后摄像头),然后再与对等连接进行混淆。另外,使用'video:{deviceId:{exact:source_2.id}}'强制约束。最后,'MediaStreamTrack.getSources'已被'navigator.mediaDevices.enumerateDevices'取代,所以试试。如果一切正常,请先尝试从对等连接中移除流,然后再重新添加。 – jib
@jib使用当前实现,我可以在本地切换源(也适用于移动设备)。我无法切换发送给对等体的流。 – dafriskymonkey
我不是Chrome上的专家(这在Firefox中不是问题,它支持'replaceTrack'),但是在Chrome中我认为你可能还需要[renegotiate](http://*.com/questions/35504214/如何在媒体流中添加媒体流/ 35515536#35515536),你可以通过数据通道做到这一点,所以它将接近无缝。 – jib