logo
Live Streaming
On this page

Implementing Video Call with React (Web)


Feature introduction

This article introduces how to quickly use React to implement a simple Video Call.

Explanation of related concepts:

  • ZEGO Express SDK: Video Call SDK provided by ZEGO, which can provide developers with convenient access, high definition and smoothness, multi-platform interoperability, low latency, and high concurrency audio and video services.
  • Publishing: The process of transmitting the packaged audio and video data stream from the capture stage to the ZEGO Video Call cloud.
  • Playing: The process of pulling existing audio and video data streams from the ZEGO Video Call cloud.

Prerequisites

Before implementing basic Video Call features, please ensure:

Download example source code

Please refer to Download example source code to get the source code.

For related source code, please check the files in the "/express-demo-web/src/Examples/Framework/React" directory.

Usage steps

Note

The Node version used in the current project is 14.17.3, and the React version is 16.7.0.

Taking user A playing user B's stream as an example, the flow is as follows:

The API call sequence of the entire publishing/playing process is as follows:

Create engine

(Optional) Create UI

Before creating the engine, it is recommended for developers to add the following UI elements to facilitate the implementation of basic Video Call features.

  • Local preview window
  • Remote video window
  • End button

Create engine

Import react.js, react-dom.js, and babel.js in the "/express-demo-web/src/Examples/Framework/React/index.html" file.

// Import react.js and react-dom.js
<script src="https://cdn.bootcdn.net/ajax/libs/react/16.7.0/cjs/react.development.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/react-dom/16.7.0/cjs/react-dom-server.browser.development.js"></script>

// Import babel.min.js to compile ES6 syntax
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
Warning

If we need to use JSX, the "type" attribute of the <script> tag needs to be set to "text/babel".

Create a ZegoExpressEngine engine instance, pass the applied AppID to the parameter "appID", and pass the access server address to the parameter "server".

Note
  • "server" is the access server address. For how to obtain it, please refer to Console - Project Information.
  • For SDK version 3.6.0 and above, server can be changed to an empty string, null, undefined, or any character, but cannot be left empty.
// Initialize instance
class CommonUsageReact extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            zg: null
        }
    }
    createZegoExpressEngineOption(){
        const zg = new ZegoExpressEngine(appID, server)
        this.setState({
            zg:zg
        },() => {
            // Listen for event callbacks
            this.initEvent();
        })
    }
}

(Optional) Listen for event callbacks

If you need to register callbacks, developers can implement certain methods in ZegoEvent (including ZegoRTCEvent and ZegoRTMEvent) according to actual needs. After creating the engine, you can set callbacks by calling the on interface.

initEvent() {
  this.state.zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => {
        if (reason == ZegoRoomStateChangedReason.Logining) {
            // Logging in
        } else if (reason == ZegoRoomStateChangedReason.Logined) {
            // Login successful
            //Only when the room state is login successful or reconnection successful, publishing (startPublishingStream) and playing (startPlayingStream) can normally send and receive audio and video
            //Publish your audio and video stream to the ZEGO Video Call cloud
        } else if (reason == ZegoRoomStateChangedReason.LoginFailed) {
            // Login failed
        } else if (reason == ZegoRoomStateChangedReason.Reconnecting) {
            // Reconnecting
        } else if (reason == ZegoRoomStateChangedReason.Reconnected) {
            // Reconnection successful
        } else if (reason == ZegoRoomStateChangedReason.ReconnectFailed) {
            // Reconnection failed
        } else if (reason == ZegoRoomStateChangedReason.Kickout) {
            // Kicked out of the room
        } else if (reason == ZegoRoomStateChangedReason.Logout) {
            // Logout successful
        } else if (reason == ZegoRoomStateChangedReason.LogoutFailed) {
            // Logout failed
        }
});
}

(Optional) Check compatibility

Before implementing publishing/playing features, developers can call the checkSystemRequirements interface to detect browser compatibility.

For browser compatible versions supported by the SDK, please refer to "Prepare environment" in Download example source code.

const result = await this.state.zg.checkSystemRequirements();
// The returned result is the compatibility detection result. When webRTC is true, it means WebRTC is supported. For the meaning of other attributes, please refer to the interface API documentation
console.log(result);
// {
//   webRTC: true,
//   customCapture: true,
//   camera: true,
//   microphone: true,
//   videoCodec: { H264: true, H265: false, VP8: true, VP9: true },
//   screenSharing: true,
//   errInfo: {}
// }

For the meaning of each parameter in the returned result, please refer to the parameter description under the ZegoCapabilityDetection interface.

Login room

