QuickBlox Documentation

QuickBlox provides powerful Chat API and SDK to add real-time messaging and video calls to your web and mobile apps. Learn how to integrate QuickBlox across multiple platforms and devices. Check out our detailed guides to make integration easy and fast.

Video Calling

Learn how to add peer-to-peer video calls to your app.

QuickBlox Video Calling API is built on top of WebRTC. It allows adding real-time video communication features into your app similar to Skype using API easily. The communication is happening between peers representing camera devices. There are two peer types:

  • Local peer is a device running the app right now.
  • Remote peer is an opponent device.

Establishing real-time video communication between two peers involves 3 phases:

  1. Signaling. At this phase, the peers’ local IPs and ports where they can be reached (ICE candidates) are exchanged as well their media capabilities and call session control messages.
  2. Discovery. At this phase, the public IPs and ports at which endpoints can be reached are discovered by STUN/TURN server.
  3. Establishing a connection. At this phase, the data are sent directly to each party of the communication process.


Pay attention

In order to start using Video Calling Module, you need to connect to QuickBlox Chat first. The signaling in the QuickBox WebRTC module is implemented over the XMPP protocol using QuickBlox Chat Module. So QuickBlox Chat Module is used as a signaling transport for Video Calling API.



Please use this WebRTC Video Calling to make the Group Calls with 4 or fewer users. Because of Mesh architecture we use for multi-point where every participant sends and receives its media to all other participants, the current solution supports group calls with up to 4 people.

Access local media stream

In order to have a call session, you need to get the 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 ask the user for permission to use devices. You should allow this dialog to access the stream. Otherwise, the browser cannot obtain access and will throw an error for getUserMedia callback function.

For more information about possible audio/video constraints, here is a good code sample from WebRTC team on how to work with getUserMedia constraints.

Attach local media stream

You can also attach your local media stream to HTML video element, if you do not pass the elementId key in parameters to getUserMedia(). To do this, use the following method.

session.attachMediaStream('myVideoElementId', stream);

Initiate a call

In order to use Video Calling API, you need to create a session object. Choose your opponents with whom you will have a call and a type of call session (VIDEO or AUDIO).

var calleesIds = [56, 76, 34]; // Users' ids
var sessionType = QB.webrtc.CallType.VIDEO; // AUDIO is also possible
var additionalOptions = {};

var session = QB.webrtc.createNewSession(calleesIds, sessionType, null, additionalOptions);

Once the call session is created, you can start calling using call() method. The extension parameter is used to pass any extra parameters in the request to your opponents.

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

After this, your opponents will receive a callback call.

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

Or, if your opponents are offline or did not answer the call request, they receive the following callback call.

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

Accept a call

To accept a call request, call accept() method.

var extension = {};

After this, your opponents will get a confirmation in the following callback.

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

Also, both the caller and opponents will get a special callback with the remote stream.

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

From this point, you and your opponents can see each other.

Reject a call

To reject a call request, use reject() method.

var extension = {};

After this, the caller will get a confirmation in the following callback.

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

End a call

To end a call, use stop() method and pass sessionId parameter to tell SDK which call session to end.

var extension = {};

After this, the opponents will get a confirmation in the following callback.

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

Call changes

Sometimes, you make changes during an active call (e.g. applying some CSS filter to a video element) that needs to be fed to the opponents and updated. To allow for this, you can use update() method to send instructions to the opponents on how to update the UI.

var extension = {
  userInfo: {
    videoFilter: "sepica"

Your opponents will receive the following callback.

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

Event listener

To process events such as incoming call, call reject, hang up, etc. you need to set up the event listener. The event listener processes various events that happen with the call session or peer connection in your app.

Using the callbacks provided by the event delegate, you can implement and execute the event-related processing code. For example, the onAcceptCallListener callback is received when your call has been accepted by the user. This callback receives information about the call session, user ID who accepted the call, and additional key-value data about the user.

QuickBlox JavaScript SDK persistently interacts with the server via XMPP connection that works as a signaling transport for establishing a call between two or more peers. It receives the callbacks of the asynchronous events which happen with the call and peer connection. This allows you to track these events and build your own video calling features around them.

To track call session and peer connection events, you should use the event listener. The supported event callbacks for a call session and peer connection are listed in the table below.

MethodInvoked when
onCallListenerA new call session has been received.
onAcceptCallListenerA call has been accepted.
onRejectCallListenerA call has been rejected.
onStopCallListenerAn accepted call has been ended by the peer by pressing the hang-up button.
onUserNotAnswerListenerA user did not respond to your call within the dedicated time interval.
onSessionCloseListenerA call session has been closed.
onCallStatsReportAn updated stats report, which is called by timeout, has been received for the user ID.
onSessionConnectionStateChangedListenerA peer connection state has been changed. View Peer connection states section for more details.
onUpdateCallListenerCalled when updates to the active call are made.
onInvalidEventsListenerCalled when some operation cannot be performed (i.e. the accept() method is called on the closed call session).
onRemoteStreamListenerA user received a stream from the opponent.

The following code lists all supported event callbacks.

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

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

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

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

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

QB.webrtc.onInvalidEventsListener = function(eventName, session, userId, userInfo) {}

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

QB.webrtc.onRemoteStreamListener = function(session, userId, stream) { }

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

QB.webrtc.onSessionCloseListener = function(session) {}

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

Go to the Resources section to see a sequence diagram for a regular call workflow.

Call session states

The following table lists all supported call session states.

NEWA new call session has such a state.
ACTIVEA call session gets this state when you initiated or accepted the incoming call.
HUNGUPA call session gets this state when you hang up, before closing the call session.
REJECTEDA call session gets this state when you reject an incoming call before closing the call session.
CLOSEDA call session is closed.

Peer connection states

The following table lists all supported states of peer connection:

QB.webrtc.SessionConnectionState.CONNECTINGThe ICE agent has been given one or more remote candidates and is checking pairs of local and remote candidates against one another to try to find a compatible match, but has not yet found a pair which will allow the peer connection to be made.
QB.webrtc.SessionConnectionState.CONNECTEDA usable pairing of local and remote candidates has been found for all components of the connection, and the connection has been established.
QB.webrtc.SessionConnectionState.CLOSEDA peer connection was closed. But the call session can still be open because there can several peer connections in a single call session.
The ICE agent for this RTCPeerConnection has shut down and is no longer handling requests.
QB.webrtc.SessionConnectionState.FAILEDOne or more of the ICE transports on the connection is in the failed state. This can occur in different circumstances, for example, bad network, etc.
QB.webrtc.SessionConnectionState.COMPLETEDThe ICE agent has finished gathering candidates, has checked all pairs against one another, and has found a connection for all components.


A regular call workflow.

Updated 24 days ago

What's Next


Video Calling

Learn how to add peer-to-peer video calls to your app.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.