Skip to content

Video Conferencing

ConnectyCube Multiparty Video Conferencing API is built on top of WebRTC protocol and based on top of WebRTC SFU architecture.

Max people per Conference call is 12.

Video Conferencing is available starting from Advanced plan.

To get a difference between P2P calling and Conference calling please read our ConnectyCube Calling API comparison blog page.

Features supported

  • Video/Audio Conference with up to 12 people
  • Join-Rejoin video room functionality (like Skype)
  • Guest rooms
  • Mute/Unmute audio/video streams
  • Display bitrate
  • Switch video input device (camera)
  • Switch audio input device (microphone)

Preparations

Set up config

In order to start working with Multiparty Video Conferencing API you need to initialize a client:

const credentials = {
appId: ...,
authKey: "...",
authSecret: "..."
}
const MULTIPARTY_SERVER_ENDPOINT = 'wss://...:8989';
const appConfig = {
debug: { mode: 1 },
conference: { server: MULTIPARTY_SERVER_ENDPOINT },
}
ConnectyCube.init(credentials, appConfig)

Default multiparty server endpoint is wss://janus.connectycube.com:8989 (see).

Connect WebRTC lib

Since “react-native-connectycube” version 3.34.0, the “react-native-webrtc” has been replaced from dependencies to peerDependencies to support autolinking. Install the “react-native-webrtc” and follow the Getting started. Configure your iOS and Android projects.

Until “react-native-connectycube” version 3.34.0, the “react-native-webrtc” is included to “react-native-connectycube”. Follow the Android Manual Linking and iOS Manual Linking guides.

Create meeting

In order to have a conference call, a meeting object has to be created.

const params = {
name: "My meeting",
start_date: timestamp,
end_date: timestamp
attendees: [
{id: 123, email: "..."},
{id: 124, email: "..."}
],
record: false,
chat: false
};
ConnectyCube.meeting.create(params)
.then(meeting => {
const confRoomId = meeting._id;
})
.catch(error => { });

Once meeting is created, you can use meeting._id as a conf room identifier in the below requests when join a call.

Create call session

Once a meeting is created/retrieved, you can create a conf call session:

const session = ConnectyCube.videochatconference.createNewSession();

Once a session is created, you can interact with a Video Conferencing API.

Access local media stream

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

const mediaParams = {
audio: true,
video: true,
};
session
.getUserMedia(mediaParams)
.then((localStream) => {})
.catch((error) => {});

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 can’t 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 how to work with getUserMedia constraints: https://webrtc.github.io/samples/src/content/getusermedia/resolution/

Attach local media stream

Then you should attach your local media stream to a video element:

import {RTCView} from 'react-native-connectycube';
// pass a local or remote stream to the RTCView component
...
<RTCView objectFit="cover" style={styles.rtcView} key={userId} streamURL={localStream.toURL()} />
...

Join room

To jump into video chat with users you should join it:

session
.join(roomId, userId, userDisplayName)
.then(() => {})
.catch((error) => {});

To check current joined video room use the following property:

const roomId = session.currentRoomId;

Join as listener

It can be a requirement where it needs to join a room as listener only, w/o publishing own media stream. It can be useful for a case with a teacher and many students where normally students join a call as listeners and only a teacher publishes own media stream:

session
.joinAsListener(confRoomId, userId, userDisplayName)
.then(() => {})
.catch((error) => {});

List online participants

To list online users in a room:

session
.listOfOnlineParticipants()
.then((participants) => {})
.catch((error) => {});

Events

There are 6 events you can listen for:

ConnectyCube.videochatconference.onParticipantJoinedListener = (
session,
userId,
userDisplayName,
isExistingParticipant
) => {};
ConnectyCube.videochatconference.onParticipantLeftListener = (session, userId) => {};
ConnectyCube.videochatconference.onRemoteStreamListener = (session, userId, stream) => {};
ConnectyCube.videochatconference.onSlowLinkListener = (session, userId, uplink, nacks) => {};
ConnectyCube.videochatconference.onRemoteConnectionStateChangedListener = (session, userId, iceState) => {};
ConnectyCube.videochatconference.onSessionConnectionStateChangedListener = (session, iceState) => {};

Mute/Unmute audio

You can mute/unmute your own audio:

// mute
session.muteAudio();
// unmute
session.unmuteAudio();
//check mute state
session.isAudioMuted(); // true/false

Mute/Unmute video

You can mute/unmute your own video:

// mute
session.muteVideo();
// unmute
session.unmuteVideo();
//check mute state
session.isVideoMuted(); // true/false

List of devices

// get all devices
ConnectyCube.videochatconference
.getMediaDevices()
.then((allDevices) => {})
.catch((error) => {});
// only video devices
ConnectyCube.videochatconference
.getMediaDevices(ConnectyCube.videochatconference.DEVICE_INPUT_TYPES.VIDEO)
.then((videoDevices) => {})
.catch((error) => {});
// only audio devices
ConnectyCube.videochatconference
.getMediaDevices(ConnectyCube.videochatconference.DEVICE_INPUT_TYPES.AUDIO)
.then((audioDevices) => {})
.catch((error) => {});

Switch video cameras

localStream.getVideoTracks().forEach((track) => track._switchCamera());

Switch audio output

  1. connect and install https://github.com/react-native-webrtc/react-native-incall-manager lib
  2. Use InCallManager class to switch audio output:
import InCallManager from 'react-native-incall-manager';
...
let isSpeakerOn = true; // false
InCallManager.setSpeakerphoneOn(isSpeakerOn);

