ZUJONOW
Book a demo
Book a demo
    Realtime communication
  • →   Tutorial

Terminology

Let's start with the terms used in Zujo meeting Client SDK.

Meeting

A Meeting represents real-time audio, video, and/or screen-share session, and is the basic building block for media sharing among participants. Supports upto 5,000 participants.

Participants

Participants are the client applications that are connected to a Meeting and shares audio and video media with one another.

Local Participant

Participant producing audio or video stream from the local client's media sources

Streams

Streams are indiviual audio and video streams produced by the participants in the meeting

Active Speaker

Active speaker represents the participant who is currently producing highest decibels audio stream (in other words speaking)

Active presenter

Active presenter is the participant who is currently sharing his/her screen as a video stream

Main participant

Main participant represents the client who shall be displayed on the main screen indicating that he/she is either presenting or speaking


Installation

Get an API key

Signup on the ZujoNow website to get a key pair for SDK authentication. Your API Key and Secret will be visible on the console dashboard.

Integrate

Include this in your HTML file

<script src="https://sdk.zujonow.com/zujo-sdk-2.0.0.min.js"></script>

Step 0: Access token generation (server-side code)

An access token is required to authenticate with the Zujo SDK and make any API calls. You can generate one with the API key and secret mentioned in your developer portal at ZujoNow console.

const jwt = require("jsonwebtoken");
const options = { expiresIn: "10m", algorithm: "HS256" };
const payload = {
apikey: apikey,
permissions: ["allow_join", "allow_mod"], // also accepts "ask_join"
};
const token = jwt.sign(payload, secret, options);

Available permissions are:

  • allow_join: The participant will be permitted entry without request.
  • ask_join: The participant will not be permitted entry without request.
  • allow_mod: Allow participant to enable/disable other participant's mic/webcam.

This generated token must be sent in the Authorization header for all API calls.
And it should also be used with the ZujoSDK.config(token) method.

Step 1: Create or join meeting

Get a meeting id for new meeting or validate an existing meeting id to join a meeting.

  • Create new meeting ID

    const options = {
    method: "POST",
    headers: {
    Authorization: "your jwt token goes here",
    },
    };
    fetch("https://call-api.zujonow.com/api/meetings", options)
    .then((response) => response.json())
    .then((result) => console.log(result)) // result will contain meetingId
    .catch((error) => console.log("error", error));

    OR

  • Validate existing meeting ID for joining

    const options = {
    method: "POST",
    headers: {
    Authorization: "your jwt token goes here",
    },
    };
    // returns status code 400 if ID is invalid
    fetch(`https://call-api.zujonow.com/api/meetings/${meetingId}`, options)
    .then((response) => response.text())
    .then((result) => console.log(result))
    .catch((error) => console.log("error", error));

Step 2: Initialize meeting

To initialize meeting you need to provide the following parameters:

  • meetingId: string from the previous step to specify which meeting to join in.
  • name: string which will be displayed as username of participant in the meeting.
  • micEnabled: boolean option to indicate if mic should be on while joining.
  • webcamEnabled: boolean option to indicate if webcam should be on while joining.
  • maxResolution: "sd" | "hd" defines the maximum available resolution for webcam video.
const meeting = ZujoSDK.initMeeting({
meetingId, // required
name, // required
micEnabled, // optional, default: true
webcamEnabled, // optional, default: true
maxResolution, // optional, default: "hd"
});

The meeting object consists of:

  • Properties:

    • id: string
    • activeSpeakerId: string
    • activePresenterId: string
    • mainParticipantId: string
    • localParticipant: Participant
    • participants: Map<string, Participant>
    • messages: Array<{senderId: string, text: string, timestamp: number}>
  • Events:

    • participant-joined, participant-left
    • speaker-changed, presenter-changed
    • main-participant-changed
    • entry-requested, entry-responded
    • recording-started, recording-stopped
    • stream-enabled, stream-disabled
    • chat-message
  • Methods:

    • join(), leave()
    • muteMic(), unmuteMic()
    • disableWebcam(), enableWebcam()
    • disableScreenShare(), enableScreenShare()
    • on(eventType: string), off(eventType: string)
    • respondEntry(participantId: string, decision: "allowed" | "denied")
    • startRecording(webhookUrl: string), stopRecording()
    • sendChatMessage(text: string)

Step 3: Get local and remote participants

You can get the local streams and participant meta from meeting.localParticipant. And a Map of joined participants is always available via meeting.participants.

const localParticipant = meeting.localParticipant;
const participants = meeting.participants;

Each participant object consists of:

  • Properties:

    • id: string
    • displayName: string
    • streams: Map<string, Stream>
  • Events:

    • stream-enabled
    • stream-disabled
  • Methods:

    • setQuality(quality: "low" | "med" | "high")
    • enableMic(), disableMic()
    • enableWebcam(), disableWebcam()
    • on(eventType: string), off(eventType: string)

Step 4: Listen for entry request events

When participant asks for entry in a meeting that you are connected to, you will be notified via entry-requested and when you or any other participant's entry is responded, entry-responded will be fired.

