This page provides an introduction to the Web SDK 4.x and a set of guidelines that help you migrate from the Web SDK 3.x to the Web SDK 4.x.
The Web SDK 4.x refactors the Web SDK 3.x. Based on the features of 3.x, 4.x fully optimizes the internal architecture of the SDK and provides more flexible and easy-to-use APIs.
Compared to the Web SDK 3.x, the Web SDK 4.x has the following advantages:
Stream
object with Track
objects for separate and flexible control over audio and video.This section introduces the major differences between the Web SDK 3.x and 4.x and provides migration examples on building a video conferencing app.
publish
or unpublish
, the SDK does not automatically switch the user role. For details, see the migration example of publishing the local tracks.For asynchronous methods such as joining and leaving a channel, publishing and subscribing, enumerating media input devices, and starting and stopping live transcoding, the Web SDK notifies users of the results of these asynchronous operations with callbacks or events, while the Web SDK 4.x uses promises.
For the Web SDK 4.x, we replace the Stream object with Track
objects. You create, publish, or subscribe to one or multiple audio and video tracks. Tracks make up a stream. The advantage of dividing a stream up into tracks is that audio and video are controllable separately. And these new methods are easier to use than the Stream.addTrack
and Stream.removeTrack
methods in the Web SDK.
For now, the Web SDK 4.x allows publishing multiple audio tracks but only one video track. The SDK automatically mixes multiple audio tracks into one when publishing.
In addition to replacing the Stream
object with Track
objects, the Web SDK 4.x provides different interfaces for the local and remote tracks. Some methods and objects are only available locally, and some are only available remotely. This change affects multiple API methods, including creating objects, publishing, and subscribing to tracks. For details, see Creating an audio track and a video track and Publish the local audio and video tracks.
Rename events
The Web SDK 4.x ensures the consistency of all event names. For example, Agora renames onTokenPrivilegeWillExpire
as token-privilege-will-expire
. Agora also renames several events to ensure developers can better understand how they work. For example, Agora renames peer-online
and peer-offline
as user-joined
and user-left
, stream-added
and stream-removed
as user-published
and user-unpublished
.
Change the format of parameters in events
In the Web SDK 3.x, the parameters of events must be wrapped in an object, while in the Web SDK 4.x, you can directly pass multiple parameters in events.
Take the "connection-state-change"
event as an example:
// Use the Web SDK 3.x
client.on("connection-state-change", e => {
console.log("current", e.curState, "prev", e.prevState);
});
// Use the Web SDK 4.x
client.on("connection-state-change", (curState, prevState) => {
console.log("current", curState, "prev", prevState);
});
Improve the event notification mechanism
The Web SDK 4.x improves its event notification mechanism, and does not trigger channel events repeatedly.
For example, assume that a local user A and remote users B, C, and D joins a channel at the same time, and B, C, and D all publishes their streams. If A suddenly loses connection with the channel due to bad network conditions, the SDK automatically reconnects A to the channel. While A is reconnecting to the channel, B leaves the channel and C unpublishes the stream. My question is, what events that the SDK triggers during the whole process?
When A joins the channel, the Web SDK 3.x and Web SDK 4.x trigger the same events:
When A loses connection with the channel due to poor network conditions and reconnects to the channel:
In the Web SDK 3.x, you can expect to receive the same events multiple times due to disconnection and reconnection, which may cause unexpected problems for dealing with these events on the app level. You need to listen for connection state changes and reset the states on the app level to avoid unexpected problems when receiving these events for the second time.
The Web SDK 4.x does not send you the same events repeatedly and ensures your app works properly during reconnection.
As these hypothetical examples demonstrate, the event notification mechanism in the Web SDK 4.x is more intuitive and does not need extra work.
This section takes building a video conferencing app as an example and introduces the differences between implementing the Web SDK 4.x and the Web SDK 3.x in detail.
First, create a Client
object and join a specified channel.
// Use the Web SDK 3.x
const client = AgoraRTC.createClient({ mode: "live", codec: "vp8" });
client.init("APPID", () => {
client.join("Token", "Channel", null, (uid) => {
console.log("join success", uid);
}, (e) => {
console.log("join failed", e);
});
});
// Use the Web SDK 4.x
const client = AgoraRTC.createClient({ mode: "live", codec: "vp8" });
try {
const uid = await client.join("APPID", "Channel", "Token", uid);
console.log("join success");
} catch (e) {
console.log("join failed", e);
}
Here we assume that our code runs within in an
async
function and useawait
in the following code snippets.
Key points:
Promise
object together with async/await
for the asynchronous operation join
.client.init
method and you pass APPID
when calling client.join
. If you want to join another channel that uses a different App ID, you do not need to create another client object.Second, create an audio track object from the audio sampled by a microphone and create a local video track from the video captured by a camera. In the sample code, by default, we play the local video track and do not play the local audio track.
// Use the Web SDK 3.x
const localStream = AgoraRTC.createStream({ audio: true, video: true });
localStream.init(() => {
console.log("init stream success");
localStream.play("DOM_ELEMENT_ID", { muted: true });
}, (e) => {
console.log("init local stream failed", e);
});
// Use the Web SDK 4.x
const localAudio = await AgoraRTC.createMicrophoneAudioTrack();
const localVideo = await AgoraRTC.createCameraVideoTrack();
console.log("create local audio/video track success");
localVideo.play("DOM_ELEMENT_ID");
Key points:
Stream
object. Call createMicrophoneAudioTrack
to create an audio track and call createCameraVideoTrack
to create a video track.init
method because the SDK initializes the microphone and camera when creating the tracks and notifies you of the result with promises.muted
parameter in the play
method. If you do not want to play the local audio track, do not call play
in the local audio track object.After creating the local audio and video tracks, publish these tracks to the channel.
// Use the Web SDK 3.x
client.publish(localStream, err => {
console.log("publish failed", err);
});
client.on("stream-published", () => {
console.log("publish success");
});
// Use the Web SDK 4.x
try {
// Remove this line if the channel profile is not live broadcast.
await client.setClientRole("host");
await client.publish([localAudio, localVideo]);
console.log("publish success");
} catch (e) {
console.log("publish failed", e);
}
Key points:
host
when publishing the stream. However, in the Web SDK 4.x, you need to call setClientRole
to set the user role as host
.publish
returns a Promise
object representing the eventual completion or failure of the asynchronous operation.publish
, you need to pass one or multiple LocalTrack
objects instead of the Stream
object. You can call publish
repeatedly to publish multiple tracks and call unpublish
repeatedly to unpublish multiple tracks.When a remote user in the channel publishes media tracks, we need to automatically subscribe to these tracks and play. To do this, you need to listen for the user-published
event and call subscribe
when the SDK triggers this event.
// Use the Web SDK 3.x
client.on("stream-added", e => {
client.subscribe(e.stream, { audio: true, video: true }, err => {
console.log("subscribe failed", err);
});
});
client.on("stream-subscribed", e => {
console.log("subscribe success");
e.stream.play("DOM_ELEMENT_ID");
});
// Use the Web SDK 4.x
client.on("user-published", async (remoteUser, mediaType) => {
await client.subscribe(remoteUser, mediaType);
if (mediaType === "video") {
console.log("subscribe video success");
remoteUser.videoTrack.play("DOM_ELEMENT_ID");
}
if (mediaType === "audio") {
console.log("subscribe audio success");
remoteUser.audioTrack.play();
}
});
Key points:
stream-added
, stream-removed
, and stream-updated
events with the user-published
and user-unpublished
events.Pay attention to the
mediaType
parameter of theuser-published
event, which marks the type of the current track the remote user publishes. It can be"video"
or"audio"
. If the remote user publishes an audio track and a video track at the same time, the SDK triggers twouser-published
events, in whichmediaType
is"audio"
and"video"
respectively.
subscribe
returns a Promise
object representing the eventual completion or failure of the asynchronous operation. When calling subscribe
, pass a remoteUser
object. For details, see AgoraRTCRemoteUser.remoteUser
and you can go on to call play
.Rename getScreenSources
as getElectronScreenSources, remove callbacks, and return a promise
getDevices returns a promise. Add getCameras and getMicrophones
Remove the Logger
object, and add disableLogUpload, enableLogUpload, and setLogLevel
Replace createStream
with the following methods:
Remove Client.init
Remove Client.getConnectionState
and add Client.connectionState
Add RECONNECTING
in ConnectionState
Add Client.uid
Remove the callbacks of Client.enableDualStream / Client.disableDualStream and return a promise
Move Client.getCameras
, Client.getDevices
, Client.getRecordingDevices
to the AgoraRTC
interface
Remove Client.getPlayoutDevices
Replace Client.getLocalAudioStats
, Client.getLocalVideoStats
, Client.getRemoteAudioStats
, and Client.getRemoteVideoStats
with LocalAudioTrack.getStats, LocalVideoTrack.getStats, RemoteAudioTrack.getStats, and RemoteVideoTrack.getStats.
Remove Client.getSystemStats
Replace Client.getSessionStats
and Client.getTransportStats
with Client.getRTCStats
Remove the callback in Client.join and return a promise. Also add the appid
parameter in this method
Remove the callback in Client.leave and return a promise.
Add Client.once
Add the tracks
parameter in Client.publish for passing LocalTrack. This method returns a promise. Remove Client.on("stream-published")
Client.unpublish returns a promise.
Add the user
parameter in Client.subscribe for passing AgoraRTCRemoteUser,This method returns a promise. Remove Client.on("stream-subscribed")
.
Add the user
parameter in Client.unsubscribe for passing AgoraRTCRemoteUser. This method returns a promise.
Client.renewToken returns a promise.
Remove the callback in Client.setClientRole and return a promise. In the Web SDK 4.x, setting the user role as audience
does not unpublish, and when calling publish
, the SDK does not automatically setting the user role as host
Replace Client.setEncryptionMode
and Client.setEncryptionSecret
with Client.setEncryptionConfig
Client.setLiveTranscoding, Client.startLiveStreaming, and Client.stopLiveStreaming all return a promise. Remove Client.on("liveTranscodingUpdated")
, Client.on("liveStreamingStarted")
, Client.on("liveStreamingFailed")
, and Client.on("liveStreamingStopped")
events.
Client.startChannelMediaRelay
return a promise
Replace setDestChannelInfo
in ChannelMediaRelayConfiguration with addDestChannelInfo, remove several parameters
Remove several parameters in setSrcChannelInfo of ChannelMediaRelayConfiguration
Client.stopChannelMediaRelay return a promise.
Remove the callback in Client.updateChannelMediaRelay and this method returns a promise.
Replace Client.on("first-video-frame-decode")
and Client.on("first-audio-frame-decode")
with RemoteTrack.on("first-frame-decode")
Replace Client.on("active-speaker")
with Client.on("volume-indicator")
Rename Client.on("onTokenPrivilegeWillExpire")
and Client.on("onTokenPrivilegeDidExpire")
as Client.on("token-privilege-will-expire") and Client.on("token-privilege-did-expire")
Remove Client.on("network-type-changed")
Remove Client.on("connected")
and Client.on("reconnect")
. You can get events related to connection states fromClient.on("connection-state-change")
Add the isFallbackOrRecover
parameter in Client.on("stream-fallback")
Remove
Stream.setAudioOutput
. Agora does not recommends setting the audio output device on the web page. Instead, Agora recommends using the default audio output device.
In the Web SDK 4.x, Agora replaces the Stream object with Track
objects. Tracks make up a stream. You create, publish, or subscribe to one or multiple audio and video tracks to control the media stream. The advantage of dividing a stream up into tracks is that audio and video are controllable separately. Additionally, the Web SDK 4.x provides different interfaces for the local and remote tracks. Some methods and objects are only available locally, and some are only available remotely.
Listed below are the major differences on media control between the Web SDK 4.x and Web SDK 3.x:
Stream.muteAudio
and Stream.muteVideo
methods with ILocalTrack.setEnabled for enabling or disabling a local audio or video track. This replacement changes the following SDK behaviors:Client.on("mute-audio")
, Client.on("mute-video")
, Client.on("unmute-audio")
, or Client.on("unmute-video")
events. The Web SDK 4.x removes these events. When you call setEnabled
to enable or disable a published local track, the SDK triggers the Client.on("user-published")
or Client.on("user-unpublished")
events on the remote client.Stream.muteVideo(true)
to disable a local video stream, the camera light stays on, which might adversely impact the user experience. In contrast, if you call setEnabled(false)
in the Web SDK 4.x to disable a local video track, the SDK immediately turns off the camera.Stream.switchDevice
with IMicrophoneAudioTrack.setDevice and ICameraVideoTrack.setDevice for setting the media input device.Stream.setAudioOutput
with IRemoteAudioTrack.setPlaybackDevice for setting the audio output device.