Warning

Kurento is a low-level platform to create WebRTC applications from scratch. You will be responsible of managing STUN/TURN servers, networking, scalability, etc. If you are new to WebRTC, we recommend using OpenVidu instead.

Acknowledgements

Kurento team gives credit to Signicat for their support that allows us to make it possible continue evolving and developing Kurento Media Server Project.

Signicat logo


JavaScript - Hello world

Warning

Bower dependencies are not yet upgraded for Kurento 7.0.0.

Kurento tutorials that use pure browser JavaScript need to be rewritten to drop the deprecated Bower service and instead use a web resource packer. This has not been done, so these tutorials won’t be able to download the dependencies they need to work. PRs would be appreciated!

This web application has been designed to introduce the principles of programming with Kurento for JavaScript developers. It consists of a WebRTC video communication in mirror (loopback). This tutorial assumes you have basic knowledge of JavaScript, HTML and WebRTC. We also recommend reading Introduction to Kurento before starting this tutorial.

Note

Web browsers require using HTTPS to enable WebRTC, so the web server must use SSL and a certificate file. For instructions, check Configure JavaScript applications to use HTTPS.

For convenience, this tutorial already provides dummy self-signed certificates (which will cause a security warning in the browser).

Running this example

First of all, install Kurento Media Server: Installation Guide. Start the media server and leave it running in the background.

Install Node.js, Bower, and a web server in your system:

curl -sSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install -g bower
sudo npm install -g http-server

Here, we suggest using the simple Node.js http-server, but you could use any other web server.

You also need the source code of this tutorial. Clone it from GitHub, then start the web server:

git clone https://github.com/Kurento/kurento.git
cd kurento/tutorials/javascript-browser/hello-world/
git checkout 7.1.0
bower install
http-server -p 8443 --ssl --cert keys/server.crt --key keys/server.key

When your web server is up and running, use a WebRTC compatible browser (Firefox, Chrome) to open the tutorial page:

  • If KMS is running in your local machine:

    https://localhost:8443/
    
  • If KMS is running in a remote machine:

    https://localhost:8443/index.html?ws_uri=ws://{KMS_HOST}:8888/kurento
    

Note

