Quickstart
Updated
Build a basic voice calling, video calling, or streaming app with the Agora RTC SDK.
This page provides a step-by-step guide on how to create a basic real-time app using the Agora RTC SDK. The same steps apply whether you're building voice calling, video calling, interactive live streaming, or broadcast streaming — only a few configuration values change based on your use case.
Understand the tech
To start a real-time session, implement the following steps in your app:
-
Initialize the engine: Before calling other APIs, create and initialize an engine instance.
-
Join a channel: Call methods to create and join a channel.
-
Join as a host: A live streaming event has one or more hosts. A host publishes audio and video to the channel and can also subscribe to streams from other hosts.
-
Join as audience: Audience members can only subscribe to streams published by hosts.
Note
For the voice calling and video calling use cases, each user joins as a host.
-
-
Send and receive audio and video: Hosts publish streams to the channel. Audience members subscribe to audio and video streams published by hosts.
-
For streaming applications, set the latency level based on your use case:
-
Interactive live streaming: Optimized for real-time interaction with ultra-low latency. Use this when hosts and audience need to interact quickly, such as in live Q&A sessions, interactive classrooms, or auctions.
-
Broadcast streaming: Optimized for scalability with slightly higher latency. Use this for large-scale events where one-way broadcasting is sufficient, such as concerts, sports events, or news broadcasts.
-
Prerequisites
- A camera and a microphone.
- A valid Agora account and project. See Agora account management for details.
- Node.js 14 or higher.
Set up your project
-
Create a new directory for your Electron project in a local folder. Add the following files to the root of the project directory:
package.json: Manages project dependencies and scripts.index.html: Defines the app's user interface.main.js: The main process entry point.renderer.js: The renderer process script, responsible for interacting with the Agora Electron SDK.
-
Create a user interface for your app based on your use-case.
A basic user interface consists of an element for local video and an element for remote video. Refer to Create a user interface to get a bare bones sample layout.
Install the SDK
Add the RTC SDK to your project using npm:
-
Configure
package.json-
macOS
{ "name": "electron-demo-app", "version": "0.1.0", "author": "your name", "description": "My Electron app", "main": "main.js", "scripts": { "start": "electron ." }, "agora_electron": { "platform": "darwin", "prebuilt": true }, "dependencies": { "agora-electron-sdk": "latest" }, "devDependencies": { "electron": "latest" } } -
Windows
{ "name": "electron-demo-app", "version": "0.1.0", "author": "your name", "description": "My Electron app", "main": "main.js", "scripts": { "start": "electron ." }, "agora_electron": { "platform": "win32", "prebuilt": true, "arch": "ia32" }, "dependencies": { "agora-electron-sdk": "latest" }, "devDependencies": {"electron": "latest" } }Configuration parameters
agora-electron-sdk: Version number of the Agora Electron SDK. Set to latest for the most recent version, or specify a version number. Seeagora-electron-sdkon npm for available versions.electron: Electron version number. Versions 5.0.0 and above are supported. For macOS devices with M1 chips, use version 11.0.0 or higher.platform(Optional): Target platform. Set todarwinfor macOS orwin32for Windows.prebuilt(Optional): Set totrueby default to prevent compatibility issues between Electron, Node.js, and the SDK.arch(Optional): Target architecture. Defaults to your system architecture.
Note
Different versions of Electron have different environment requirements. If you see errors due to a mismatched environment when running the project, refer to the official Electron documentation to choose the appropriate Electron and Node.js versions.
-
-
To install the dependencies, open a terminal in your project root directory and run the following commands::
-
macOS
npm install -
Windows
npm install -D --arch=ia32 electron npm installNote
-
On Windows, you must first install the 32-bit version of Electron by running
npm install -D --arch=ia32 electron, and then runnpm install. Otherwise, you may encounter the error: “Not a valid Win32 application.” -
If a
node_modulesfolder exists in the project root directory, delete it before runningnpm installto avoid potential errors.
-
-
Compile the latest SDK from the Electron SDK repository and integrate it into your application.
Implement Realtime Communication
This section guides you through the implementation of basic real-time audio and video interaction in your app.
The following figure illustrates the essential steps:
This guide includes complete sample code that demonstrates implementing basic real-time interaction. To understand the core API calls in the sample code, review the following implementation steps.
Set up the main process
The main.js file is the entry point for your Electron application. It defines the main process, which is responsible for creating and managing browser windows. This script initializes the app, loads the UI from index.html, and ensures proper behavior across platforms.
const { app, BrowserWindow } = require("electron");
const path = require("path");
// If using Electron 9.x or later, set allowRendererProcessReuse to false
app.allowRendererProcessReuse = false;
function createWindow() {
// Create the browser window
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// preload: path.join(__dirname, "renderer.js"),
// Enable Node integration and disable context isolation
nodeIntegration: true,
contextIsolation: false,
},
});
// Load the contents of the index.html file
mainWindow.loadFile("./index.html");
// Open the Developer Tools
mainWindow.webContents.openDevTools();
}
// Manage the browser window for the Electron app
app.whenReady().then(() => {
createWindow();
// On macOS, create a new window if none are open
app.on("activate", function () {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
// Quit the Electron app when all windows are closed (except on macOS)
app.on("window-all-closed", function () {
if (process.platform !== "darwin") app.quit();
});Handle permissions
Perform this step only when the target platform is macOS. Starting with macOS v10.14, you must check and obtain permission before accessing the camera or microphone. Use Electron’s askForMediaAccess method to request these permissions from the user.
Add the following code to the main.js file:
// Check and request device permissions
async function checkAndApplyDeviceAccessPrivilege() {
// Check and request camera permission
const cameraPrivilege = systemPreferences.getMediaAccessStatus('camera');
console.log(`Camera privilege before applying: ${cameraPrivilege}`);
if (cameraPrivilege !== 'granted') {
await systemPreferences.askForMediaAccess('camera');
console.log('Requested camera access from user');
}
// Check and request microphone permission
const micPrivilege = systemPreferences.getMediaAccessStatus('microphone');
console.log(`Microphone privilege before applying: ${micPrivilege}`);
if (micPrivilege !== 'granted') {
await systemPreferences.askForMediaAccess('microphone');
console.log('Requested microphone access from user');
}
}
checkAndApplyDeviceAccessPrivilege();Import dependencies
Import the modules and functions required to build the app using RTC SDK. Add the following code to renderer.js:
const {
createAgoraRtcEngine,
ChannelProfileType,
ClientRoleType,
VideoSourceType,
VideoViewSetupMode
} = require("agora-electron-sdk");Specify connection parameters
Provide the App ID, temporary token, and the channel name you used when generating the token. The engine uses these values to initialize and join the channel.
// Enter your App ID
const APPID = "<-- Insert App Id -->";
// Enter your temporary token
let token = "<-- Insert Token -->";
// Enter the channel name used when generating the token
const channel = "<-- Insert Channel Name -->";
// Specify a unique user ID for this session
let uid = 123;Initialize the engine
For real-time communication, create an IRtcEngine object by calling createAgoraRtcEngine and then call initialize with RtcEngineContext to specify the App ID. Call registerEventHandler to register a custom event handler for managing user interactions within the channel.
let rtcEngine;
const os = require("os");
const path = require("path");
const sdkLogPath = path.resolve(os.homedir(), "./test.log");
// Create RtcEngine instance
rtcEngine = createAgoraRtcEngine();
// Initialize RtcEngine instance
rtcEngine.initialize({
appId: APPID,
logConfig: { filePath: sdkLogPath }
});Enable the video module
Call the enableVideo method to enable the video module, and then call startPreview to start the local video preview.
// Enable the video module
rtcEngine.enableVideo();
// Start the local video preview
rtcEngine.startPreview();Join a channel
To join a channel, call joinChannel with the following parameters:
-
Channel name: The name of the channel to join. Clients that pass the same channel name join the same channel. If a channel with the specified name does not exist, it is created when the first user joins.
-
Authentication token: A dynamic key that authenticates a user when the client joins a channel. In a production environment, you obtain a token from a token server in your security infrastructure. For the purpose of this guide Generate a temporary token.
-
User ID: A 32-bit signed integer that identifies a user in the channel. You can specify a unique user ID for each user yourself. If you set the user ID to
0when joining a channel, the SDK generates a random number for the user ID and returns the value in theonJoinChannelSuccesscallback. -
Channel media options: Configure
ChannelMediaOptionsto define publishing and subscription settings, optimize performance for your specific use-case, and set optional parameters.
Set the channelProfile, clientRoleType, and audienceLatencyLevelType according to your use case:
| Use case | Channel profile | Client role | Latency level |
|---|---|---|---|
| Voice calling | ChannelProfileCommunication | ClientRoleBroadcaster | N/A |
| Video calling | ChannelProfileCommunication | ClientRoleBroadcaster | N/A |
| Interactive live streaming | ChannelProfileLiveBroadcasting | ClientRoleBroadcaster or ClientRoleAudience | AudienceLatencyLevelUltraLowLatency (default) |
| Broadcast streaming | ChannelProfileLiveBroadcasting | ClientRoleBroadcaster or ClientRoleAudience | AudienceLatencyLevelLowLatency |
Note
- Only broadcasters can publish media. Audience members cannot publish until promoted to broadcaster.
- Choose Communication mode for calls where every user publishes, typically fewer than 17 participants. Choose Live Broadcasting mode for larger events with separate hosts and audience.
- The latency level only applies to the audience role, and affects your pricing tier.
The following example shows the configuration for interactive live streaming with the broadcaster role:
// Join the channel using a temporary token
rtcEngine.joinChannel(token, channel, uid, {
// Set the channel profile according to your use case (see table above)
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting,
// Set the user role to ClientRoleBroadcaster (host) or ClientRoleAudience according to your use case
clientRoleType: ClientRoleType.ClientRoleBroadcaster,
// Only takes effect when clientRoleType is ClientRoleAudience
audienceLatencyLevelType: AudienceLatencyLevelType.AudienceLatencyLevelLowLatency,
// Publish audio collected from the microphone
publishMicrophoneTrack: true,
// Publish video collected from the camera
publishCameraTrack: true,
// Automatically subscribe to all audio streams
autoSubscribeAudio: true,
// Automatically subscribe to all video streams
autoSubscribeVideo: true,
});Register event handlers
Call the registerEventHandler method to register the following callback events:
onJoinChannelSuccess: Triggered when the local user successfully joins a channel. After joining, callsetupLocalVideoto configure the local video window.onUserJoined: Triggered when a remote user joins the current channel. After the remote user joins, callsetupRemoteVideoto configure the remote video window.onUserOffline: Triggered when a remote user leaves the current channel. After the remote user leaves, callsetupRemoteVideoto close the remote video window.
const EventHandles = {
// Listen for the local user joining the channel
onJoinChannelSuccess: ({ channelId, localUid }, elapsed) => {
console.log('Successfully joined channel: ' + channelId);
// After the local user joins the channel, set up the local video view
rtcEngine.setupLocalVideo({
sourceType: VideoSourceType.VideoSourceCameraPrimary,
uid: uid,
view: localVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
});
},
// Listen for remote users joining the channel
onUserJoined: ({ channelId, localUid }, remoteUid, elapsed) => {
console.log('Remote user ' + remoteUid + ' joined');
// After a remote user joins the channel, set up the remote video view
rtcEngine.setupRemoteVideo(
{
sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid,
view: remoteVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
},
{ channelId },
);
},
// Listen for users leaving the channel
onUserOffline: ( { channelId, localUid }, remoteUid, reason ) => {
console.log('Remote user ' + remoteUid + ' left the channel');
// After a remote user leaves the channel, remove the remote video view
rtcEngine.setupRemoteVideo(
{
sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid,
view: remoteVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupRemove,
},
);
},
};
// Register the event handler
rtcEngine.registerEventHandler(EventHandles);Note
To ensure that you receive all RTC SDK events, set the engine event handler before joining a channel.
Display the local video
To display the local video:
// Set up the local video view
rtcEngine.setupLocalVideo({
sourceType: VideoSourceType.VideoSourceCameraPrimary,
uid: uid,
view: localVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
});Display remote video
To display the remote video, call setupRemoteVideo to configure the remote video feed.
// Set up the remote video view
rtcEngine.setupRemoteVideo(
{
sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid,
view: remoteVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
},
{ channelId },
);
// Remove the remote video view
rtcEngine.setupRemoteVideo(
{
sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid,
view: remoteVideoContainer,
setupMode: VideoViewSetupMode.VideoViewSetupRemove,
},
);Call this method when the client receives the onUserJoined callback.
Start and close the app
When a user launches your app, start Realtime Communication. When a user closes the app, stop Realtime Communication and release resources.
-
To start Realtime Communication, initialize the engine, display the local video and join a channel.
-
When Realtime Communication ends, leave the channel and clean up resources:
// Stop the preview rtcEngine.stopPreview(); // Leave the channel rtcEngine.leaveChannel();When you no longer need to interact, unregister the event handler and call
releaseto release engine resources.// Unregister the event handler rtcEngine.unregisterEventHandler(EventHandles); // Release the engine rtcEngine.release();caution
After destroying the engine, you can no longer use SDK methods and callbacks. To use the real-time interaction functions again, create a new engine instance. See Initialize the engine for details.
Complete sample code
A complete code sample demonstrating the basic process of real-time interaction is provided for your reference. Replace the entire contents of the main.js and renderer.js with the following code samples:
main.js
Note
- In
renderer.js, replace the values forAPPID,token, andchannelwith your App ID, the temporary token from Agora Console, and the channel name you used to generate the token. - If you're targeting macOS v10.14 or later, add the device permission code to
main.js. For more details, see Get device permissions.
To test the complete code, see Test the sample code.
Create a user interface
To connect the sample code to your existing UI, ensure that your index.html file includes the HTML elements used to Display the local video and Display remote video.
Alternatively, use the following sample to create a minimal interface. Add the following code to index.html:
Sample code to create the user interface
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Electron Quickstart</title>
</head>
<body>
<h1>Electron Quickstart</h1>
<!-- Add the local video view to the interface -->
<div
id="join-channel-local-video"
style="width: 300px; height: 300px; float: left"
></div>
<!-- Add the remote video view to the interface -->
<div
id="join-channel-remote-video"
style="width: 300px; height: 300px; float: left"
></div>
</body>
<script src="./renderer.js"></script>
</html>Test the sample code
Take the following steps to test the sample code:
-
Update the
APPID,token, andchannelparameter values in your code. -
To run the app, execute the following command in the project root directory:
npm startYou see a window pop up showing the local video.
-
Invite a friend to run the demo app on a second device. Alternatively, use the Web demo to join the same channel.
- If users on both devices join the channel as hosts, they can see and hear each other.
- If one user joins as host and the other as audience, the host can see themselves in the local video window; the audience can see the host in the remote video window and hear the host.
Reference
This section contains content that completes the information on this page, or points you to documentation that explains other aspects of this product.
- If a firewall is deployed in your network environment, refer to Connect with Cloud Proxy to use Agora services normally.
Next steps
After implementing the quickstart sample, read the following documents to learn more:
- To ensure communication security in a test or production environment, best practice is to obtain and use a token from an authentication server. For details, see Secure authentication with tokens.
Sample project
Agora provides open source sample projects on GitHub for your reference. Download or view the JoinChannelVideo project for a more detailed example.
