2016-08-24 1964 views
7

我希望能够在与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视图是铬

+0

我会隔离并确保您可以在本地首先同时查看两个摄像头(许多手机不允许在同一时间使用前后摄像头),然后再与对等连接进行混淆。另外,使用'video:{deviceId:{exact:source_2.id}}'强制约束。最后,'MediaStreamTrack.getSources'已被'navigator.mediaDevices.enumerateDevices'取代,所以试试。如果一切正常,请先尝试从对等连接中移除流,然后再重新添加。 – jib

+0

@jib使用当前实现,我可以在本地切换源(也适用于移动设备)。我无法切换发送给对等体的流。 – dafriskymonkey

+1

我不是Chrome上的专家(这在Firefox中不是问题,它支持'replaceTrack'),但是在Chrome中我认为你可能还需要[renegotiate](http://stackoverflow.com/questions/35504214/如何在媒体流中添加媒体流/ 35515536​​#35515536​​),你可以通过数据通道做到这一点,所以它将接近无缝。 – jib

回答

1

replaceTrack API只是此定义。

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

它在本机API中已经在某种程度上可用。但它目前正在开发中,所以请自担风险。

+0

我不知道如何使用'replaceTrack',因为'getUserMedia'中的'stream'与'callingSession.localStream'完全相同。 – dafriskymonkey

5

在写这篇文章的时候,WebRTC specification是非常有希望的,但是这个规范的实现在浏览器之间是不一样的。目前Chrome的实施仍然很久。尽管如此,多亏了臂架评论和SO answer以及SDP (Session Description Protocol)的更多了解,我现在可以使用Chrome切换摄像机。

首先,制约我getUserMedia方法是错误的,这里是我如何成功地传递正确的约束:

var mediaParams = { 
      // the other constraints 
      video: {mandatory: {sourceId: source_2.id}} 
      // ... 
     }; 

调用getUserMediamediaParams参数后,我们需要从对等连接删除当前流然后添加新的一个是这样的:

peerConnection.removeStream(peerConnection.getLocalStreams()[0]); 
peerConnection.addLocalStream(stream); 

的代码这两行会触发onnegotiationneededpeerConnection物体上时,意味着对等体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)); 

我希望这会帮助别人一天。

+0

谢谢! 我浪费了我12小时的时间,你的回答让我感到很开心。但切换相机脸部时遇到了一个问题。如果我切换相机3-4次,我的视频通话就会中断。 问题出在oniceconnectionstatechanged。 – hamzox

+0

@hamzox我不记得确切的细节,但由于某种原因'onnegotiationneeded'被触发两次。我刚刚创建了一个布尔值,我在'onnegotiationneeded'回调中切换了布尔的状态,如果布尔值为'true',那么我执行'peerConnection.createOffer',这确保'createOffer'被执行1 2.它确实是一个黑客,但我不想浪费更多时间在这上面;)希望这会有所帮助 – dafriskymonkey

相关问题