h1. Kurento HTML5 API

h2. Introduction

The Kurento HTML5 API is composed by three different classes:

* *KwsWebRtcContent*: do a connection with a WebRTC endpoint server allowing a bi-directional communication
* *KwsContentPlayer*: connect to a HTTP streaming server only allowing a uni-directional playing communication
* *KwsContentUploader*: do a uni-directional connection to a HTTP streaming server to upload a media file

This classes compose the Kurento Web SDK Content API (*kwsContentApi*) and will try to connect automatically to the content server, start the event-polling mechanism and also fill the local and remote video tags if they are defined.


h2. Class methods

This are the methods applied to all of the kwsContentApi classes if other thing is not specified.

* *Constructor*: create a new instance of the class, and try to connect automatically to the content server.
>
> *Parameters*
>
> * *url*: URL of the JsonRPC endpoint on the content server whom we want this instance to connect.
> * *options*: optional parameters for the constructor, stored as an object. If this param or any of its attributes is ommited, their default values will be used instead. In this object we can define how the connection streams should be both for audio and video streams, being the only forbidden combination to don't send nor receive nothing, or using invalid values to set them. This will be notified to the user raising a RangeError exception. For *KwsContentPlayer* and *KwsContentUploader*, values regarding to send or receive streams respectively will be ignored.
>> * *audio*: audio stream mode (*inactive*, *sendonly*, *recvonly* or *sendrecv*). Default is *sendrecv*.
>> * *video*: video stream mode (*inactive*, *sendonly*, *recvonly* or *sendrecv*). Default is *sendrecv*.
>> * *localVideoTag*: id of the video tag intended for the local video stream, so it will be initialized automatically. By default is not defined.
>> * *remoteVideoTag*: id of the video tag intended for the remote video stream, so it will be initialized automatically. In the future, it will be allowed to use also an audio tag if it was requested an audio only stream without video. By default if not defined only the 'remotestream' event will be effective to fetch the remote stream.
>> * *iceServers*: array of objects to initialize the STUN/TURN and ICE servers with the same structure as an Array of WebRTC RTCIceServer objects. This only it's meaningful for *WebRtcContent* constructor. By default it uses Google public STUN server.
>
> *Expected behaviour*
>
> # When the kwsContentApi instance object is created, it send automatically a *start* request to the server
> # The content server send back the response message
> # The client instance dispatch a *start* event. In case the session was rejected, a *terminate* event is dispatched with a message notifying to the user about it. In case there was an error connecting to the server, an *error* event is dispatched instead.

* *execute*: execute a command on the server. This method will not end the session in any case.
>
> *Parameters*
>
> * *type*: command to execute on the server.
> * *data*: parameters needed by this command, being its format dependent of the command to be executed.
> * *callback*: function called after the remote execution is done. Its parameters are:
>> * *error*: error happened while doing the remote execution.
>> * *result*: result of the remote execution, if any.
>
> *Expected behaviour*
>
> # When calling *execute* method, an *execute* message is send to the server
> # The content server send back the response message
> # In response it can get an *error* on the server execution or the execution *result*, both of them given to the callback function.

* *terminate*: clearly terminate the connection with the server
>
> *Parameters*
>
> Terminate method doesn't need parameters.
>
> *Expected behaviour*
>
> # When calling *terminate* method, a *terminate* notification will be send to the server, without waiting for a response.
> # The client instance dispatch a *terminate* event with a message notifying that the client was the one that ended the session.


h2. Events

The kwsContentApi classes inherit from the Node.js EventEmitter class, and so they follow their event mechanism oriented to functions, similar to how jQuery does.

* *start*: connection was successfuly stablished. This is dispatched after receiving a successful message for a *start* request to the WebRTC endpoint or streaming server.
>
> <pre>
(no parameters)
</pre>

* *localstream*: the requested local stream is available. The dispatched event has a *stream* attribute with a MediaStream object for the local video stream, and an *url* attribute with the local video blob URI. Also, if *localVideoTag* attribute was defined on the options object on the constructor, this stream will be set as the source of the video tag defined by that id. Currently this event is only dispatched by the KwsWebRtcContent class.
>
> <pre>
<code class="Javascript">
data = {
  stream: stream,
  url: url
}
</code>
</pre>

* *remotestream*: the requested remote stream is available. The dispatched event has a *stream* attribute with the remote video stream as a MediaStream object, and an *url* attribute with the URI to the stream. Also, if *remoteVideoTag* was defined on the constructor, this stream will be set as the source of the video tag defined by that id.
>
> <pre>
<code class="Javascript">
data = {
  stream: stream,
  url: url
}
</code>
</pre>

* *mediaevent*: a new media event was send by the WebRTC server endpoint. This dispatched event has a *data* attribute and its meaning is particular to the *MediaEvent*s dispatched by each pipeline being processed, so you should refer to the documentation of the pipeline you are using or to the documentation of its *MediaMixers*s or *MediaElement*s.
>
> <pre>
<code class="Javascript">
data = Application-dependent-content
</code>
</pre>

