Harmony端实现语聊房

本文档将介绍如何在您的 Harmony 项目中集成 ARTC SDK, 快速实现一个简单的纯音频互动App,适用于语音通话、语聊房等场景。

功能介绍

在开始前,您需要了解以下有关音视频实时互动的基本概念:

  • ARTC SDK:阿里云实时音视频产品,帮助开发中快速实现实时音视频互动的SDK。

  • 频道:房间的概念,在同一个频道内的用户可以进行实时互动。

  • 主播:可在频道内发布音视频流,并可订阅其他主播发布的音视频流。

  • 观众:可在频道内订阅音视频流,不能发布音视频流。

下图展示了实现音频通话及语聊房的基本流程:

image
  1. 用户需要先调用joinChannel加入频道,才能进行推流、拉流:

    • 普通纯音频通话场景:所有用户都是主播角色,可以进行推流和拉流;

    • 语聊房场景:需要在频道内推流的用户设置主播角色;如果用户只需要拉流,不需要推流,则设置观众角色;

    • 通过setClientRole为用户设置不同的角色。

  2. 加入频道后,不同角色的用户有不同的推拉流行为:

    • 所有频道内的用户都可以接收相同频道内的音视频流;

    • 主播角色可以在频道内推音视频流;

    • 观众如果需要推流,需要调用setClientRole方法,将用户角色切换成主播,便可以推流。

前提条件

在运行示例项目之前,请确保开发环境满足以下要求:

  • 开发工具:DevEco Studio 5.0.3.900 Release 或以上版本;获取配套 API Version 12的 HarmonyOS NEXT SDK 或以上版本。

  • 测试设备:获取配套 API Version 12的 HarmonyOS NEXT 5.0.0.102 操作系统或以上版本,支持音视频的鸿蒙设备,且已开启“允许调试”选项。

  • 网络环境:需要稳定的网络连接。

  • 应用准备:获取实时音视频应用的AppIDAppKey,详情请参见创建应用

示例项目

阿里云ARTC SDK提供了开源的示例项目供客户参考,您可以前往下载或查看示例源码

实现步骤

下面将以语聊房场景为例进行演示,相关功能时序如下:

image

语聊房场景主要特点如下:

  • 纯音频:频道内仅包含音频,不包含视频。

  • 主播/观众角色:频道内角色分为主播和观众角色,主播角色可以推拉音频流,观众角色只能拉取主播推送的音频流;观众角色可以切换为主播角色。

实现纯音频互动

1. 处理权限请求

进入音频互动前,请确保已经申请了音频和网络相关权限。

2. 获取鉴权 Token

调用joinChannel加入 ARTC 频道时需要传入鉴权 Token,用于鉴权用户的合法身份,有关 Token 的介绍和生成请参考Token鉴权

上线发布阶段

由于Token的生成需要使用AppKey,写死在客户端存在泄露的风险,因此强烈建议线上业务通过业务Server生成下发给客户端。

开发调试阶段

开发调试阶段,如果业务Server还没有生成Token的逻辑,可以暂时参考示例项目中的Token生成逻辑,生成临时Token。

3. 创建并初始化引擎

  • 创建 RTC 引擎

    调用getInstance创建 RTC 引擎对象。

    private rtcEngine: AliRtcEngine | null | undefined;
    
    this.rtcEngine = AliRtcEngine.getInstance('', this.context);
  • 初始化引擎

    • 调用setChannelProfile接口设置频道为互动模式。

    • 根据业务场景中用户的角色,调用setClientRole接口为用户设置主播/观众角色。

    • 调用setAudioProfile接口设置音频质量与场景模式。

// 设置频道模式为互动直播模式
this.rtcEngine.setChannelProfile(AliRtcChannelProfile.AliRtcInteractiveLive);

// 设置用户角色
if (this.isAnchor) {
  // 主播角色:需要推流
  this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleInteractive);
} else {
  // 观众角色:只拉流
  this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleLive);
}

