Media Server independent WebRTC player

birme

Jonas Birmé

Posted on April 7, 2022

Media Server independent WebRTC player

While original focus of WebRTC was on video conferencing it can also be used for real-time broadcast or streaming with ultra-low latency (DASH-IF WebRTC report). However, the adoption rate for using WebRTC in this context has been slow and one of the reasons is the lack of standard protocol for ingest (producer) and playback (viewer).

The ingest side is being addressed by the draft IETF standard WHIP that allows you to send media from a WHIP compliant sender software to a WHIP compliant media server. WHIP proposes a simple HTTP based protocol that will allow WebRTC based ingest of content into streaming services and/or CDNs.

On the playback side there are standardization initiatives in discussion but not as far progressed as on the ingest side with WHIP. WebRTC media servers provides WebRTC players but they are often tied to the specific WebRTC media server.

As we have not yet reached a common standard (transport method) for the SDP exchange between media server (broadcaster) and the player in this context we have launched an open source project for a media server independent WebRTC player.

Example of WebRTC player

A player with media server adapters where you either can use one of the included ones or build a custom adapter that you use on your own. We welcome contributions to this project in the form of media server adapters and this blog post will walk you through how to use and add an adapter

How to use it

If you just want to use the WebRTC player with any of the included adapters the HTML and Javascript below gives you an example.

<html>
  <head><script type="module" src="index.ts"></script></head>
  <body>
    <video autoplay muted controls>
    <button id="play">Play</button>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

And the Javascript (typescript) code.

import { WebRTCPlayer, ListAvailableAdapters } from "@eyevinn/webrtc-player";

const video = document.querySelector("video");
const iceServers = [{ urls: "stun:stun.l.google.com:19302" }];
document.querySelector<HTMLButtonElement>("#play").addEventListener("click", async () => {
  const channelUrl = "<media-server-url-to-channel>";
  const player = new WebRTCPlayer({ 
    video: video,
    type: "se.eyevinn.webrtc",
    iceServers: iceServers 
  });
  await player.load(new URL(channelUrl));
});
Enter fullscreen mode Exit fullscreen mode

The string se.eyevinn.webrtc specifies to use the included adapter for an Eyevinn WebRTC WHIP-broadcaster. To obtain a list of available adapters you can do the following.

ListAvailableAdapters().forEach(adapterType => {
  console.log(adapterType);
}
Enter fullscreen mode Exit fullscreen mode

Develop a custom adapter

If you want to use this WebRTC player but with a media server of your own you can develop a custom adapter and use that one instead. When you create an instance of the player you provide an AdapterFactoryFunction that will return a new instance of an adapter extending the base class BaseAdapter.

const player = new WebRTCPlayer({
  video: video, 
  type: "custom", 
  adapterFactory: (peer: RTCPeerConnection, channelUrl: URL) => {
    return new CustomAdapter(peer, channelUrl);
  }
});
Enter fullscreen mode Exit fullscreen mode

Set type === "custom" and the factory function in the constructor. A template for a custom adapter below.

import { BaseAdapter } from "@eyevinn/webrtc-player";

class CustomAdapter extends BaseAdapter {
  constructor(peer: RTCPeerConnection, channelUrl: URL) {
    super(peer, channelUrl);
  }

  // Overload SDP exchange method
  async exchangeSdp() {
    // do stuff here
  }
}
Enter fullscreen mode Exit fullscreen mode

The exchangeSdp() function is where you implement the media server specific way of exchanging SDPs. For example:

async exchangeSdp() {
  const response = await fetch(this.channelUrl.href, {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ sdp: this.localPeer.localDescription.sdp })
  });
  if (response.ok) {
    const { sdp } = await response.json();
    this.localPeer.setRemoteDescription({ type: "answer", sdp: sdp });
  }
}
Enter fullscreen mode Exit fullscreen mode

In the example above the local SDP is sent with an HTTP POST to the media server which in return responds with the remote SDP.

Contributing

If you want to include support for your media server or want to contribute in general we are very happy for a pull request to this project. To add an adapter to the project you first create the adapter in the same way as described above but also include it in the repository in the adapters folder. Then add your unique string to the list of adapters in adapters/factory.ts together with a factory function.

Related open source projects

About Eyevinn Technology

Eyevinn Technology is an independent consultant firm specialized in video and streaming. Independent in a way that we are not commercially tied to any platform or technology vendor.

At Eyevinn, every software developer consultant has a dedicated budget reserved for open source development and contribution to the open source community. This give us room for innovation, team building and personal competence development. And also gives us as a company a way to contribute back to the open source community.

Want to know more about Eyevinn and how it is to work here. Contact us at work@eyevinn.se!

💖 💪 🙅 🚩
birme
Jonas Birmé

Posted on April 7, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related