Sample-webrtc-web

Ask tech team
From QuickBlox Developers (API docs, code samples, SDK)
Jump to: navigation, search

Contents

Sources & Demo

Demo — https://quickblox.github.io/quickblox-javascript-sdk/samples/webrtc

Download ZIP — https://github.com/QuickBlox/quickblox-javascript-sdk/archive/gh-pages.zip

Overview

The WebRTC VideoChat code sample allows you easily add video calling features into your Web app. Enable a video call function similar to Skype using this code sample as a basis.

It is built on top of the WebRTC technology.


NewInterfaceOfWebRTCSample.png


Browsers support of WebRTC

Desktop:

  • Chrome (latest)
  • Firefox (latest)
  • Opera (latest)

Mobile:

  • Android Browser (latest)
  • Opera Mobile (latest)
  • Chrome for Android (latest)
  • Firefox for Android (latest)

Unfortunately, these features are unsupported in IE and Safari, and iOS mobile browsers.
You can find more info here - http://iswebrtcreadyyet.com/.

Note: Opera mini for Android, which has minimal functionality, does not work with this technology either.


Prepare your application for Javascript SDK

Preparation includes the following steps:

  • Create QuickBlox account
  • Register an application in Dashboard
  • Integrate QuickBlox SDK into application

Register a QuickBlox account

https://quickblox.com/signup/

Create application in the Admin panel

https://admin.quickblox.com/apps/new

In addition, there is helpful 5 minute guide.

Connect the SDK and configure

http://quickblox.com/developers/Javascript#Connect_JavaScript_SDK_to_Web_and_Node.js_applications


Integrate video calling to your application

Transition guide from 1.7 to 2.0 version

This migration guide will provide guidance to upgrade your existing application to SDK version 2.0:

  1. Now methods as getUserMedia, attachMediaStream, detachMediaStream, call, accept, reject, stop, update, mute, unmute, snapshot are encapsulated in session object. You can obtain it via var session = QB.webrtc.createNewSession(calleesIds, typeOfCall);
  2. Added a callback to close a session - onSessionCloseListener.
  3. Renamed the callback onSessionStateChangedListener to onSessionConnectionStateChangedListener

More detailed info on these updates find in guide below.


Connect to chat

You have to connect to the Chat because the QuickBlox Video calling SDK exchanges signaling messages over XMPP protocol via own signaling mechanism.

QB.chat.connect({userId: 4355, password: "geremy67df"}, function(err, roster) {
  if(err){
 
  }else{
 
  }
});

More detailed info about connection to Chat you can find on Chat code sample page.


Create video session

In order to use Video calling API you have to create a session object - choose your opponents with whom you would like to have a video chat and a type of session (VIDEO or AUDIO):

var calleesIds = [56, 76, 34]; // User's ids 
var sessionType = QB.webrtc.CallType.VIDEO; // AUDIO is also possible
 
var session = QB.webrtc.createNewSession(calleesIds, sessionType);


Get local Media Stream

Access local media stream

In order to have a video chat session you have to get access to the user's devices (webcam / microphone):

var mediaParams = {
  audio: true,
  video: true,
  options: {
    muted: true,
    mirror: true
  },
  elemId: 'localVideo'
};
 
session.getUserMedia(mediaParams, function(err, stream) {
  if (err){
 
  }else{
 
  }
});


This method lets the browser asks the user for permission to use devices. The appearance of the popup varies between browsers.

Chrome

Firefox

Opera


You should allow this dialog to access the stream. Otherwise, the browser can't obtain access and will throw an error for the getUserMedia callback function.


Parameters

You can use following parameters with getUserMedia

Param Required Type Value Example Description
audio Yes* Boolean true / false audio stream from microphone
video Yes* Boolean true / false video stream from webcam
elemId Optional String 'localVideo' ID of audio/video DOM element to attach a video stream to.
options[muted] Optional** Boolean true / false disable local audio stream for user

Note: is useful to reduce echo cancellation
and noises in the audio/video chat

options[mirror] Optional** Boolean true / false mirrored rotate the video stream

* audio or/and video are required
** the options object will work only if elemId exists


Localhost and the secure HTTP protocol

The request for webrtc permissions is a security measure in browsers. Note also that getUserMedia() must be used solely when on the server, not the local file system, otherwise media streaming will not work.

Also you have to use HTTPS protocol to make it works - Chrome will block it on HTTP.


Code snippets

Get only audio stream from microphone

session.getUserMedia({audio: true}, function(err, stream) {
  // callback
});

Get only video stream from webcam

session.getUserMedia({video: true}, function(err, stream) {
  // callback
});

Get both streams

session.getUserMedia({audio: true, video: true}, function(err, stream) {
  // callback
});

Get stream and automatically attach it to video element on the page

