web-dev-qa-db-ja.com

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"
 }
_

「source_1」(「user」に面している)から呼び出しを開始し、ユーザーが「source_2」(「environment」に面している)に切り替えられるようにします。

私の現在のコードでは、ユーザーが「カメラの切り替え」ボタンをクリックすると、次のように実行されます:(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アプリはionic crosswalk付きアプリ=>ウェブビューはクロム

8
dafriskymonkey

この投稿を書いている時点では、WebRTC specification は非常に有望ですが、それでもこの仕様の実装はブラウザーごとに異なります。現在、Chromeの実装はまだ古いです。それでも、jibコメントとこれに感謝します SO回答 そして 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);

これらの2行のコードは、onnegotiationneededオブジェクトでpeerConnectionをトリガーします。つまり、ピア1はピア2にストリームを変更したことを通知する必要があるため、新しい説明が必要になります。そのため、オファーを作成し、新しい説明を設定して、この新しい説明をピアに送信する必要があります。

peerConnection.createOffer()
.then(function (offer) {
      peerConnection.setLocalDescription(offer);
})
.then(function () {
      send(JSON.stringify({ "sdp": peerConnection.localDescription }));
});

この時点で、SDPをどのようにsendするかはあなた次第です。 (私のユースケースでは、WebSocketを使用して送信する必要がありました。)

他のピアが新しいSDPを受信したら、それを自分のピア接続に設定する必要があります。

var obj = JSON.parse(answer).sdp;
peerConnection.setRemoteDescription(new RTCSessionDescription(obj));

これがいつか誰かに役立つことを願っています。

5
dafriskymonkey

replaceTrack APIは、このためだけに定義されました。

最終的にchromeはRTCRtpSender.replaceTrackメソッド( http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface )をサポートします。これは使用できます再ネゴシエーションなしでトラックを置き換えるには、その機能の開発をChrome here: https://www.chromestatus.com/feature/534780923871232 で追跡できます。

ネイティブAPIではすでにある程度利用可能です。ただし、現在開発中ですので、自己責任でご利用ください。

1

候補プロセスを失うことなく現在のカメラを置き換えるには、次のサンプルコードを使用する必要があります。明らかに、独自の変数を置き換えます。

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) { });

次のサイトで機能していることがわかります: Can Peek

0
Pedro