* *terminate*: connection was finished without errors, being the termination requested by us or by the WebRTC server endpoint. This is indicated by the *code* and *message* fields of the event.
>
> <pre>
<code class="Javascript">
reason = {
  code: 1,
  message: "Reason about who terminated the connection"
}
</code>
</pre>

* *error*: a communications fatal error has occurred (service unavailable on polling or executing commands after several tries, for example). When happening this, the connection is also being clossed automatically.
>
> <pre>
<code class="Javascript">
error = {
  type: "error",
  code: -1,
  message: "An error description"
}
</code>
</pre>


h2. How to use it

The Kurento HTML5 API is designed with simplicity in mind, in a way of just create an instance of one of the kwsContentApi classes, set the event callbacks, and you are ready.

The code is compatible both with Node.js and browser. In Node.js, the kwsContentApi classes are directly available just by doing a require() on the library, while on the browser after importing the browser specific release with a script tag, they are available on the *kwsContentApi* global namespace.

First of all, you need to define the URL of the content server JsonRPC endpoint, and if you need them, the optional parameters of the IDs for the local and the remote video tags:

<pre>
<code class="Javascript">
var uri = "http://www.example.com/jsonrpc";

var options =
{
  localVideoTag:  'localVideo',
  remoteVideoTag: 'remoteVideo'
};
</code>
</pre>

Later, create an instance of one the kwsContentApi classes, so we can connect with the content server. If the values given on the options object were not correct, the constructor will raise an exception so you can fix them:

<pre>
<code class="Javascript">
var conn = new KwsWebRtcContent(uri, options);
</code>
</pre>

After that, you can set the event callbacks directly on the just created instance.

<pre>
<code class="Javascript">
// Start and terminate events
conn.on('start', function()
{
  console.log("Connection started");
});
conn.on('terminate', function(reason)
{
  console.log("Connection terminated due to "+reason.message);
});

// LocalStream and remoteStream events
conn.on('localstream', function(data)
{
  console.info("LocalStream set to "+data.url);
});
conn.on('remotestream', function(data)
{
  console.info("RemoteStream set to "+data.url);
});

// Media event
conn.on('mediaevent', function(data)
{
  console.info("MediaEvent: "+JSON.stringify(data));
});

// Error
conn.on('error', function(error)
{
  console.error(error.message);
});
</code>
</pre>

From this point you'll not need to worry more about the session with the content server, the kwsContentApi classes will do it for you. If you want to send a command to the content server, you can do it with the *execute* method. This will require that you know previously what are the available commands that you can send to the pipeline available on the connection you are currently connected and what are their parameters.

<pre>
<code class="Javascript">
conn.execute("applyEffect", "sepia", function(error, result)
{
  if(error)
    console.error(error)
  else
    console.info("Gone back in time 60 years... Result = "+result);
});
</code>
</pre>

If you want to end the session from the client side, you only need to call to the *terminate* method on the connection instance:

<pre>
<code class="Javascript">
conn.terminate();
</code>
</pre>

You can find a full working example on the "example folder":https://github.com/Kurento/kws-content-api/tree/develop/example of the "Kurento Web SDK content API":https://github.com/Kurento/kws-content-api source code repository.


h2. Messages protocol

The protocol to comunicate with the WebRTC server endpoint is based on "JSON-RPC 2.0 over HTTP":http://www.simple-is-better.org/json-rpc/jsonrpc20-over-http.html. If not otherwise specified, the messages apply for all the kwsContentApi classes.

* *start*: does the initial connection request to the WebRTC or Kurento media server endpoint.
> *params*:
> An object with a 'constraints' attribute being an object defining the audio and video mode (none, send, recv or sendrecv).
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "method": "start",
  "params":
  {
    "constraints":
    {
      "audio": "sendrecv",
      "video": "sendrecv"
    }
  },
  "id": 1
}
</code>
</pre>

> For *KwsWebRtcContent*, it also includes a *sdp* attribute containing the offer SDP.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "method": "start",
  "params":
  {
    "constraints":
    {
      "audio": "sendrecv",
      "video": "sendrecv"
    },
    "sdp": "veryLargeOfferSDP"
  },
  "id": 1
}
</code>
</pre>

> *result*:
> An object with a *sessionId* attribute with the ID generated by the server for this client session, and a *url* attribute containing the URL of the video and/or audio streaming if it was requested. For *KwsContentUploader*, it's the URL of the endpoint on the Media Server where you can upload the media file.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "result":
  {
    "sessionId": 1234,
    "url": "http://example.com/stream-veryLongId"
  },
  "id": 1
}
</code>
</pre>

> For *KwsWebRtcContent*, the *url* attribute is substituted for a *sdp* attribute containing the answer SDP.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "result":
  {
    "sessionId": 1234,
    "sdp": "veryLargeOfferSDP"
  },
  "id": 1
}
</code>
</pre>