Generate Token

Logging into the room requires a Token for identity verification. For how to obtain it, please refer to Using Token Authentication. For quick debugging, you can use the console to generate a temporary Token.

Login room

Call the loginRoom interface, pass in the room ID parameter "roomID", "token", and user parameter "user", and pass in the parameter "config" according to the actual situation to log into the room.

Warning
  • Before logging into the room, please register all callbacks that need to be listened to after logging into the room. After successfully logging into the room, you can receive related callbacks.
  • The values of "roomID", "userID", and "userName" parameters are all customized.
  • Both "roomID" and "userID" must be unique. It is recommended that developers set "userID" to a meaningful value and associate it with the business account system.
// Login room, returns true if successful
// Setting userUpdate to true will enable listening to the roomUserUpdate callback. By default, this listening is not enabled
const result = await this.state.zg.loginRoom(roomID, token, {userID, userName}, {userUpdate: true});

Listen for event callbacks after logging into the room

According to actual application needs, listen for event notifications you want to pay attention to before logging into the room, such as room state updates, user state updates, stream state updates, etc.

  • roomStateChanged: Room state update callback. After logging into the room, when the room connection state changes (such as room disconnection, login authentication failure, etc.), the SDK will notify through this callback.

  • roomUserUpdate: User state update callback. After logging into the room, when users are added to or removed from the room, the SDK will notify through this callback.

    Only when calling the loginRoom interface to log into the room and passing in the ZegoRoomConfig configuration, and the "userUpdate" parameter value is "true", users can receive the roomUserUpdate callback.

  • roomStreamUpdate: Stream state update callback. After logging into the room, when users add or remove audio and video streams in the room, the SDK will notify through this callback.

Warning

Usually, if a user wants to play videos published by other users, they can call the startPlayingStream interface in the callback of stream state update (ADD) to play the remote audio and video stream published by remote users.

// Room state update callback
this.state.zg.on('roomStateChanged', (roomID, reason, errorCode, extendData) => {
        if (reason == ZegoRoomStateChangedReason.Logining) {
            // Logging in
        } else if (reason == ZegoRoomStateChangedReason.Logined) {
            // Login successful
            //Only when the room state is login successful or reconnection successful, publishing (startPublishingStream) and playing (startPlayingStream) can normally send and receive audio and video
            //Publish your audio and video stream to the ZEGO Video Call cloud
        } else if (reason == ZegoRoomStateChangedReason.LoginFailed) {
            // Login failed
        } else if (reason == ZegoRoomStateChangedReason.Reconnecting) {
            // Reconnecting
        } else if (reason == ZegoRoomStateChangedReason.Reconnected) {
            // Reconnection successful
        } else if (reason == ZegoRoomStateChangedReason.ReconnectFailed) {
            // Reconnection failed
        } else if (reason == ZegoRoomStateChangedReason.Kickout) {
            // Kicked out of the room
        } else if (reason == ZegoRoomStateChangedReason.Logout) {
            // Logout successful
        } else if (reason == ZegoRoomStateChangedReason.LogoutFailed) {
            // Logout failed
        }
});

// User state update callback
this.state.zg.on('roomUserUpdate', (roomID, updateType, userList) => {
    console.warn(
        `roomUserUpdate: room ${roomID}, user ${updateType === 'ADD' ? 'added' : 'left'} `,
        JSON.stringify(userList),
    );
});

// Stream state update callback
// For specific implementation of the callback method, please refer to the "Video Call" example source code file /src/Examples/QuickStart/VideoTalk/index.js
this.state.zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => {
    if (updateType == 'ADD') {
        // Stream added, start playing stream
    } else if (updateType == 'DELETE') {
        // Stream deleted, stop playing stream
    }
});

Publish stream

Create stream

  1. Before starting to publish, you need to create a local audio and video stream. Call the createZegoStream interface. By default, it will capture camera images and microphone sounds.
Warning

After calling the createZegoStream interface, you need to wait for the ZEGO server to return the stream object before performing subsequent operations.

Create a container <div> for the media stream player component in HTML.

<div id="local-video" style="width:320px;height:240px;"></div>

Play the media stream after creating the stream.

// After calling the createZegoStream interface, you need to wait for the ZEGO server to return the stream object before performing subsequent operations
const localStream = await this.state.zg.createZegoStream();

// Play the video before or during publishing preview.
localStream.playVideo(document.querySelector("#local-video"), {enableAutoplayDialog:true});
  1. (Optional) Set audio and video capture parameters

