1

2 台の PC からビデオをストリーミングし、両方のビデオをブラウザで見たいです。次のコードでは、一方の PC で両方のビデオを取得していますが、もう一方の PC では取得していません。これは、一方の PC がリモート PC にビデオをストリーミングしているが、もう一方の PC がそのビデオを最初のピアにストリーミングしていないことを意味します。このプログラムでは単一のピア接続オブジェクトを使用しています。ここで何がうまくいかないのか、誰でも教えてくれますか。

    var constraints = { audio: true, video: true };    
    var configuration = { iceServers:[{
                            urls: "stun:stun.services.mozilla.com",
                            username: "louis@mozilla.com",
                            credential: "webrtcdemo"
                        }, {
                            urls:["stun:xx.xx.xx.xx:8085"]
                        }]
    };
    var pc;

    function handlePeerAvailableCheckMsg(cmd) {
        console.log('peer-availability ' + cmd);
        start();
        if (cmd === "peer-available-yes") {        
            addCameraMic();
        }    
    }

    function addCameraMic() {
        var localStream;
var promisifiedOldGUM = function(constraints) {            
            var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia);

            if(!getUserMedia) {
                return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }            
            return new Promise(function(resolve, reject) {
                getUserMedia.call(navigator, constraints, resolve, reject);
            });
        }


        if(navigator.mediaDevices === undefined) {
            navigator.mediaDevices = {};
        }

        if(navigator.mediaDevices.getUserMedia === undefined) {
            navigator.mediaDevices.getUserMedia = promisifiedOldGUM;
        }

        //get local media (camera, microphone) and render on screen.
            navigator.mediaDevices.getUserMedia(constraints)
            .then(function(stream) {        
                var lvideo = document.getElementById('lvideo');
                localStream = stream;
                lvideo.src = window.URL.createObjectURL(localStream);        
                lvideo.onloadedmetadata = function(e) {
                    lvideo.play();
                };
                //Adding a track to a connection triggers renegotiation by firing an negotiationneeded event.
                //localStream.getTracks().forEach(track => pc.addTrack(track,localStream));
                pc.addStream(stream);
            }).catch(function(err) {
                console.log("getMediaUser Reject - " + err.name + ": " + err.message);
            });
    }

    function start() {        
        var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
        pc = new RTCPeerConnection(configuration);

        // send any ice candidates to the other peer, the local ICE agent needs to deliver a message to the other peer through the signaling server.
        // this will be done once the local description is set successfully, icecandidate events will be generated by local ice agent.
        pc.onicecandidate = function (evt) {
            if (!evt.candidate) return;
            console.log('onicecandidate: '+ evt.candidate);
            wbClient.send(JSON.stringify({"cmd":"new-ice-candidate","candidate": evt.candidate }));
        };

        //Start negotiation by setting local description and sending video offer to the remote peer.
        pc.onnegotiationneeded = function(evt){            
            pc.createOffer()
            .then(function(offer){ //offer is nothing but SDP
                    console.log('Local description is '+ offer + ' and its status when offer created' + pc.signalingState);                
                    return pc.setLocalDescription(offer);
            })
            .then(function(){
                    wbClient.send(JSON.stringify({"userName":userName,"roomId":roomId,"cmd":"video-offer","sdp":pc.localDescription}));                
            })
            .catch(function(err) {                
                    console.log("[INFO:whiteboard.js:start] - Offer could not be sent to the remote peer - " + err.name + ": " + err.message);
            });
        };

        pc.onaddstream = function (evt) {
            console.log('[INFO:whiteboard.js:start] - Receiving video stream from remote peer');
            var rvideo = document.getElementById('rvideo');
            rvideo.src = window.URL.createObjectURL(evt.stream);
            rvideo.onloadedmetadata = function(e) {
                console.log('remote video metadata loaded..');
                rvideo.play();
            };
        };        
    }

    //will be invoked when a message from remote peer arrives at this client
    function handleVideoOfferMsg(obj) {    

        var RTCSessionDescription = window.webkitRTCSessionDescription || window.RTCSessionDescription;
        //Session description based on received SDP from remote peer.
        var desc = new RTCSessionDescription(obj.sdp);
        var descJson = desc.toJSON();
        console.log('Received session description (new offer) : ' + JSON.stringify(descJson));    
        //Set remote peer's capabilities based on received SDP
        console.log('While processing incoming offer - LDT : ' + pc.localDescription + ' RDT ' + pc.remoteDescription);
        addCameraMic();
        pc.setRemoteDescription(desc)        
            .then(function(){
                return pc.createAnswer();
            })
            .then (function(answer){
                //var ansJson = answer.toJSON();
                return pc.setLocalDescription(answer);
            })        
            .then (function(){                              
                console.log('sending answer to the remote peer ' + pc.localDescription);
                wbClient.send(JSON.stringify({"userName":obj.userName,"roomId":roomId,"cmd":"video-answer","sdp":pc.localDescription}));                
            })        
            .catch(function(err) {            
                console.log("Error while sending answer " + err.name + ": " + err.message);      
            });
    }

    function handleVideoAnswerMsg(desc) {
        if (pc.localDescription === null || pc.localDescription.type !== "offer") return;
        var RTCSessionDescription = window.webkitRTCSessionDescription || window.RTCSessionDescription;
        var des = new RTCSessionDescription(desc);
        var descJson = des.toJSON();
        console.log('Received answer session description (new answer) : ' + JSON.stringify(descJson));
        pc.setRemoteDescription(des); //set remote description to incoming description object of remote peer
    }

    function handleNewICECandidateMsg(candidate) {    
        var RTCIceCandidate = window.webkitRTCIceCandidate || window.RTCIceCandidate;
        if (pc.localDescription !== null && pc.remoteDescription !== null && pc.signalingState === "stable")
            pc.addIceCandidate(new RTCIceCandidate(candidate))
        .catch(function(err) {
            console.log('handleNewICECandidateMsg ' + err.name + ": " + err.message);      
        });
    }