// 设置音频配置(高音质模式 + 音乐场景)
this.rtcEngine.setAudioProfile(
  AliRtcAudioProfile.AliRtcHighQualityMode,
  AliRtcAudioScenario.AliRtcSceneMusicMode
);
  • 实现常用回调

    SDK 在运行过程中如遇到异常情况,会优先尝试内部重试机制以自动恢复。对于无法自行解决的错误,SDK 会通过预定义的回调接口通知您的应用程序。

    以下是一些 SDK 无法处理、需由应用层监听和响应的关键回调:

    异常发生原因

    回调及参数

    解决方案

    说明

    鉴权失败

    onJoinChannel回调中的result返回AliRtcErrJoinBadToken

    发生错误时App需要检查Token是否正确。

    在用户主动调用API时,若鉴权失败,系统将在调用API的回调中返回鉴权失败的错误信息。

    鉴权将要过期

    onWillAuthInfoExpire

    发生该异常时App需要重新获取最新的鉴权信息后,再调用refreshAuthInfo刷新鉴权信息。

    鉴权过期错误在两种情况下出现:用户调用API或程序执行期间。因此,错误反馈将通过API回调或通过独立的错误回调通知。

    鉴权过期

    onAuthInfoExpired

    发生该异常时App需要重新入会。

    鉴权过期错误在两种情况下出现:用户调用API或程序执行期间。因此,错误反馈将通过API回调或通过独立的错误回调通知。

    网络连接异常

    onConnectionStatusChange回调返回AliRtcConnectionStatusFailed

    发生该异常时APP需要重新入会。

    SDK具备一定时间断网自动恢复能力,但若断线时间超出预设阈值,会触发超时并断开连接。此时,App应检查网络状态并指导用户重新加入会议。

    被踢下线

    onBye

    • AliRtcOnByeUserReplaced:当发生该异常时排查用户userid是否相同。

    • AliRtcOnByeBeKickedOut:当发生该异常时,表示被业务踢下线,需要重新入会。

    • AliRtcOnByeChannelTerminated:当发生该异常时,表示房间被销毁,需要重新入会。

    RTC服务提供了管理员可以主动移除参与者的功能。

    本地设备异常

    onLocalDeviceException

    发生该异常时App需要检测权限、设备硬件是否正常。

    RTC服务支持设备检测和异常诊断的能力;当本地设备发生异常时,RTC服务会通过回调的方式通知客户本地设备异常,此时,若SDK无法自行解决问题,则App需要介入以查看设备是否正常。

const listener = new AliRtcEngineEventListener()
  .onJoinChannel((resultCode: number, channel: string, elapsed: string) => {
    console.info(`加入频道结果: result=${resultCode}, channel=${channel}, userId=${this.UserId}, elapsed=${elapsed}`);
    this.handleJoinResult(resultCode, channel);
  })
  .onLeaveChannel((resultCode: number) => {
    console.info(`离开频道结果: result=${resultCode}`);
  })
  .onConnectionStatusChange((status: number, reason: number) => {
    console.info(`连接状态改变: status=${status}, reason=${reason}`);

  })
this.rtcEngine.setRtcEngineEventListener(listener);

4. 设置推拉流属性

SDK 默认情况下会自动推送和拉取频道内的音视频流

  • 设置为观众模式后只能拉流,publishLocalAudioStream 无效。

  • 对于主播和观众均可以设置为下面的配置。

this.rtcEngine.publishLocalAudioStream(true);
// 语聊场景不需要发布视频
this.rtcEngine.publishLocalVideoStream(false);

// 设置默认订阅所有远端音频流
this.rtcEngine.setDefaultSubscribeAllRemoteAudioStreams(true);
this.rtcEngine.subscribeAllRemoteAudioStreams(true);

5. 加入频道开始纯音频互动

调用joinChannel加入频道,如果Token是单参数规则生成的,需要调用SDK单参数的joinChannelWithToken接口,如果是多参数规则生成的,需要调用SDK多参数的joinChannel接口。调用完加入频道后,可以在onJoinChannelResult回调中拿到加入频道结果,如果result0,则表示加入频道成功,否则需要检查传进来的Token是否非法。

// 加入频道
const result = this.rtcEngine.joinChannelWithToken(this.Token, '', '', '语聊房用户');
console.info('加入频道调用结果:', result);

6. 结束纯音频互动

音频互动结束,需要离开房间并销毁引擎,按照下列步骤结束音视频互动。

  1. 调用leaveChannel离会。

  2. 调用destroy销毁引擎,并释放相关资源。

this.rtcEngine.leaveChannel();
this.hasJoined = false;
AliRtcEngine.destroyInstance();

this.rtcEngine = null;

7. (可选)观众上下麦

业务场景中,如果观众角色的用户想要推流,需要调用setClientRole将观众角色切换为主播角色。

// 切换为主播角色
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleInteractive);

// 切换为观众角色
this.rtcEngine.setClientRole(AliRtcClientRole.AliRtcClientRoleLive);

相关文档