You can set audio and video related capture parameters through the following properties in the createZegoStream interface as needed. For details, please refer to Custom Video Capture:

  • camera: Configuration for camera and microphone capture stream.

  • screen: Configuration for screen capture stream.

  • custom: Configuration for third-party stream capture.

Start publishing

Call the startPublishingStream interface, pass in the stream ID parameter "streamID" and the stream object "localStream" obtained from creating the stream, to send the local audio and video stream to remote users.

Warning
  • The value of the "streamID" parameter is customized and must be globally unique within the entire AppID.
  • If you need to publish multiple streams, call the startPublishingStream interface multiple times. Ensure that the "streamID" of each stream is different.
// localStream is the MediaStream object obtained from creating the stream
this.state.zg.startPublishingStream(streamID, localStream)

Listen for event callbacks after publishing

According to actual application needs, listen for event notifications you want to pay attention to after publishing, such as publishing state updates, publishing quality, etc.

  • publisherStateUpdate: Publishing state update callback. After successfully calling the publishing interface, when the publishing state changes (such as network interruption causing publishing exceptions, etc.), the SDK will notify through this callback while retrying publishing.
  • publishQualityUpdate: Publishing quality callback. After successfully calling the publishing interface, the audio and video stream quality data (such as resolution, frame rate, bitrate, etc.) is called back periodically.
// Register the publisherStateUpdate publishing state update event callback.
this.state.zg.on('publisherStateUpdate',({streamID, state}) => {
    // streamID is the stream ID of publishing, state is the publishing state. You can do some logical processing based on these states.
})
// Register the publishQualityUpdate publishing quality update event callback.
this.state.zg.on('publishQualityUpdate', (streamID, stats) => {
    // In the stats object, you can get stream quality related information such as resolution, frame rate, bitrate for data display.
})

Play stream

Start playing

Call the startPlayingStream interface, and according to the passed stream ID parameter "streamID", play the audio and video images that have been published to the ZEGO server by remote users.

Note

The "streamID" published by remote users can be obtained from the roomStreamUpdate callback.

Create a container <div> for the media stream player component in HTML.

<div id="remote-video" style="width: 320px;height: 240px"></div>

Play the remote stream obtained on the interface.

const remoteStream = await this.state.zg.startPlayingStream(streamID);

// Create a media stream player component
const remoteView = this.state.zg.createRemoteStreamView(remoteStream);
// "remote-video" is the container DOM element id.
remoteView.play("remote-video", {enableAutoplayDialog:true});
Warning

"streamID" must be globally unique within the entire AppID.

Listen for event callbacks after playing

According to actual application needs, listen for event notifications you want to pay attention to after playing, such as playing state changes, playing quality, etc.

  • playerStateUpdate: Playing state update callback. After successfully calling the playing interface, when the playing state changes (such as network interruption causing publishing exceptions, etc.), the SDK will notify through this callback while retrying publishing.
  • playQualityUpdate: Playing quality callback. After successfully calling the playing interface, the audio and video stream quality data (such as resolution, frame rate, bitrate, etc.) is called back periodically.
// Register the playerStateUpdate playing state update event callback.
this.state.zg.on('playerStateUpdate',({streamID, state}) => {
    // streamID is the stream ID of playing, state is the playing state. You can do some logical processing based on these states.
})
// Register the playQualityUpdate playing quality update event callback.
this.state.zg.on('playQualityUpdate', (streamID, stats) => {
    // In the stats object, you can get stream quality related information such as resolution, frame rate, bitrate for data display.
})

Experience Video Call features

Run the project on a real device. After running successfully, you can see the local video image.

To facilitate the experience, ZEGO provides a Web platform for debugging. On this page, enter the same AppID and RoomID, enter different UserIDs and corresponding Token, and you can join the same room to communicate with real device devices. When the Video Call starts successfully, you can hear remote audio and see remote video images.

Stop publishing/playing

Stop publishing

Call the stopPublishingStream interface to stop sending local audio and video streams to remote users.

this.state.zg.stopPublishingStream(streamID)

Destroy stream

Call the destroyStream interface to destroy the created stream data. After destroying the stream, developers need to destroy the video (stop capture) themselves.

// localStream is the MediaStream object obtained by calling the createZegoStream interface
this.state.zg.destroyStream(localStream)

Stop playing

Call the stopPlayingStream interface to stop playing the audio and video stream published by remote users.

this.state.zg.stopPlayingStream(streamID)

Logout room

Call the logoutRoom interface to log out of the room.

this.state.zg.logoutRoom(roomID)

Previous

Implementing Video Call with Angular (Web)

Next

Use uni-app for Browser Rendering and Playback (Web)