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.
-
Unity Hub and Unity Editor 2018.4.0 or higher.
-
A suitable operating system and compiler for your development platform:
Development platform Operating system version Compiler version Android Android 4.1 or later Android Studio 4.1 or later iOS iOS 10.15 or later Xcode 9.0 or later macOS macOS 10.15 or later Xcode 9.0 or later Windows Windows 7 or later Microsoft Visual Studio 2017 or later
Set up your project
Refer to the following steps or the Official Unity documentation to create a Unity project.
-
Open Unity and click New.
-
Enter the following details:
- Project name : The name of the project.
- Location : Project storage path.
- Template : The project type. Select 3D.
-
Click Create project.
To open your existing project:
-
In the Projects window, click the Open button in the top-right corner.
-
Browse your file manager and select the folder of the project you want to open.
-
Confirm your selection to add the project to the Projects window and open it in the Unity Editor.
Install the SDK
-
Go to the Download SDKs page and download the latest version of the Unity SDK.
-
In Unity Editor, navigate to Assets > Import Package > Custom Package, and select the unzipped SDK.
All plugins are selected by default. Deselect any plugins you don't need, then click Import.
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.
Before proceeding, create and set up a script to implement Video Calling and bind the script to the canvas.
Steps to set up a script
-
Create a new script and import the UI library.
-
In the Project tab, navigate to Assets > Agora-Unity-RTC-SDK > Code > Rtc, right-click and select Create > C# Script. A new file named
NewBehaviourScript.csappears in your Assets. -
Rename the file to
JoinChannel.csand open it. -
Import the Unity namespaces to access UI components by adding the following code at the top of the file:
using UnityEngine; using UnityEngine.UI;
-
-
Bind the script to the canvas.
In
Assets/Agora-Unity-RTC-SDK/Code/Rtc, select theJoinChannel.csfile, and drag it to the Canvas. In the Inspector panel, ensure that the file is bound to the Canvas.
Import Agora classes
Import the Agora.Rtc namespace, which contains various classes and interfaces required to implement real-time audio and video functions.
using Agora.Rtc;Initialize the engine
For real-time communication, create an IRtcEngine instance using RtcEngine.CreateAgoraRtcEngine(). Then, configure it using Initialize(context) with an RtcEngineContext, specifying the application context, App ID, and channel profile. In your JoinChannel.cs file, add the following code:
internal IRtcEngine RtcEngine;
// Fill in your app ID
private string _appID= "";
private void SetupVideoSDKEngine()
{
// Create an IRtcEngine instance
RtcEngine = Agora.Rtc.RtcEngine.CreateAgoraRtcEngine();
RtcEngineContext context = new RtcEngineContext();
context.appId = _appID;
context.channelProfile = CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING;
context.audioScenario = AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT;
// Initialize the instance
RtcEngine.Initialize(context);
}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 audienceLatencyLevel according to your use case:
| Use case | Channel profile | Client role | Latency level |
|---|---|---|---|
| Voice calling | CHANNEL_PROFILE_COMMUNICATION | CLIENT_ROLE_BROADCASTER | AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY (default) |
| Video calling | CHANNEL_PROFILE_COMMUNICATION | CLIENT_ROLE_BROADCASTER | AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY (default) |
| Interactive live streaming | CHANNEL_PROFILE_LIVE_BROADCASTING | CLIENT_ROLE_BROADCASTER or CLIENT_ROLE_AUDIENCE | AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY (default) |
| Broadcast streaming | CHANNEL_PROFILE_LIVE_BROADCASTING | CLIENT_ROLE_BROADCASTER or CLIENT_ROLE_AUDIENCE | AUDIENCE_LATENCY_LEVEL_LOW_LATENCY |
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:
// Fill in your channel name
private string _channelName = "";
// Fill in a temporary token
private string _token = "";
public void Join() {
// Set channel media options
ChannelMediaOptions options = new ChannelMediaOptions();
// Start video rendering
LocalView.SetEnable(true);
// Automatically subscribe to all audio streams
options.autoSubscribeAudio.SetValue(true);
// Automatically subscribe to all video streams
options.autoSubscribeVideo.SetValue(true);
// Set the channel profile to live broadcast
options.channelProfile.SetValue(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING);
// Set the user role as host
options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
// If setting the client role to audience, uncomment the following line to configure the latency level
// options.audienceLatencyLevel.SetValue(AUDIENCE_LATENCY_LEVEL_TYPE.AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY);
// Join a channel
RtcEngine.JoinChannel(_token, _channelName, 0, options);
}Subscribe to RTC SDK events
Create an instance of the UserEventHandler class and set it as the engine event handler. Override the callbacks based on your use-case.
// Implement your own callback class by inheriting from the IRtcEngineEventHandler interface
internal class UserEventHandler : IRtcEngineEventHandler
{
private readonly JoinChannelVideo _videoSample;
internal UserEventHandler(JoinChannelVideo videoSample)
{
_videoSample = videoSample;
}
// Triggered when the local user successfully joins a channel
public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
{
}
// Triggered when the SDK receives and successfully decodes the first frame of a remote video
public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
{
// Set the display for the remote video
_videoSample.RemoteView.SetForUser(uid, connection.channelId, VIDEO_SOURCE_TYPE.VIDEO_SOURCE_REMOTE);
// Start video rendering
_videoSample.RemoteView.SetEnable(true);
Debug.Log("Remote user joined");
}
// Triggered when the remote user leaves the channel
public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
{
// Stop displaying the remote video
_videoSample.RemoteView.SetEnable(false);
}
}Create an instance of the user callback class and call InitEventHandler to register the event handler.
private void InitEventHandler()
{
UserEventHandler handler = new UserEventHandler(this);
RtcEngine.InitEventHandler(handler);
}Note
To ensure that you receive all RTC SDK events, register the event handler before joining a channel.
Display the local video
Use the following code to set up the local video view:
internal VideoSurface LocalView;
private void PreviewSelf()
{
// Enable the video module
RtcEngine.EnableVideo();
// Enable local video preview
RtcEngine.StartPreview();
// Set up local video display
LocalView.SetForUser(0, "");
// Render the video
LocalView.SetEnable(true);
}Display remote video
When a remote user joins the channel, the OnUserJoined callback is triggered. Call SetForUser to set the remote video display and call SetEnable(true) to render the video.
internal VideoSurface RemoteView;
// When the SDK receives the first frame of a remote video stream and successfully decodes it, the OnUserJoined callback is triggered.
public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed) {
// Set the remote video display
_videoSample.RemoteView.SetForUser(uid, connection.channelId, VIDEO_SOURCE_TYPE.VIDEO_SOURCE_REMOTE);
// Start video rendering
_videoSample.RemoteView.SetEnable(true);
Debug.Log("Remote user joined");
}Leave the channel
Call LeaveChannel to leave the current channel.
public void Leave() {
Debug.Log("Leaving " + _channelName);
// Leave the channel
RtcEngine.LeaveChannel();
// Disable the video module
RtcEngine.DisableVideo();
// Stop remote video rendering0
RemoteView.SetEnable(false);
// Stop local video rendering
LocalView.SetEnable(false);
}Handle permissions
To access the media devices, add device permissions to your project according to your target platform.
Since version 2018.3, Unity does not actively obtain device permissions from the user. Call CheckPermission to check for and obtain the necessary permissions.
-
Include the
UnityEngine.Androidnamespace, which contains Android-specific classes for interacting with Android devices from Unity:#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID) using UnityEngine.Android; #endif -
Create a list of permissions to be obtained.
#if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID) private ArrayList permissionList = new ArrayList() { Permission.Camera, Permission.Microphone }; #endif -
Check if the required permissions have been granted. If not, prompt the user to grant the necessary permissions.
private void CheckPermissions() { #if (UNITY_2018_3_OR_NEWER && UNITY_ANDROID) foreach (string permission in permissionList) { if (!Permission.HasUserAuthorizedPermission(permission)) { Permission.RequestUserPermission(permission); } } #endif }
For iOS and macOS platforms, the RTC SDK includes a post-build script named BL_BuildPostProcess.cs. When you build and export your Unity project as an iOS project, this script automatically inserts camera and microphone permission entries into the Info.plist file, eliminating the need for manual updates.
Start and stop your client
-
When the client starts, ensure that device permissions have been granted.
void Update() { CheckPermissions(); } -
To start Realtime Communication, initialize the engine and set up the event handler.
void Start() { SetupVideoSDKEngine(); InitEventHandler(); PreviewSelf(); } -
To clean up all session-related resources when a user exits the client, call the
Disposemethod of theIRtcEngine.void OnApplicationQuit() { if (RtcEngine != null) { Leave(); // Destroy IRtcEngine RtcEngine.Dispose(); RtcEngine = null; } }Note
After calling
Dispose, you can no longer use any methods or callbacks of the SDK. To use Realtime Communication features again, create a new engine instance.
Complete sample code
A complete code sample demonstrating the basic process of real-time interaction is provided for your reference. To quickly implement the basic functions of Realtime Communication, copy the following sample code into your project:
Sample code to implement Realtime Communication in your client
Create a user interface
Follow these steps to set up a basic UI for your project or to integrate essential UI elements into your existing interface. A basic UI consists of the following components:
- Local view window
- Remote view window
- Buttons to join and leave the channel
Create a basic UI
-
Create buttons to join and leave channel
-
In your Unity project, right-click the Sample Scene and select Game Object > UI > Button. You see a button on the scene canvas.
-
In the Inspector panel, rename the button to
Joinand adjust the position coordinates as needed. For example:- Pos X:
-329 - Pos Y:
-172
- Pos X:
-
Select the Text control of the Join button , and change the text to
Joinin the Inspector panel. -
Repeat the steps to create a Leave button, using the following positions:
- Pos X:
329 - Pos Y:
-172
- Pos X:
-
-
Create local and remote view windows
-
Right-click the Canvas and select UI > Raw Image.
-
In the Inspector panel, rename
Raw ImagetoLocalViewand adjust its size and position on the canvas. For example:- PosX:
-250 - Pos Y:
0 - Width:
250 - Height:
250
- PosX:
-
Repeat the above steps to create a remote view window, name it
RemoteView, and adjust its position on the canvas:- PosX:
250 - Pos Y:
0 - Width:
250 - Height:
250
Save the changes.
- PosX:
-
At this point your UI looks similar to the following:
Test the sample code
Take the following steps to test the sample code:
-
Obtain a temporary token from Agora Console.
-
In
JoinChannel.cs, update_appID,_channelName, and_tokenwith the app ID, channel name, and temporary token for your project. -
In Unity Editor, click Play to run your project.
-
Click Join to join a channel.
-
Invite a friend to run the demo client on a second device. Use the same
_appID_,_token, and_channelNameto join. Alternatively, use the Web demo to join the same channel.After your friend joins successfully, you can hear and see each other.
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.