meeting.on("entry-requested", (participantId, name) => {
setEntryRequests([...entryRequestsRef.current, { id: participantId, name }]);
// you can open a dialog to respond with
// decision "allowed" or "denied" with the following method
meeting.respondEntry(participantId, decision);
});
meeting.on("entry-responded", (participantId, decision) => {
// decision parameter will be: "allowed" or "denied"
setEntryRequests(
entryRequestsRef.current.filter((r) => r.id !== participantId)
);
});

Step 5: Listen for new & leaving participant events

When participant joins or leaves a meeting that you are connected to, you will be notified via participant-joined and participant-left events respectively.

meeting.on("participant-joined", (participant) => {
setParticipants(new Map(meeting.participants));
});
meeting.on("participant-left", (participant) => {
setParticipants(new Map(meeting.participants));
});

Step 6: Listen for audio/video stream events

When a participant from meeting enables or diables a audio/video stream, you will be notified via stream-enabled and stream-disabled events from the participant object.

participant.on("stream-enabled", (stream) => {
if (stream.kind === "video") {
// play video track on a <video /> element
} else if (stream.kind === "audio") {
// play audio track on a <audio /> element
} else if (stream.kind === "share") {
// play screen sharing video track on a <video /> element
}
});
participant.on("stream-disabled", (stream) => {
if (stream.kind === "video") {
// remove video track or the <video /> element
} else if (stream.kind === "audio") {
// remove audio track or the <audio /> element
} else if (stream.kind === "share") {
// remove screen sharing video track or the <video /> element
}
});

Each stream object consists of:

  • Properties:

    • id: string
    • kind: string
    • codec: string
    • track: MediaStreamTrack
  • Methods:

    • pause()
    • resume()

Note: Chrome Autoplay policy workaround

Chrome's autoplay policy does not allow audio autoplay unless user has interacted with the domain (click, tap, etc.) or the user's Media engagement Index threshold has been crossed. Thus, as a workaround before starting the meeting, user can either create a meeting join page or create a join meeting confirmation dialog by which we can perform a user click interaction to enable audio autoplay in chrome's newer versions.

Step 7: Main screen video (optional)

When a participant who is currently presenting or speaking is changed in the meeting, you will be notified via main-participant-changed event.

meeting.on("main-participant-changed", (participant) => {
// show participant video stream on main screen
});

Step 8: Join the meeting

After we set local participant, main-screen participant, other participants, participant event handlers and stream event handlers from the meeting, next step is to join the meeting by calling meeting.join(). This will trigger participant-joined event for all other participants.

meeting.join();

Step 9: Utility methods & events (optional)

  • Mute/Unmute mic

    Toggle own mic with the unmuteMic() and muteMic() methods. Toggling mic will trigger stream-enabled and stream-disabled events for all other participants when enabling and disabling mic.

    // unmute/mute your own mic
    meeting.unmuteMic();
    meeting.muteMic();
    // unmute/mute other participant's mic
    participant.unmuteMic();
    participant.muteMic();
  • Enable/Disable Webcam

    Toggle own webcam with the enableWebcam() and disableWebcam() methods. Toggling webcam will trigger stream-enabled and stream-disabled events for all other participants when enabling and disabling webcam.

    // disable/enable your own webcam
    meeting.enableWebcam();
    meeting.disableWebcam();
    // disable/enable other participant's webcam
    participant.enableWebcam();
    participant.disableWebcam();
  • Enable/Disable Screen share

    Share your screen with the enableScreenShare() method and stop sharing with disableScreenShare(). Toggling screen-share will trigger stream-enabled and stream-disabled events for all other participants when enabling and disabling screen-share.

    meeting.enableScreenShare();
    meeting.disableScreenShare();
  • Start/Stop recording

    Record the meeting session with startRecording(webhookUrl) method and stop recording with stopRecording(). Toggling recording will trigger recording-started and recording-stopped events for all participants when starting and stopping recording respectively.

    // The webhook will be called with the fileUrl as a POST request when the recording is processed.
    meeting.startRecording("https://your-app-server.com/api/recordings");
    meeting.stopRecording();
    // ...
    meeting.on("recording-started", () => {
    setRecordStatus("active");
    // 🔴 notify all users of recording start
    });
    meeting.on("recording-stopped", () => {
    setRecordStatus("inactive");
    // ⚫ notify all users of recording end
    });
  • In-meeting Chat

    Send messages with the sendChatMessage(text) method and all other participants will be notified via chat-message event.

    meeting.sendChatMessage("Hello world!");
    // ...
    meeting.on("chat-message", (data) => {
    setChatMessages([...meeting.messages]);
    const { senderId, text, timestamp } = data;
    // 📢 notify user or show in the chat window
    });
  • Active speaker event

    The speaker-changed event will be fired whenever the loudest speaking participant changes.

    meeting.on("speaker-changed", (participant) => {
    // indicate participant as speaking
    });
  • Active presenter event

    The presenter-changed event will be fired whenever someone enables screen sharing.

    meeting.on("presenter-changed", (participant) => {
    // indicate participant as presenting screen
    });
  • Set participant video quality

    Update the participant video quality based on use case to "low" | "med" | "high".

    participant.setQuality("low");

Leave the meeting

You can disconnect from the meeting with meeting.leave() method. This will trigger participant-left event for all other participants.

meeting.leave();

ZUJONOW

Make your app engaging.

API/SDKRealtime communicationLive streamingOn Demand VideoContent delivery

Copyright © 2021 ZUJONOW