By default, this tutorial works out of the box by using non-secure WebSocket (ws://) to establish a client connection between the browser and KMS. This only works for localhost. It will fail if the web server is remote.

If you want to run this tutorial from a remote web server, then you have to do 3 things:

  1. Configure Secure WebSocket in KMS. For instructions, check Signaling Plane security (WebSocket).

  2. In index.js, change the ws_uri to use Secure WebSocket (wss:// instead of ws://) and the correct KMS port (TCP 8433 instead of TCP 8888).

  3. As explained in the link from step 1, if you configured KMS to use Secure WebSocket with a self-signed certificate you now have to browse to https://{KMS_HOST}:8433/kurento and click to accept the untrusted certificate.

Understanding this example

Kurento provides developers a Kurento JavaScript Client to control Kurento Media Server. This client library can be used in any kind of JavaScript application including desktop and mobile browsers.

This hello world demo is one of the simplest web applications you can create with Kurento. The following picture shows a screenshot of this demo running:

Kurento Hello World Screenshot: WebRTC in loopback

Kurento Hello World Screenshot: WebRTC in loopback

The interface of the application (an HTML web page) is composed by two HTML5 video tags: one showing the local stream (as captured by the device webcam) and the other showing the remote stream sent by the media server back to the client.

The logic of the application is quite simple: the local stream is sent to the Kurento Media Server, which sends it back to the client without modifications. To implement this behavior, we need to create a Media Pipeline composed by a single Media Element, i.e. a WebRtcEndpoint, which holds the capability of exchanging full-duplex (bidirectional) WebRTC media flows. This media element is connected to itself,, so that the media it receives (from browser) is send back (to browser). This media pipeline is illustrated in the following picture:

Kurento Hello World Media Pipeline in context

Kurento Hello World Media Pipeline in context

This is a web application, and therefore it follows a client-server architecture. Nevertheless, due to the fact that we are using the Kurento JavaScript client, there is not need to use an application server since all the application logic is held by the browser. The Kurento JavaScript Client is used directly to control Kurento Media Server by means of a WebSocket bidirectional connection:

Complete sequence diagram of Kurento Hello World (WebRTC in loopbak) demo

Complete sequence diagram of Kurento Hello World (WebRTC in loopbak) demo

The following sections analyze in deep the client-side (JavaScript) code of this application, the dependencies, and how to run the demo. The complete source code can be found in GitHub.

JavaScript Logic

The Kurento hello-world demo follows a Single Page Application architecture (SPA). The interface is the following HTML page: index.html. This web page links two Kurento JavaScript libraries:

  • kurento-client.js : Implementation of the Kurento JavaScript Client.

  • kurento-utils.js : Kurento utility library aimed to simplify the WebRTC management in the browser.

In addition, these two JavaScript libraries are also required:

  • Bootstrap : Web framework for developing responsive web sites.

  • jquery.js : Cross-platform JavaScript library designed to simplify the client-side scripting of HTML.

  • adapter.js : WebRTC JavaScript utility library maintained by Google that abstracts away browser differences.

  • ekko-lightbox : Module for Bootstrap to open modal images, videos, and galleries.

  • demo-console : Custom JavaScript console.

The specific logic of the Hello World JavaScript demo is coded in the following JavaScript file: index.js. In this file, there is a function which is called when the green button labeled as Start in the GUI is clicked.

var startButton = document.getElementById("start");

startButton.addEventListener("click", function() {
   var options = {
     localVideo: videoInput,
     remoteVideo: videoOutput
   };

   webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function(error) {
      if(error) return onError(error)
      this.generateOffer(onOffer)
   });

   [...]
}

The function WebRtcPeer.WebRtcPeerSendrecv abstracts the WebRTC internal details (i.e. PeerConnection and getUserStream) and makes possible to start a full-duplex WebRTC communication, using the HTML video tag with id videoInput to show the video camera (local stream) and the video tag videoOutput to show the remote stream provided by the Kurento Media Server.

Inside this function, a call to generateOffer is performed. This function accepts a callback in which the SDP offer is received. In this callback we create an instance of the KurentoClient class that will manage communications with the Kurento Media Server. So, we need to provide the URI of its WebSocket endpoint. In this example, we assume it’s listening in port TCP 8888 at the same host than the HTTP serving the application.

[...]

var args = getopts(location.search,
{
  default:
  {
    ws_uri: 'ws://' + location.hostname + ':8888/kurento',
    ice_servers: undefined
  }
});

[...]

kurentoClient(args.ws_uri, function(error, client){
  [...]
};

Once we have an instance of kurentoClient, we need to create a Media Pipeline, as follows:

client.create("MediaPipeline", function(error, _pipeline){
   [...]
});

If everything works correctly, we will have an instance of a media pipeline (variable _pipeline in this example). With it, we are able to create Media Elements. In this example we just need a single WebRtcEndpoint.

In WebRTC, SDP is used for negotiating media exchanges between applications. Such negotiation happens based on the SDP offer and answer exchange mechanism by gathering the ICE candidates as follows:

pipeline = _pipeline;

pipeline.create("WebRtcEndpoint", function(error, webRtc){
   if(error) return onError(error);

   setIceCandidateCallbacks(webRtcPeer, webRtc, onError)

   webRtc.processOffer(sdpOffer, function(error, sdpAnswer){
     if(error) return onError(error);

     webRtcPeer.processAnswer(sdpAnswer, onError);
   });
   webRtc.gatherCandidates(onError);

   [...]
});

Finally, the WebRtcEndpoint is connected to itself (i.e., in loopback):

webRtc.connect(webRtc, function(error){
   if(error) return onError(error);

   console.log("Loopback established");
});

Note

The TURN and STUN servers to be used can be configured simple adding the parameter ice_servers to the application URL, as follows:

https://localhost:8443/index.html?ice_servers=[{"urls":"stun:stun1.example.net"},{"urls":"stun:stun2.example.net"}]
https://localhost:8443/index.html?ice_servers=[{"urls":"turn:turn.example.org","username":"user","credential":"myPassword"}]

Dependencies

All dependencies of this demo can to be obtained using Bower. The list of these dependencies are defined in the bower.json file, as follows:

"dependencies": {
   "kurento-client": "7.1.0",
   "kurento-utils": "7.1.0"
}

To get these dependencies, just run the following shell command:

bower install

Note

You can find the latest version of Kurento JavaScript Client at Bower.