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.
- A device running Windows 7 or higher.
- Microsoft Visual Studio 2017 or higher with C++ desktop development support and C++ 11 or above.
- If you use C# for development, you also need the .NET Framework.
Set up your project
The following steps outline the process to set up a new Visual Studio 2022 project on Windows 11 for implementing real-time audio and video interaction functions.
-
In Visual Studio, select File > New > Project to create a new project. In the pop-up window, select MFC application as the project template, click Next, update the project name to
AgoraQuickStart, set the project storage location, and then click Create. -
In the pop-up MFC application window, set the application type to Dialog-based , and set Use MFC to Use MFC in a shared DLL. Enter the generated class, set the generated class to Dlg, set the base class to CDialog, and click Finish.
To integrate real-time audio and video interaction into your project:
-
Launch Visual Studio 2022 and open your existing project by selecting File > Open > Project/Solution.
-
Navigate to your project directory and open the
.slnfile.
-
Create a user-interface for your app based on your application use-case.
A basic UI consists of the following controls:
- A Picture Control for displaying local video
- A Picture Control for displaying remote video
- An Edit Control for entering a channel name
- Buttons to join and leave a channel
Refer to Create a user interface to get a bare bones sample layout.
Install the SDK
Install the Agora RTC SDK:
-
Download the latest Windows SDK.
-
Unzip and open the downloaded SDK. Copy all subfolders in
sdk/to your solution folder. Make sure these subfolders are in the same directory as your.slnfile.
Configure the project
In the Solution Explorer window, right-click the project name and click Properties to configure the following:
- Go to the C/C++ > General > Additional Include Directory menu, click Edit, and in the pop-up window enter
$(SolutionDir)sdk\high_level_api\include. - Go to the Linker > General > Additional Library Directory menu, click Edit, and in the pop-up window:
- for 64 bit Windows, enter
$(SolutionDir)sdk\x86_64. - for x86 Windows, enter
$(SolutionDir)sdk\x86.
- for 64 bit Windows, enter
- Go to the Linker > Input > Additional Dependencies menu, click Edit, and in the pop-up window:
- for 64 bit Windows, enter
$(SolutionDir)sdk\x86_64\agora_rtc_sdk.dll.lib. - for x86 Windows, enter
$(SolutionDir)sdk\x86\agora_rtc_sdk.dll.lib.
- for 64 bit Windows, enter
- Enter the Advanced menu, and in Advanced Properties, set Copy contents to OutDir and Copy C++ runtime to output directory to
Yes. - Go to the Build Events > Post-Build Events > Command Line menu and enter
copy $(SolutionDir)sdk\x86_64\*.dll $(SolutionDir)$(Platform)\$(Configuration). - Click Apply to save the configuration.
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.
Initialize the engine
For real-time communication, initialize an IRtcEngine instance and set up event handlers to manage user interactions within the channel. Use RtcEngineContext to specify the App ID, and custom event handler, then call initialize to initialize the engine, enabling further channel operations. Add the following code to your header and .cpp files:
// Declare the required variables
IRtcEngine* m_rtcEngine = nullptr; // RTC engine instance
CAgoraQuickStartRtcEngineEventHandler m_eventHandler; // IRtcEngineEventHandlervoid CAgoraQuickStartDlg::initializeAgoraEngine() {
// Create IRtcEngine object
m_rtcEngine = createAgoraRtcEngine();
// Create IRtcEngine context object
RtcEngineContext context;
// Input your App ID. You can obtain your project's App ID from the Agora Console
context.appId = APP_ID;
// Add event handler for callbacks and events
context.eventHandler = &m_eventHandler;
// Initialize
int ret = m_rtcEngine->initialize(context);
m_initialize = (ret == 0);
if (m_initialize) {
// Enable the video module
m_rtcEngine->enableVideo();
} else {
AfxMessageBox(_T("Failed to initialize Agora RTC engine"));
}
}Join a channel
To join a channel, call joinChannel[2/2] 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 | N/A |
| Video calling | CHANNEL_PROFILE_COMMUNICATION | CLIENT_ROLE_BROADCASTER | N/A |
| 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:
void CAgoraQuickStartDlg::joinChannel(const char* token, const char* channelName) {
ChannelMediaOptions options;
// Set the channel profile according to your use case (see table above)
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
// Set the user role to CLIENT_ROLE_BROADCASTER (host) or CLIENT_ROLE_AUDIENCE according to your use case
options.clientRoleType = CLIENT_ROLE_BROADCASTER;
// Only takes effect when clientRoleType is CLIENT_ROLE_AUDIENCE
options.audienceLatencyLevel = AUDIENCE_LATENCY_LEVEL_LOW_LATENCY;
// Publish the audio stream captured by the microphone
options.publishMicrophoneTrack = true;
// Publish the camera track
options.publishCameraTrack = true;
// Automatically subscribe to all audio streams
options.autoSubscribeAudio = true;
// Automatically subscribe to all video streams
options.autoSubscribeVideo = true;
// Join the channel using the temporary token obtained from the console
m_rtcEngine->joinChannel(token, channelName, 0, options);
}Subscribe to RTC SDK events
The RTC SDK provides an interface for subscribing to channel events. To use it, create a custom event handler class by inheriting from IRtcEngineEventHandler and override its methods to handle real-time interaction events. Add callbacks to receive notification of users joining and leaving the channel.
Note
To ensure that you receive all RTC SDK events, set the engine event handler before joining a channel.
// Define the CAgoraQuickStartRtcEngineEventHandler class to handle callback events such as users joining and leaving the channel
class CAgoraQuickStartRtcEngineEventHandler
: public IRtcEngineEventHandler {
public:
CAgoraQuickStartRtcEngineEventHandler()
: m_hMsgHandler(nullptr) {
}
// Set the handle of the message receiving window
void SetMsgReceiver(HWND hWnd) {
m_hMsgHandler = hWnd;
}
// Register onJoinChannelSuccess callback
// This callback is triggered when a local user successfully joins a channel
virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed) {
if (m_hMsgHandler) {
::PostMessage(m_hMsgHandler, WM_MSGID(EID_JOIN_CHANNEL_SUCCESS), uid, 0);
}
}
// Register onUserJoined callback
// This callback is triggered when the remote host successfully joins the channel
virtual void onUserJoined(uid_t uid, int elapsed) {
if (m_hMsgHandler) {
::PostMessage(m_hMsgHandler, WM_MSGID(EID_USER_JOINED), uid, 0);
}
}
// Register onUserOffline callback
// This callback is triggered when the remote host leaves the channel or is offline
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason) {
if (m_hMsgHandler) {
::PostMessage(m_hMsgHandler, WM_MSGID(EID_USER_OFFLINE), uid, 0);
}
}
private:
HWND m_hMsgHandler;
};Implement the callback functions.
LRESULT CAgoraQuickStartDlg::OnEIDJoinChannelSuccess(WPARAM wParam, LPARAM lParam) {
// Join channel success callback
uid_t localUid = wParam;
return 0;
}
LRESULT CAgoraQuickStartDlg::OnEIDUserJoined(WPARAM wParam, LPARAM lParam) {
// Remote user joined callback
uid_t remoteUid = wParam;
if (m_remoteRender) {
return 0;
}
// Render remote view
VideoCanvas canvas;
canvas.renderMode = RENDER_MODE_TYPE::RENDER_MODE_HIDDEN;
canvas.uid = remoteUid;
canvas.view = m_staRemote.GetSafeHwnd();
m_rtcEngine->setupRemoteVideo(canvas);
m_remoteRender = true;
return 0;
}
LRESULT CAgoraQuickStartDlg::OnEIDUserOffline(WPARAM wParam, LPARAM lParam) {
// Remote user left callback
uid_t remoteUid = wParam;
if (!m_remoteRender) {
return 0;
}
// Clear remote view
VideoCanvas canvas;
canvas.uid = remoteUid;
m_rtcEngine->setupRemoteVideo(canvas);
m_remoteRender = false;
return 0;
}Enable the video module
Call the enableVideo method to enable the video module.
// Enable the video module
m_rtcEngine->enableVideo();Display the local video
Follow these steps to set up and start the local video preview:
-
Create a
VideoCanvasinstance and configure its properties:- Set the video rendering mode.
- Specify the user ID (
uid). - Define the display window.
-
Call the
setupLocalVideomethod to apply theVideoCanvasconfiguration. -
Call the
startPreviewmethod to start the local video preview.void CAgoraQuickStartDlg::setupLocalVideo() { // Set local video display properties VideoCanvas canvas; // Set video to be scaled proportionally canvas.renderMode = RENDER_MODE_TYPE::RENDER_MODE_HIDDEN; // User ID canvas.uid = 0; // Video display window canvas.view = m_staLocal.GetSafeHwnd(); m_rtcEngine->setupLocalVideo(canvas); // Preview the local video m_rtcEngine->startPreview(); }
Display remote video
To display the remote user's video:
-
Define the video display properties using
VideoCanvas. -
Call
setupRemoteVideoto render the video.void CAgoraQuickStartDlg::setupRemoteVideo(uid_t remoteUid) { // Set remote video display properties VideoCanvas canvas; // Set video size to be proportionally scaled canvas.renderMode = RENDER_MODE_TYPE::RENDER_MODE_HIDDEN; // Remote user ID canvas.uid = remoteUid; // You can only choose to set either view or surfaceTexture. If both are set, only the settings in view take effect. canvas.view = m_staRemote.GetSafeHwnd(); m_rtcEngine->setupRemoteVideo(canvas); m_remoteRender = true; return 0; }
Leave the channel
When a user ends a call, or closes the client call leaveChannel to exit the current channel.
To stop the local video preview and clear the view:
-
Call
stopPreviewto stop playing the local video. -
Call
setupLocalVideo, passing an emptyVideoCanvasto reset the view.void CAgoraQuickStartDlg::LeaveChannel() { if (m_rtcEngine) { // Stop local video preview m_rtcEngine->stopPreview(); // Leave the channel m_rtcEngine->leaveChannel(); // Clear local view VideoCanvas canvas; canvas.uid = 0; m_rtcEngine->setupLocalVideo(canvas); m_remoteRender = false; } }
Release resources
To destroy the engine instance, call release :
// Release resources when the object is destroyed
m_rtcEngine->release(true);
m_rtcEngine = NULL;Caution
After you call Dispose, you can no longer use any SDK methods or callbacks. To use realtime communication again, you must create a new engine. For more information, see Initialize the Engine.
Complete sample code
A complete code sample that implements the basic process of real-time interaction is presented here for your reference. Copy the sample code into your project to quickly implement the basic functions of real-time interaction.
AgoraQuickStartDlg.h
Create a user interface
To connect the sample code to your existing user interface, ensure that your UI includes the controls used to Display the local video and Display remote video.
Alternatively, follow these steps to create a bare-bones UI for your project.
Steps to create a minimalistic UI
-
Switch the project to resource view in the right menu bar, and then open the
.Dialogfile. -
From View > Toolbox, select Add Picture Control, and in Properties > Miscellaneous, set the ID of the control to
IDC_STATIC_REMOTE. -
From View > Toolbox , select Add Picture Control , and in Properties > Miscellaneous , set the control's ID to
IDC_STATIC_LOCAL. -
To set up an input box for entering the channel name, from View > Toolbox , select add Static Text control, and change the description text to
Channel namein the properties. Add an Edit Control as an input box, and in Properties > Miscellaneous, set the control's ID toIDC_EDIT_CHANNEL. -
To add join and leave channel buttons, open View > Toolbox and add two Button controls. In Properties > Miscellaneous , set the IDs to
ID_BTN_JOINandID_BTN_LEAVE, and set the description text to Join and Leave respectively. Your user interface looks similar to the following:
Follow these steps to create a bare-bones UI for your project.
Test the sample code
To test your app, follow these steps:
-
In Visual Studio, select local Windows debugger to start compiling the application.
-
Enter the name of the channel you want to join in the input box and click the Join button to join the channel.
You see yourself in the local view.
-
Use the Web demo to join the same channel and test the following use-cases:
- 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 sample project for a more detailed example.
- For a Windows C# implementation, see this sample project.
