Danny Wang
Danny Wang

Reputation: 449

Why is WebRTC remote video source generated by URL.createObjectURL

In this document, it uses URL.createObjectURL to set the video source. (This is the code to answer a call).

var offer = getOfferFromFriend();
navigator.getUserMedia({video: true}, function(stream) {
  pc.onaddstream = e => video.src = URL.createObjectURL(e.stream);
  pc.addStream(stream);

  pc.setRemoteDescription(new RTCSessionDescription(offer), function() {
    pc.createAnswer(function(answer) {
      pc.setLocalDescription(answer, function() {
        // send the answer to a server to be forwarded back to the caller (you)
      }, error);
    }, error);
  }, error);
});

I expected video.src to be the address to retrieve the remote video. So it should be fixed and given by the other side of the connection (whoever initiated the call). But the value of URL.createObjectURL is generated on the answerer's side, and it event depends on when the function is called. How it can be used to get the remote video stream?

Edit: The result of URL.createObjectURL looks like blob:http://some.site.com/xxxx-the-token-xxxx. With this string, how does the video component know where to load the remote stream? Is there a hashmap of {url:stream} stored somewhere? If so, how does the video component access the hashmap?

A stream object does store a token string, which you can get with stream.toURL. But it is different from the result of URL.createObjectURL. The value of URL.createObjectURL depends on time. If you call it twice in a row, you get different values.

Upvotes: 3

Views: 4167

Answers (2)

jib
jib

Reputation: 42450

URL.createObjectURL(stream) is a hack. Stop using it. Efforts are underway to remove it.

Use video.srcObject = stream directly instead. It is standard and well-implemented.

This assignment of a local resource should never have been a URL in the first place, and is a red herring to understanding how WebRTC works.

WebRTC is a transmission API, sending data directly from one peer to another. No content URLs are involved. The remote stream you get from onaddstream is a local object receiver side, and is the live streaming result of the transmission, ready to be played.

The documentation you read is old and outdated. Thanks for pointing it out, I'll fix it. It has other problems: you should call setRemoteDescription immediately, not wait for the receiver to share their camera, otherwise incoming candidates are missed. Instead of the code you show, do this:

pc.onaddstream = e => video.srcObject = e.stream;

function getOfferFromFriend(offer) {
  return pc.setRemoteDescription(new RTCSessionDescription(offer))
    .then(() => navigator.getUserMedia({video: true}))
    .then(stream => {
      pc.addStream(stream);
      return pc.createAnswer();
    })
    .then(answer => pc.setLocalDescription(answer))
    .then(() => {
      // send the answer to a server to be forwarded back to the caller (you)
    })
    .catch(error);
}

It uses srcObject, avoids the deprecated callback API, and won't cause intermittent ICE failures.

Upvotes: 11

Adrian Ber
Adrian Ber

Reputation: 21370

Because a WebRTC connection involves several steps and what you get from such a connection is a stream. But the src property of the video tag does not accept a stream, but a URL. And this is the way to "convert" a stream to a URL.

Upvotes: 1

Related Questions