2

What is the best approach for setting up an RTC connection that will success the first time ?

The following code sometimes works, sometimes doesn't. I think it's a problem with addIceCandidate being called either before or after createAnswer, and I don't know which is preferable, or if that is even the issue (for why its not working all the time, just paste it into a browser, and try it a few times, you should see that at least sometimes the "call" button doesn't work all the time):

<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>

Notice how sometimes the video streams come in later and empty.

  • how is the stream empty? Does it have no tracks? Or does the ice connection not establish? – Philipp Hancke Mar 24 '20 at 12:03
  • @PhilippHancke it seems to have at least one track, it just doesnt show anything in the video element. I think its something to do with the answer being created before the addIcecAndidate (or after?) Do you know which one has to come first? – B''H Bi'ezras -- Boruch Hashem Mar 24 '20 at 22:26

2 Answers2

3

i run into the same problem when i use PeerConnection API before, the problem is Unified Plan SDP format, maybe it worth to read.

ssskip
  • 259
  • 1
  • 6
  • can u explain it a little? – B''H Bi'ezras -- Boruch Hashem Apr 03 '20 at 01:40
  • @bluejayke In Unified Plan, senders and receivers are created in pairs of transceivers, and a transceiver.receiver.track may have been created long before remote SDP offers a track. As such, the track that is fired in RTCPeerConnection.ontrack is no longer guaranteed to have an ID matching the sender-side version of the track. Furthermore, because of addTransceiver() and replaceTrack(), a track may be sent multiple times. – ssskip Apr 03 '20 at 16:04
  • @bluejayke that means there must be have a track, you can try to test plan-b, should be works fine. BTW your code is hard to read – ssskip Apr 03 '20 at 16:06
  • is this an additional library added onto RTCPeerConnection? If so, I would prefer to do this without any extra libraries. The main part of the code is in the wow() function, the ontrack event is at the bottom – B''H Bi'ezras -- Boruch Hashem Apr 03 '20 at 20:24
  • so i should use the default plan-b, or I should use unified plan (to fix the error)? – B''H Bi'ezras -- Boruch Hashem Apr 05 '20 at 10:56
  • @bluejayke i prefer use unified plan, firefox use unified plan, you still need handle this problem anyway – ssskip Apr 05 '20 at 14:32
0

Please look again at documentation. At first, you are using async functions, so it could not resolve at the time then you call it (for example user doesn't answer for prompt or browser decline it at all). At second, you're not handling errors, add catch() block to your code and browser will answer to your question itself

Travnikov.dev
  • 464
  • 6
  • 14