> In case the connection is rejected, it's returned an object with a *rejected* attribute containing an object with a *code* and a *message* attributes with the reason why the session was not accepted, and no *sessionId* is defined.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "result":
  {
    "rejected":
    {
      "code": 1,
      "message": "Unauthorized user"
    }
  },
  "id": 1
}
</code>
</pre>

* *poll*: request a list with the latest *MediaEvent*s.
> *params*: an object with only a 'sessionId' attribute containing the ID for this session.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "method": "poll",
  "params":
  {
    "sessionId": 1234
  },
  "id": 1
}
</code>
</pre>

> *result*: an object with a *contentEvents* attribute containing an array with the latest *MediaEvent*s, and a *controlEvents* attribute containing an array with the latest control events for this session, or an empty object if none was generated. Each control event can has an optional *data* attribute containing an object with a *code* and a *message* attributes.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "result":
  {
    "contentEvents":
    [
      {"type": "event1"},
      {"type": "event2"}
    ],
    "controlEvents":
    [
      {
        "type": "event1",
        "data":
        {
          "code": 1,
          "message": "license plate"
        }
      },
      {"type": "event2"}
    ]
  },
  "id": 1
}
</code>
</pre>

* *execute*: exec a command on the server.
> *params*: an object with a *sessionId* attribute containing the ID for this session, and a *command* object with a *type* string attribute for the command type and a *data* attribute for the command specific parameters.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "method": "execute",
  "params":
  {
    "sessionId": 1234,
    "command":
    {
      "type": "commandType",
      "data": ["the", "user", "defined", "command", "parameters"]
    }
  },
  "id": 1
}
</code>
</pre>

> *result*: an object with only a *commandResult* attribute containing a string with the command results.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "result":
  {
    "commandResult": "Everything has gone allright"
  },
  "id": 1
}
</code>
</pre>

* *terminate*: request explicitly to the WebRTC media server to close the connection.
> *params*: an object with only a *sessionId* attribute containing the ID for this session.
>
> <pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "method": "terminate",
  "params":
  {
    "sessionId": 1234,
    "reason":
    {
      "code": 1,
      "message": "User ended session"
    }
  }
}
</code>
</pre>

*Errors*

In case *poll* or *request* request failed but the connection with the server was successful, an error response will be given with a HTTP error 2XX or maybe also 4XX or 5XX (dependent of the configuration of the server, but desirable the latest ones as specified in the "JSON-RPC 2.0 over HTTP":http://www.simple-is-better.org/json-rpc/jsonrpc20-over-http.html specification), it will be returned an object with a *code* attribute with an integer specific for each error, a *message* attribute with a short string explaining the reason of the error on the server, and an optional *data* attribute with detailed info of the error and without a defined structure (could be a string, an object, a traceback...).

<pre>
<code class="JSON">
{
  "jsonrpc": "2.0",
  "error":
  {
    "code": 1,
    "message": "an error has occurred",
    "data": "errorData"
  },
  "id": 1
}
</code>
</pre>


h2. Development

The project is developed to be compatible with "Node.js":http://nodejs.org and web browsers using the same source code base. This means you need to do some extra steps to prepare the environment and upload the code if you modify it.


h3. Download the project dependencies

The project dependencies are downloaded from external Node.js modules located at the "NPM registry":https://npmjs.org. They're already configured on the "package.json":https://npmjs.org/doc/json.html file so they are fetch automatically executing NPM from the command line:

<pre>
<code class="bash">
npm install
</code>
</pre>

This will download both the project dependencies and the developer dependencies (like unit testing frameworks or code processors) at the "node_modules":https://npmjs.org/doc/files/npm-folders.html#Node-Modules folder, so it will be needed to be executed each time a new project dependency is added. This step will not be required by external third party Node.js projects when using this one as a dependency (they will have already configured their own package.json file and download the project and its dependencies automaticaly) and will be needed to be executed only one time on download/install time. If any of the project dependencies has been updated on their origin repository, the downloaded local copy can be updated from the command line using

<pre>
<code class="bash">
npm update
</code>
</pre>

This will re-check all the project dependencies and download and install the new updated ones.


h3. Generate the browser version

The source code needs to be adapted to the browser environment. The project is already configured to do it automatically by "Browserify":http://browserify.org using a "Grunt":http://gruntjs.com task, and it's also configured to download them automatically as developer dependencies of the project, so it can be executed directly from the locally downloaded Node.js modules folder from the command line with

<pre>
<code class="bash">
node_modules/.bin/grunt
</code>
</pre>

This will generate browser-ready Javascript library files on the */dist* folder ready to be referenced on a HTML script tag, one of them standalone (not needing third party libraries) and other needing a externally provided _require()_ function (useful when more than one library is being generated by Browserify, so having it in common help to use less bandwidth), and also it's generating their minimified versions. To generate a copy ready to be integrated on a "maven":http://maven.apache.org project, you can execute instead

<pre>
<code class="bash">
node_modules/.bin/grunt maven
</code>
</pre>

This will generate a copy of the files at _src/main/resources/js_ ready to be used on the creation of a JAR file.