WebRTC signaling

[This documentation is work in progress]

There is no standardized signaling protocol for WebRTC applications. For this reason,  the UV4L Streaming Server attempts to support or leverage a variety of them so that they can be used in different scenarios:

  1. built-in, “proprietary” message passing over websocket;
  2. Janus, a general purpose WebRTC Gateway;
  3. PeerJS (work-in-progress);
  4. XMPP Jingle (experimental, out of the scope of this doc.)
Built-in signaling

This signaling protocol is implemented in the UV4L Streaming Server module itself and allows a peer (e.g. a browser) to initiate a bidirectional, p2p audio-video-data call session with a uv4l instance. This protocol is based on message passing over websocket, which must stay open for the whole duration of the session. Messages are in JSON format and should include a mandatory what field identifying a request or an answer, a data field specifying the content of the request or the answer, and may include an options field if a request supports it (e.g. a call request).

  • call request. This is the very first message in a session and is required by the initiator to start the call with uv4l:
   what: "call",
   options: {
      force_hw_vcodec: true,
      vformat: 30

At the moment of writing, options may only include whether uv4l has to use the hardware encoder and decoder, if supported by the platform on which it is running, and what resolution and frame rate shall be used in this case. Note that all other options affecting a WebRTC session can be modified, before it begins, through the RESTful API.

  • offer answer. On a call request, uv4l answers with an offer containing its SDP (the string reported as <uv4l-sdp> for simplicity below) :
       what: "offer",
       data: "<uv4l-sdp>"
  • generateIceCandidates request. After receiving the remote (uv4l) SDP, the initiator shall ask uv4l to start to generate its own list of ICE candidates (this request might be turned into a no-op in the future as it could be implicit in the call request, but for now just do it):
       what: "generateIceCandidates"
  • answer request. The initiator can in turn provide its local SDP with the following message:
       what: "answer",
       data: "<local-sdp>"
  • iceCandidates answer. As soon as uv4l has gathered its ICE candidates, it will pass all of them to the initiator (as an array):
       what: "iceCandidates",
       data: <array-of-uv4l-ice-candidates>
  • addIceCandidate request. The initiator tells uv4l to add the one local ICE Candidate specified. This should be typically sent for each local ICE Candidate being generated by the initiator:
       what: "addIceCandidate",
       data: "<local-ice-candidate>"
  • message message. Messages from uv4l during the session (typically errors), before possibly unilaterally closing the socket, come in the following form:

       what: "message",
       data: "<error-message>"

hangup request. This can be sent by initiator to signal that the call has terminated. Alternatively, to hangup the initiator can just close the websocket.

   what: "hangup"

As you can see the protocol is reasonably simple and can be easily adapted or wrapped into more sophisticated signaling protocols for interoperability with third-party infrastructures.

An example of how all the above works with a simple web application can be found here.

Janus WebRTC Gateway

At the moment of writing, the UV4L Streaming Server supports the videoroom plugin:

This is a plugin implementing a videoconferencing SFU (Selective Forwarding Unit) for Janus, that is an audio/video/data router. This means that the plugin implements a virtual conferencing room peers can join and leave at any time. This room is based on a Publish/Subscribe pattern. Each peer can publish his/her own live audio/video/data feeds: this feed becomes an available stream in the room the other participants can attach to. This means that this plugin allows the realization of several different scenarios, ranging from a simple webinar (one speaker, several listeners) to a fully meshed video conference (each peer sending and receiving to and from all the others).

UV4L natively implements the underlying signaling protocol required to interact with a given videoroom hosted by a Janus Gateway and provides two alternative interfaces to do this via HTTP(S).

One is “action-based”, meaning that you essentially invoke a GET request towards the UV4L Streaming Server specifying, in the parameters of the request, whether you want to start a new session or stop the one in progress. Other parameters indicate the gateway URL, the room number, the username to be shown to others in the room, and some other optional things such as whether you want to be a publisher only, a subscriber or both. For more detailed informations with an example, please read this.

The second interface is based on ad-hoc RESTful API. It gives a more fine-grained control over the whole session and can be used to develop more sophisticated and interactive web applications. The documentation can be found here.

Note that the two interfaces described above are mutually exclusive, thus they cannot be used at the same time to control the same session.