Javascript RTPeerConnection跟踪事件有时返回空流

Javascript RTPeerConnection跟踪事件有时返回空流,javascript,webrtc,video-capture,mediastream,rtcpeerconnection,Javascript,Webrtc,Video Capture,Mediastream,Rtcpeerconnection,建立首次成功的RTC连接的最佳方法是什么 下面的代码有时有效,有时无效。我认为无论是在createAnswer之前还是之后调用addIceCandidate都是一个问题,我不知道哪一个更可取,或者这是否就是问题所在(为什么它一直不起作用,只需将它粘贴到浏览器中,并尝试几次,您至少会看到有时会出现“调用”按钮不能一直工作): 录像带{ 宽度:300px } 开始 呼叫 变量ls、p、p2、bpl、bpr、con={ //sdpSemantics:“默认值” },deets={ offerToRe

建立首次成功的RTC连接的最佳方法是什么

下面的代码有时有效,有时无效。我认为无论是在
createAnswer
之前还是之后调用
addIceCandidate
都是一个问题,我不知道哪一个更可取,或者这是否就是问题所在(为什么它一直不起作用,只需将它粘贴到浏览器中,并尝试几次,您至少会看到有时会出现“调用”按钮不能一直工作):


录像带{
宽度:300px
}
开始
呼叫
变量ls、p、p2、bpl、bpr、con={ //sdpSemantics:“默认值” },deets={ offerToReceiveAudio:1, offerToReceiveVideo:1 } 函数g(){ 领航员。 mediaDevices.getDisplayMedia()。然后(s=>{ ls=L.srcObject=s; }) } s、 onclick=e=>{ g() }; 函数wow(数据={}){ 让本地=新的RTPeerConnection(con), 远程=新的RTPeerConnection(con); local.addEventListener(“ICEScandidate”,e=>oic(remote,e)); remote.addEventListener(“ICEScandidate”,e=>oic(local,e)); remote.addEventListener(“track”,e=>grs(data.video,e)); 数据 .localStream .getTracks() .forEach(t=>{ local.addTrack(t,data.localStream); }); local.createOffer(deets)。然后(offer=>{ local.setLocalDescription(提供); remote.setRemoteDescription(报价); remote.createAnswer().then(答案=>{ remote.setLocalDescription(应答); local.setRemoteDescription(应答); }) }); } c、 onclick=e=>{ 让localStream=ls; 哇({ 视频:R, 本地流 }); 哇({ 视频:R2, 本地流 }); 哇({ 视频:R3, 本地流 }); }; 函数grs(vid,e){ if(vid.srcObject!==e.streams[0]){ vid.srcObject=e.streams[0]; } } 功能oic(pc,e){ 让其他=pc; 如果(如候选人) 其他 .addIceCandidate(如候选人) }

请注意,有时视频流会稍后进入,并且是空的。

请注意。首先,您使用的是异步函数,因此在调用它时无法解析(例如,用户不响应提示或浏览器拒绝提示)。其次,您没有处理错误,将catch()块添加到代码中,浏览器将回答您的问题本身

我以前使用PeerConnection API时遇到了相同的问题,问题是统一计划SDP格式,也许值得一读


流是如何清空的?它没有轨道吗?或者ice连接没有建立?@PhilippHancke它似乎至少有一个音轨,只是没有显示视频元素中的任何内容。我认为这与addIcecAndidate之前(或之后?)创建的答案有关。您知道哪一个必须首先出现吗?谢谢,尽管问题与屏幕捕获API无关;相反,主要是RTPeerConnection对象,我有两个按钮,因此在捕获流后,我是否可以单击Call?你可以解释一下吗?@bluejayke在统一计划中,发送器和接收器成对创建,并且在远程SDP提供跟踪之前很久,可能已经创建了一个收发器.receiver.track。因此,在rtpeerconnection.ontrack中激发的磁道不再保证具有与该磁道的发送方版本匹配的ID。此外,由于addTransponser()和replaceTrack()的原因,一个磁道可能会被发送多次。@bluejayke这意味着必须有一个磁道,您可以尝试测试plan-b,应该可以正常工作。顺便说一句,您的代码很难阅读。这是添加到RTPeerConnection的附加库吗?如果是这样的话,我更愿意这样做,而不需要任何额外的库。代码的主要部分在wow()函数中,ontrack事件位于底部,所以我应该使用默认的plan-b,还是应该使用统一的plan(来修复错误)?
<body>
    <style>
        video {
            width: 300px
        }
    </style>
    <button id="s">start</button>
    <button id=c>Call</button><br>
<video id="L" autoplay muted></video>
<video id=R autoplay></video>
<video id=R2 autoplay></video>
<video id=R3 autoplay></video>
<script>
var ls, p, p2, bpl, bpr, con = {
 //   sdpSemantics: "default"
}, deets = {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
}

function g() {
    navigator.
    mediaDevices.getDisplayMedia().then(s => {
        ls = L.srcObject = s;

    })
}
s.onclick = e => {
    g()
};

function wow(data={}) {
    let local  = new RTCPeerConnection(con),
        remote = new RTCPeerConnection(con);

    local .addEventListener("icecandidate", e => oic(remote, e));
    remote.addEventListener("icecandidate", e => oic(local , e));

    remote.addEventListener("track", e => grs(data.video, e));

    data
        .localStream
        .getTracks()
        .forEach(t => {
            local.addTrack(t, data.localStream);
        });

    local.createOffer(deets).then(offer => {
        local .setLocalDescription(offer);
        remote.setRemoteDescription(offer);

        remote.createAnswer().then(answer => {
            remote.setLocalDescription(answer);
            local .setRemoteDescription(answer);
        })
    });
}

c.onclick = e => {
    let localStream = ls;
    wow({
        video: R,
        localStream
    });

    wow({
        video: R2,
        localStream
    });

    wow({
        video: R3,
        localStream
    });

};

function grs(vid,e) { 
    if(vid.srcObject !== e.streams[0]) {
        vid.srcObject = e.streams[0];
    }
}

function oic(pc, e) {
    let other = pc;
    if(e.candidate)
        other
        .addIceCandidate(e.candidate)
}
</script>
</video>
</body>