Also, pay attention to InCall Manager lib if you need to use one of the options below:

  • Manage devices events like wired-headset plugged-in state, proximity sensors and expose functionalities to javascript.
  • Automatically route audio to proper devices based on events and platform API.
  • Toggle speaker or microphone on/off, toggle flashlight on/off
  • Play ringtone/ringback/dtmftone

Screen Sharing

Request a desktop stream by calling getDisplayMedia:

session
.getDisplayMedia()
.then((localDesktopStream) => {})
.catch((error) => {});

In React Native, the getDisplayMedia method does not accept constrains as a parameter due to react-native-webrtc limitations.

If the local stream already exists, the next call to getUserMedia or getDisplayMedia will update the tracks in the stream and preserve the track’s enabled state for the audio track.

Screen Sharing on Android

Follow this guide to configure Screen Sharing on Android and this to support Screen Capture on Android 10+. Call the getDisplayMedia after starting a ForegroundService:

import { Platform } from 'react-native';
import notifee, { AndroidImportance } from '@notifee/react-native';
/* ... */
const ScreenSharingComponent() {
const mediaParams = {
audio: true,
video: true,
};
const startShareScreen = async () => {
if (Platform.OS === 'android') {
const channelId = await notifee.createChannel({
id: 'screen_capture',
name: 'Screen Capture',
lights: false,
vibration: false,
importance: AndroidImportance.DEFAULT,
});
await notifee.displayNotification({
title: 'Screen Capture',
body: 'Capturing...',
android: {
channelId,
asForegroundService: true,
},
});
}
// Capturing a screen
const stream = await session.getDisplayMedia();
};
const stopShareScreen = async () => {
if (Platform.OS === 'android') {
await notifee.stopForegroundService();
}
//Get back media stream from camera or call `session.stop(extension)`
const stream = await session.getUserMedia(mediaParams);
};
return <>{/* ... */}</>
}
export default ScreenSharingComponent;

Screen Sharing on iOS

Preform the Screen Sharing integration for iOS guide from Jitsi. Use <ScreenCapturePickerView> component from ‘react-native-webrtc’ to prepare:

import React from 'react';
import { findNodeHandle, Platform, NativeModules } from 'react-native';
import { ScreenCapturePickerView } from 'react-native-webrtc';
/* ... */
const ScreenSharingComponent() {
const screenCaptureView = React.useRef(null);
const mediaParams = {
audio: true,
video: true,
};
const startShareScreen = async () => {
if (Platform.OS === 'ios') {
const reactTag = findNodeHandle(screenCaptureView.current);
await NativeModules.ScreenCapturePickerViewManager.show(reactTag);
}
// Capturing a screen
const stream = await session.getDisplayMedia();
};
const stopShareScreen = async () => {
// Get back media stream from camera or call `session.stop(extension)`
const stream = await session.getUserMedia(mediaParams);
};
return <>
{/* ... */}
{Platform.OS === 'ios' && (
<ScreenCapturePickerView ref={screenCaptureView} />
)}
</>
}
export default ScreenSharingComponent;

Get remote user bitrate

const bitrate = session.getRemoteUserBitrate(userId);

Get remote user mic level

const micLevel = session.getRemoteUserVolume(userId);

Leave room and destroy conf session

To leave current joined video room:

session
.leave()
.then(() => {})
.catch((error) => {});

Retrieve meetings

Retrieve a meeting by id:

const params = {
_id: meetingId,
};
ConnectyCube.meeting
.get(params)
.then((meeting) => {})
.catch((error) => {});

Retrieve a list of meetings:

const params = { limit: 5, offset: 0 };
ConnectyCube.meeting
.get(params)
.then((meetings) => {})
.catch((error) => {});

Edit meeting

A meeting creator can edit a meeting:

const params = { name, start_date, end_date };
ConnectyCube.meeting
.update(meetingId, params)
.then((meeting) => {})
.catch((error) => {});

Delete meeting

A meeting creator can delete a meeting:

ConnectyCube.meeting
.delete(meetingId)
.then(() => {})
.catch((error) => {});

Recording

Server-side recording is available. Read more about Recording feature https://connectycube.com/2021/02/23/connectycube-releases-server-side-calls-recording-along-with-new-meetings-api/

Retrieve recordings with download url

ConnectyCube.meeting
.getRecordings(meetingId)
.then(() => {})
.catch((error) => {});

Continue call in background

If you are developing dedicated apps for iOS and Android - it’s required to apply additional configuration for the app to keeping the call alive when it goes into the background.

**iOS: **

There is no way to continue a video call in background because of some OS restrictions. What is supported there is to continue with voice calling while an app is in background. Basically, the recommended to achieve this is to switch off device camera when an app goes to background and then switch camera on back when an app goes to foreground.

Furthermore, even voice background call are blocked by default on iOS. To unblock - you need to setup proper background mode capabilities in your project. Please find the Enabling Background Audio link with more information how to do it properly. Generally speaking, you need to enable Voice over IP and Remote notifications capabilities:

Setup Xcode VOIP capabilities

**Android: **

For Android, we also recommend to implement the same camera switch flow when go to background and then return to foreground.

To keep the call while in background, we recomment to use the react-native-background-actions library.

The flow is the following:

  • when start a call or go background -> display notification
  • when stop call or return to foreground -> hide notification
// Background Activity
import BackgroundService from "react-native-background-actions";
startBackgroundMode = () => {
this.stopBackgroundMode();
const options = {
taskName: "AppName",
taskTitle: "You have an active call",
taskDesc: "Press to return",
taskIcon: {
name: "ic_notification",
type: "mipmap",
},
linkingURI: "appName://foreground",
};
BackgroundService.start(async (params) => {
await new Promise(async () => {});
}, options);
};
stopBackgroundMode = (force = false) => {
if (BackgroundService.isRunning() || force) {
return BackgroundService.stop();
}
};