session.getUserMedia({audio: true, video: true, elemId: 'localVideo'}, function(err, stream) {
  // callback
});

Get stream and automatically attach, mute and mirrored rotate it

var options = {
  muted: true,
  mirror: true
};
session.getUserMedia({audio: true, video: true, elemId: 'localVideo', options: options}, function(err, stream) {
  // callback
});


Advanced settings

It's also possible to set custom video resolution using getUserMedia constraints.

Example of HD camera resolution constraints, i.e. minWidth: 1280, minHeight: 720:

var contraints = {       
      audio: true,
      video: {
            optional: {
              minWidth: 1280,
              maxWidth: 1280,
              minHeight: 720,
              maxHeight: 720
            }
      }
};
 
session.getUserMedia(contraints, function(err, stream) {
  // callback
});

Here is a good code sample from WebRTC team how to work with getUserMedia constraints: https://webrtc.github.io/samples/src/content/getusermedia/resolution/

Attach stream on the page

You can also attach your local media stream to HTML video element lately if you don't pass the elemId key in parameters to getUserMedia.

To do this use the following steps:

  • create any audio / video element in html
  • call session.attachMediaStream(id, stream, options)


Param Required Type Value Example Description
id Yes String 'localVideo' ID of audio/video DOM element
stream Yes Object [stream from browser] Media Stream Object received via getUserMedia
options[muted] Optional Boolean true / false disable the audio stream for DOM element
options[mirror] Optional Boolean true / false mirrored rotate the video stream


This method attaches Media Stream Object to your DOM element and auto plays it

session.attachMediaStream('videoElement', stream);

The same method is used for remote stream, received from your opponents.


Note on Debugging

If you try to download and open sample in your browser, you will likely run into Cross-Origin Resource Sharing (CORS) errors since the browser will block your requests to use video and microphone features.

To test a sample locally we recommend you setup a simple server using Python.

To do this, open your terminal and change directories into your sample and depending on your version of Python, run one of the following commands:

# Python 2
python -m SimpleHTTPServer <portNo>
 
# Python 3
python -m http.server <portNo>

For example,

python -m SimpleHTTPServer 8002

Now you can go to http://localhost:8002/index.html to debug your app.


Make a call

Make a call with this method:

var extension = {};
session.call(extension, function(error) {
 
});

The extension is used to pass any extra parameters in the request to your opponents.


After this call the opponents will get an incoming call request in onCallListener callback:

QB.webrtc.onCallListener = function(session, extension) {
 
};

If the opponent is offline at the moment then onUserNotAnswerListener callback will be fired on caller's side:

QB.webrtc.onUserNotAnswerListener = function(session, userId) {
 
};

Settings & configuration

Session settings

There are a set of pre defined Video calling settings that you can update for your purpose:

var CONFIG = {
  webrtc: {
    answerTimeInterval: 60, // Max answer time after that the 'QB.webrtc.onUserNotAnswerListener' callback will be fired.
    dialingTimeInterval: 5,  // The interval between call requests produced by session.call(extension)
    disconnectTimeInterval: 30 // If an opponent lost a connection then after this time the caller will now about it via 'QB.webrtc.onSessionConnectionStateChangedListener' callback.
    statsReportTimeInterval: false // Allows access to the statistical information about a peer connection. You can set amount of seconds you can get statistic information after.
  }
  ...
};
 
QB.init(3477, 'ChRnwEJ3WzxH9O4', 'AS546kpUQ2tfbvv', CONFIG);


We recommend you to create config.js configuration file in your js-application and insert your custom video calling settings into it.

ICE servers

Also you can customise a list of ICE servers (via iceServers key).

We use 3 TURN servers: in North Virginia turn.quickblox.com, in Asia turnsingapore.quickblox.com and in Europe turnireland.quickblox.com.

How does WebRTC select which TURN server to use if multiple options are given? During the connectivity checking phase, WebRTC will choose the TURN relay with the lowest round-trip time. Thus, setting multiple TURN servers allows your application to scale-up in terms of bandwidth and number of users.

Here is a list with default settings that we use, you can customise all of them or only some particular:

var CONFIG = {
  webrtc: {
    iceServers: [
      {
        'url': 'stun:stun.l.google.com:19302'
      },
      {
        'url': 'stun:turn.quickblox.com',
        'username': 'quickblox',
        'credential': 'baccb97ba2d92d71e26eb9886da5f1e0'
      },
      {
        'url': 'turn:turn.quickblox.com:3478?transport=udp',
        'username': 'quickblox',
        'credential': 'baccb97ba2d92d71e26eb9886da5f1e0'
      },
      {
        'url': 'turn:turn.quickblox.com:3478?transport=tcp',
        'username': 'quickblox',
        'credential': 'baccb97ba2d92d71e26eb9886da5f1e0'
      },
    ]
  }
  ...
};
QB.init(3477, 'ChRnwEJ3WzxH9O4', 'AS546kpUQ2tfbvv', CONFIG);

