2016-08-24 132 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

相關問題