4

1 に答える 1

1

2 つの問題があります。

カメラがレース中

着信時にカメラが時間内に追加されていないようです:

    addCameraMic();
    pc.setRemoteDescription(desc)        
        .then(function(){
            return pc.createAnswer();
        })

addCameraMicは非同期関数ですが、promise を返さないため、競合しpc.setRemoteDescriptionて負ける可能性があります。つまりpc.createAnswer、ストリームが追加される前に実行され、ビデオなしで応答します。

addCameraMicpromise を返すように修正し、代わりにこれを試してください。

pc.setRemoteDescription(desc)
    .then(addCameraMic)
    .then(function() {
        return pc.createAnswer();
    })

これにより、ストリームが回答の前に追加されることが保証されます。

注:pc.setRemoteDescription ICE 候補者を受け入れる準備をするために、常に最初に電話してくださいpc。ICE 候補者は、オファーの直後に到着する場合があります。

アイス候補は思ったより早く到着

これに加えて、あなたhandleNewICECandidateMsgは間違っているように見えます:

function handleNewICECandidateMsg(candidate) {    
    if (pc.localDescription !== null && pc.remoteDescription !== null && pc.signalingState === "stable")
        pc.addIceCandidate(new RTCIceCandidate(candidate))

Trickle ICE は、オファー/アンサー交換をオーバーラップし、状態を待ちませんstable

ICE 候補は、ピアの成功コールバックが完了するとすぐにピアから発砲を開始しsetLocalDescriptionます。つまり、シグナル チャネルは (順序が維持されている場合)、次のようoffer, candidate, candidate, candidateになりanswer, candidate, candidate, candidateます。基本的に、候補を見つけたら追加します。

function handleNewICECandidateMsg(candidate) {    
    pc.addIceCandidate(new RTCIceCandidate(candidate))

それが役立つことを願っています。

于 2016-08-06T03:16:29.237 に答える