Test your settings

Google has another great analysis tool – test.webrtc.org

You open the settings, insert your own STUN and TURN server configuration – and start the test.

It will then check the system and network connections to give you a nice view of what the browser is experiencing – something you can later use to understand the environment you operate in.

Accept a call

Use accept method to accept the incoming call:

var extension = {};
session.accept(extension);


After this call the opponent will get a confirmation in onAcceptCallListener callback:

QB.webrtc.onAcceptCallListener = function(session, userId, extension) {
 
};

Next, caller will get also remote media stream from the opponent in onRemoteStreamListener function

QB.webrtc.onRemoteStreamListener = function(session, userID, remoteStream) {
  // attach the remote stream to DOM element
  session.attachMediaStream('remoteVideo', remoteStream);
};

From this point you have a working ready to go real-time videochat!


Reject a call

Use the reject method to decline an incoming call:

var extension = {};
session.reject(extension);


After this call the opponent will get a reject signal in onRejectCallListener callback:

QB.webrtc.onRejectCallListener = function(session, userId, extension) {
 
};


End a call

Either participant can end the call anytime with the following method:

var extension = {};
session.stop(extension);


After this call the opponent will get a stop signal in onStopCallListener callback:

QB.webrtc.onStopCallListener = function(session, userId, extension) {
 
};

Track session state

There is a callback function to track the session state:

QB.webrtc.onSessionConnectionStateChangedListener = function(session, userID, connectionState) {
 
};

The possible values of connectionState are those of an enum of type QB.webrtc.SessionConnectionState:

  • QB.webrtc.SessionConnectionState.UNDEFINED
  • QB.webrtc.SessionConnectionState.CONNECTING
  • QB.webrtc.SessionConnectionState.CONNECTED
  • QB.webrtc.SessionConnectionState.FAILED
  • QB.webrtc.SessionConnectionState.DISCONNECTED
  • QB.webrtc.SessionConnectionState.CLOSED
  • QB.webrtc.SessionConnectionState.COMPLETED


Notify opponents about any updates

Sometimes you make changes on the client side (e.g. changing the camera feed orientation from portrait to landscape) that need to be fed to the opponents and updated. For this, you can use the update function to send instructions to the opponents on how to update the UI.

var extension = {
  "userInfo": {
    "param1": "value1",
    "param2": "value2"
  }
}
session.update(extension);


After this call the opponent will get a signal in onUpdateCallListener callback:

QB.webrtc.onUpdateCallListener = function(session, userId, extension) {
 
};


Mute the stream

You can disable some of your local media stream at any time with mute(type) method:

session.mute('audio');
 
session.mute('video');

Naturally, you can unmute the stream with the following methods:

session.unmute('audio');
 
session.unmute('video');

Stats reporting

You are able to observe stats provided by WebRTC.

To start collecting report information do the following on config:

var CONFIG = {
  webrtc: {
    ...
    statsReportTimeInterval: true
  }
  ...
};

And listen for stats reports in callback:

QB.webrtc.onCallStatsReport = function onCallStatsReport(session, userId, stats, error) {
 
}

More info on stats keys is here

Recording a stream

We recommend using qbMediaRecorderJS to record streams, download the recorded files and checking available mimeTypes in your browser. Check out docs / sample of qbMediaRecorderJS.

To test the sample recommend using several audio/video sources. We welcome your suggestions for the development of the tool.


Deprecated feature (QB.Recorder).

Support: Firefox 47, Chrome 49, Opera 40.

You can record a stream or a few streams by using QB.Recorder.
Now QB.Recorder is in beta version, so be careful with this functionality.

var options = {
    callbacks: {
        onStartRecording: function startRecord() {  /* ... */  },
        onStopRecording: function stopRecord(blob) { /* ... */ },
        onErrorRecording: function errorRecord(error) { /* ... */ },
        onPauseRecording: function pauseRecord() { /* ... */ },
        onResumeRecording: function resimeRecord() { /* ... */ }
  }
}
 
var recorder = new QB.Recorder(stream, options);
recorder.record();
// ...
recorder.pause();
// ...
recorder.resume();
// ...
recorder.stop();

See more functions in our WebRTC sample. The recorder is available in a peer-to-peer call.

Known issues:

  • We recommend that you limit the duration of recording to 3 minutes currently. The longer duration can lead to the crash of the browser's tab;
  • Firefox has an issue when we are recording a remote stream. Got 'GenericError'. We are not recommended to use QB.Recorder in Firefox because it has some unexpected errors when MediaStream was ended, for example it crashes a page.