WebRTC:切换相机

daf*_*key 7 webrtc

我希望能够在与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


daf*_*key 5

在撰写本文时,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)

我希望有一天这会有所帮助.


Dr.*_*ard 1

ReplaceTrack API 就是为此而定义的。

最终chrome将支持RTCRtpSender.replaceTrack方法(http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface),该方法可用于替换轨道而无需重新协商。您可以在此处跟踪 Chrome 中该功能的开发情况:https://www.chromestatus.com/feature/5347809238712320

它已经在某种程度上在本机 API 中可用。但它目前正在开发中,因此使用需要您自担风险。