Implement a voice chat room on HarmonyOS
This document describes how to integrate the Alibaba Real-Time Communication (ARTC) software development kit (SDK) into your HarmonyOS project. Using the ARTC SDK, you can quickly build a simple audio-only interactive application for scenarios such as voice calls and voice chat rooms.
Function introduction
Before you begin, understand the following basic concepts of real-time audio and video interaction:
ARTC SDK: The software development kit for ApsaraVideo Real-time Communication. It is an Alibaba Cloud product that helps developers quickly implement real-time audio and video interactions.
Channel: A concept similar to a room. Users in the same channel can interact in real time.
Streamer: A user who can publish audio and video streams in a channel and subscribe to streams published by other streamers.
Viewer: A user who can subscribe to audio and video streams in a channel but cannot publish them.
The following figure shows the basic flow for implementing a voice call or a voice chat room:
Users must call
joinChannelto join a channel before they can ingest or pull streams:Audio-only call scenario: All users are streamers and can ingest and pull streams.
Voice chat room scenario: Users who need to ingest streams in the channel must have the streamer role. If a user only needs to pull streams, you can set their role to viewer.
You can use
setClientRoleto set different roles for users.
After joining a channel, the stream ingest and pulling behaviors vary based on the user's role:
All users in a channel can receive audio and video streams from other users in the same channel.
Streamers can ingest audio and video streams into the channel.
If a viewer needs to ingest a stream, they must call the
setClientRolemethod to switch their role to streamer before they can ingest the stream.
Prerequisites
Before you run the sample project, make sure your development environment meets the following requirements:
Development tool: DevEco Studio 5.0.3.900 Release or later. Obtain the HarmonyOS NEXT SDK for API Version 12 or later.
Test device: A HarmonyOS device that supports audio and video, running HarmonyOS NEXT 5.0.0.102 (for API Version 12) or later. The "Allow debugging" option must be enabled.
Network: A stable network connection is required.
Application: An AppID and AppKey for your ApsaraVideo Real-time Communication application. For more information, see Create an application.
Sample project
The Alibaba Cloud ARTC SDK provides an open source sample project for your reference. You can download the project or view the sample source code.
Implementation steps
The following section uses a voice chat room scenario as an example. The process is as follows:
The main features of a voice chat room scenario are as follows:
Audio-only: The channel contains only audio, not video.
Streamer and viewer roles: The roles in the channel are divided into streamer and viewer. Streamers can ingest and pull audio streams. Viewers can only pull audio streams that are ingested by streamers. Viewers can switch their role to streamer.
Implement audio-only interaction
1. Handle permission requests
Before you start the audio interaction, ensure that you have requested audio and network permissions.
2. Get an authentication token
When you call joinChannel to join an ARTC channel, you must pass an authentication token to authenticate the user's identity. For more information about how to generate tokens, see Token-based authentication.
Production phase:
Generating a token requires an AppKey. To avoid security risks associated with hardcoding the AppKey on the client, we strongly recommend that you generate tokens on your business server and send them to the client for your online service.
Development and testing phase:
During development and testing, if your business server is not yet configured to generate tokens, you can temporarily use the token generation logic in the sample project to create a temporary token.
3. Create and initialize the engine
Create the RTC engine
Call
getInstanceto create an RTC engine object.private rtcEngine: AliRtcEngine | null | undefined; this.rtcEngine = AliRtcEngine.getInstance('', this.context);Initialize the engine
Call the
setChannelProfilemethod to set the channel to interactive mode.Based on the user's role in the scenario, call the
setClientRolemethod to set the user as a streamer or viewer.Call the
setAudioProfilemethod to set the audio quality and scenario mode.
// Set the channel profile to interactive streaming mode.
this.rtcEngine.setChannelProfile(AliRtcChannelProfile.AliRtcInteractiveLive);
// Set the user role.
if (this.isAnchor) {
// Streamer role: needs to publish streams.
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleInteractive);
} else {
// Viewer role: only pulls streams.
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleLive);
}
// Set the audio profile (high-quality mode + music scenario).
this.rtcEngine.setAudioProfile(
AliRtcAudioProfile.AliRtcHighQualityMode,
AliRtcAudioScenario.AliRtcSceneMusicMode
);Implement common callbacks
If an exception occurs during runtime, the SDK first tries to recover automatically using its internal retry mechanism. For errors that the SDK cannot resolve on its own, it notifies your application through predefined callbacks.
The following table describes key callbacks for events that the SDK cannot handle on its own. Your application layer must listen for and respond to these callbacks.
Causes of the abnormal behavior
Callback and parameter
Solutions
Description
Authentication failed
The
resultin theonJoinChannelcallback returnsAliRtcErrJoinBadToken.When this error occurs, your application must verify that the token is correct.
If authentication fails when a user calls an API, the system returns an authentication failure error message in the API callback.
Authentication token is about to expire
onWillAuthInfoExpireWhen this exception occurs, the app must retrieve the latest authentication information and then call
refreshAuthInfo.An authentication expiration error occurs in two scenarios: during an API call or program execution. Therefore, the error feedback is returned through an API callback or a separate error callback.
Authentication token expired
onAuthInfoExpiredWhen this exception occurs, the app must rejoin the meeting.
This event can occur when a user calls an API or during program execution. The feedback is sent through an API callback or a separate error callback.
Network connectivity issue
The
onConnectionStatusChangecallback returnsAliRtcConnectionStatusFailed.When this status is returned, your application must rejoin the channel.
The SDK can automatically recover from network disconnections for a certain period. However, if the disconnection time exceeds a preset threshold, the connection times out. In this case, your application should check the network status and guide the user to rejoin the channel.
Kicked offline
onByeAliRtcOnByeUserReplaced: When this event occurs, check if the useruseridis the same.AliRtcOnByeBeKickedOut: This event indicates that the user was removed by the business service. The user must rejoin the channel.AliRtcOnByeChannelTerminated: This event indicates that the channel was destroyed. The user must rejoin the channel.
The RTC service allows an administrator to remove participants.
Local device exception
onLocalDeviceExceptionWhen this exception occurs, the app should check whether the permissions and device hardware are functioning as expected.
The RTC service supports device detection and exception diagnosis. When a local device exception occurs, the RTC service notifies the client through a callback. If the SDK cannot resolve the issue, your application must intervene and check whether the device is working correctly.
const listener = new AliRtcEngineEventListener()
.onJoinChannel((resultCode: number, channel: string, elapsed: string) => {
console.info(`Join channel result: result=${resultCode}, channel=${channel}, userId=${this.UserId}, elapsed=${elapsed}`);
this.handleJoinResult(resultCode, channel);
})
.onLeaveChannel((resultCode: number) => {
console.info(`Leave channel result: result=${resultCode}`);
})
.onConnectionStatusChange((status: number, reason: number) => {
console.info(`Connection status changed: status=${status}, reason=${reason}`);
})
this.rtcEngine.setRtcEngineEventListener(listener);4. Set stream publishing and pulling properties
By default, the SDK automatically publishes and pulls audio and video streams within the channel.
After you set the role to viewer, you can only pull streams. The
publishLocalAudioStreammethod is invalid for viewers.The following configuration can be set for both streamers and viewers.
this.rtcEngine.publishLocalAudioStream(true);
// Publishing video is not needed in a voice chat scenario.
this.rtcEngine.publishLocalVideoStream(false);
// Set the default to subscribe to all remote audio streams.
this.rtcEngine.setDefaultSubscribeAllRemoteAudioStreams(true);
this.rtcEngine.subscribeAllRemoteAudioStreams(true);5. Join a channel to start the audio-only interaction
Call joinChannel to join the channel. If the token was generated with a single-parameter rule, call the single-parameter AliRtcEngine method. If it was generated with a multi-parameter rule, call the multi-parameter AliRtcEngine method. After you call the method to join the channel, you can obtain the result from the onJoinChannelResult callback. If the result is 0, the user successfully joined the channel. Otherwise, check whether the provided token is invalid.
// Join the channel.
const result = this.rtcEngine.joinChannelWithToken(this.Token, '', '', 'Voice Chat User');
console.info('Join channel call result:', result);6. End the audio-only interaction
When the audio interaction is over, you must leave the channel and destroy the engine. Follow these steps to end the audio interaction:
Call
leaveChannelto leave the channel.Call
destroyto destroy the engine and release related resources.
this.rtcEngine.leaveChannel();
this.hasJoined = false;
AliRtcEngine.destroyInstance();
this.rtcEngine = null;7. (Optional) Let a viewer become a streamer
In your scenario, if a user with the viewer role needs to publish a stream, you can call setClientRole to switch their role to streamer.
// Switch to the streamer role
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleInteractive);
// Switch to the viewer role
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleLive);References
For more audio operations, such as in-ear monitoring, volume control, and speaker callbacks, see Common audio operations and configurations.
To set vocal effects, such as voice changing, beautification, and reverb, see Set voice changing, reverb, and beautification effects.
To play background music or accompaniment music files, see Play and stream external audio input (including sound effects and accompaniment).