简介

实时音视频 SDK 是一套用于在 HarmonyOS 应用中快速集成实时音视频通话能力的 Native SDK。只需少量代码,即可实现语音通话、视频通话、直播连麦等场景,支持音频/视频采集、编码、传输、渲染,以及麦克风静音、摄像头切换、音量调节等常用能力。

SDK 基于 WebRTC 技术栈,接口设计与主流 RTC SDK 保持一致,集成简单、接入成本低,适合需要在自有应用中直接集成实时音视频能力的开发者。

快速集成

添加模块依赖

将 SDK 的 .har 包放入工程 libs 目录,在模块的 oh-package.json5 中添加依赖:

{
  "dependencies": {
    "TangRTCSDK": "file:./libs/TangRTCSDK.har"
  }
}

或者执行依赖安装:

ohpm install tangrtcsdk

配置权限

在应用 module.json5 中声明以下权限(按需添加):

权限

说明

使用场景

ohos.permission.INTERNET

网络访问

必须

ohos.permission.MICROPHONE

麦克风

音频通话

ohos.permission.CAMERA

摄像头

视频通话

ohos.permission.KEEP_BACKGROUND_RUNNING

后台运行

后台音频通话

建议在 abilities 中配置 backgroundModes,以支持后台音频:

"backgroundModes": ["audioRecording", "audioPlayback", "voip"]

导入 SDK

import {
  RtcEngine,
  RtcEngineConfig,
  ChannelMediaOptions,
  VideoCanvas,
  VideoEncoderConfiguration,
  Constants
} from 'TangRTCSDK'

典型调用流程

页面加载
  └── 创建 RtcEngineConfig(AppId、Context、事件回调)
  └── RtcEngine.create(config)
  └── enableAudio() / enableVideo()
  └── setVideoEncoderConfiguration()(视频场景)
用户点击「加入频道」
  └── 申请麦克风/摄像头权限
  └── 配置 ChannelMediaOptions
  └── joinChannelWithOptions(token, channelName, uid, options)
        └── onJoinChannelSuccess → 入会成功
        └── onUserJoined → 远端用户加入
  └── setupLocalVideo / setupRemoteVideo(视频场景)
用户点击「离开频道」
  └── stopPreview()(视频场景)
  └── leaveChannel()
  └── RtcEngine.destroy()

初始化 RtcEngine

在页面 aboutToAppear 中创建引擎实例,并注册事件回调:

import { common } from '@kit.AbilityKit'
import { RtcEngine, RtcEngineConfig, Constants } from 'TangRTCSDK'

private rtcEngine: RtcEngine | undefined = undefined

aboutToAppear(): void {
  let config = new RtcEngineConfig()
  let context = getContext(this) as common.UIAbilityContext

  config.mAppId = 'YOUR_APP_ID'          // 全时云控制台申请的 App ID
  config.mContext = context
  config.mEventHandler = {}

  // 入会成功
  config.mEventHandler.onJoinChannelSuccess = (channel: string, uid: number, elapsed: number) => {
    console.info(`加入频道成功,uid=${uid}`)
  }

  // 远端用户加入
  config.mEventHandler.onUserJoined = (uid: number, elapsed: number) => {
    console.info(`远端用户加入,uid=${uid}`)
  }

  // 远端用户离开
  config.mEventHandler.onUserOffline = (uid: number, reason: number) => {
    console.info(`远端用户离开,uid=${uid}`)
  }

  // 离开频道
  config.mEventHandler.onLeaveChannel = () => {
    console.info('已离开频道')
  }

  // 错误回调
  config.mEventHandler.onError = (err: number, message: string) => {
    console.error(`RTC 错误:${err} ${message}`)
  }

  this.rtcEngine = RtcEngine.create(config)
}

页面销毁时释放资源:

aboutToDisappear(): void {
  if (this.rtcEngine != undefined) {
    this.rtcEngine.leaveChannel()
    RtcEngine.destroy().then(() => {
      console.info('RtcEngine 已销毁')
    })
    this.rtcEngine = undefined
  }
}

加入音频频道

纯音频通话场景,只需开启音频模块,不发布摄像头轨道:

// 1. 开启音频
this.rtcEngine.enableAudio()

// 2. 配置频道参数
let mediaOption = new ChannelMediaOptions()
mediaOption.publishCameraTrack = false       // 不发布摄像头
mediaOption.publishMicrophoneTrack = true    // 发布麦克风
mediaOption.autoSubscribeVideo = false       // 不订阅远端视频
mediaOption.autoSubscribeAudio = true        // 订阅远端音频
mediaOption.channelProfile = Constants.ChannelProfile.COMMUNICATION
mediaOption.clientRoleType = Constants.ClientRole.BROADCASTER

// 3. 加入频道
let ret = this.rtcEngine.joinChannelWithOptions('', 'channelName', 0, mediaOption)
if (ret != Constants.ErrorCode.ERR_OK) {
  console.error('加入失败:' + RtcEngine.getErrorDescription(ret))
}

音频常用操作

// 静音/取消静音本地麦克风
this.rtcEngine.muteLocalAudioStream(true)   // 静音
this.rtcEngine.muteLocalAudioStream(false)  // 取消静音

// 调节音量(0~100)
this.rtcEngine.adjustPlaybackSignalVolume(80)   // 播放音量
this.rtcEngine.adjustRecordingSignalVolume(80)  // 采集音量

// 设置音频场景与音质
this.rtcEngine.setAudioScenario(Constants.AudioScenarioType.DEFAULT)
this.rtcEngine.setAudioProfile(Constants.AudioProfileType.DEFAULT)

// 耳返
this.rtcEngine.enableInEarMonitoring(true, 1)
this.rtcEngine.setInEarMonitoringVolume(50)
说明: HarmonyOS 暂不支持通过 SDK 直接切换音频输出设备,可通过系统 AVCastPicker 组件让用户选择音频路由。详见 鸿蒙音频设备切换指南

加入视频频道

视频通话场景,需要开启视频模块并绑定渲染视图:

// 1. 配置视频编码参数
let encoderConfig = new VideoEncoderConfiguration()
encoderConfig.dimensions = { width: 960, height: 540 }
encoderConfig.frameRate = 15
this.rtcEngine.setVideoEncoderConfiguration(encoderConfig)

// 2. 开启视频
this.rtcEngine.enableVideo()

// 3. 配置频道参数
let mediaOption = new ChannelMediaOptions()
mediaOption.autoSubscribeVideo = true
mediaOption.autoSubscribeAudio = true
mediaOption.channelProfile = Constants.ChannelProfile.LIVE_BROADCASTING
mediaOption.clientRoleType = Constants.ClientRole.BROADCASTER

// 4. 加入频道
let ret = this.rtcEngine.joinChannelWithOptions('', 'channelName', 0, mediaOption)

视频渲染(XComponent)

使用 XComponent 作为视频渲染容器,libraryname 必须设置为 Constants.TANG_LIB_NAME(即 "tangrtcsdk"):

// 本地视频预览
XComponent({
  id: 'preview_local',
  type: 'surface',
  libraryname: Constants.TANG_LIB_NAME
}).onLoad(() => {
  let canvas = new VideoCanvas('preview_local')
  canvas.uid = localUid
  canvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN
  this.rtcEngine?.setupLocalVideo(canvas)
})

// 远端视频渲染
XComponent({
  id: 'preview_remote',
  type: 'surface',
  libraryname: Constants.TANG_LIB_NAME
}).onLoad(() => {
  let canvas = new VideoCanvas('preview_remote')
  canvas.uid = remoteUid
  canvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN
  this.rtcEngine?.setupRemoteVideo(canvas)
})

视频常用操作

// 静音/取消静音本地音视频
this.rtcEngine.muteLocalAudioStream(true)
this.rtcEngine.muteLocalVideoStream(true)

// 静音/取消静音远端音视频
this.rtcEngine.muteRemoteAudioStream(remoteUid, true)
this.rtcEngine.muteRemoteVideoStream(remoteUid, true)

// 切换前后摄像头
this.rtcEngine.switchCamera()

// 开启/停止本地预览
this.rtcEngine.startPreview()
this.rtcEngine.stopPreview()

Token 鉴权入会

生产环境建议使用 Token 鉴权。Token 由业务服务端生成,客户端在入会时传入:

// 1. 注册 Token 相关回调
config.mEventHandler.onRequestToken = () => {
  // Token 无效,需向服务端重新申请
}

config.mEventHandler.onTokenPrivilegeWillExpire = (oldToken: string) => {
  // Token 即将过期,向服务端申请新 Token 后调用 renewToken
  // this.rtcEngine?.renewToken(newToken)
}

// 2. 使用 Token 加入频道
let mediaOption = new ChannelMediaOptions()
mediaOption.publishCameraTrack = true
mediaOption.publishMicrophoneTrack = true
mediaOption.autoSubscribeVideo = true
mediaOption.autoSubscribeAudio = true
mediaOption.channelProfile = Constants.ChannelProfile.LIVE_BROADCASTING
mediaOption.clientRoleType = Constants.ClientRole.BROADCASTER

let ret = this.rtcEngine.joinChannelWithOptions(token, channelName, 0, mediaOption)
this.rtcEngine.startPreview()

核心 API 说明

RtcEngine.create()

创建 RtcEngine 实例,全局只需创建一个实例。

RtcEngine.create(config: RtcEngineConfig): RtcEngine

参数

类型

说明

config

RtcEngineConfig

引擎配置,包含 AppId、Context、事件回调


RtcEngine.joinChannelWithOptions()

加入频道。

joinChannelWithOptions(
  token: string,
  channelId: string,
  uid: number,
  options: ChannelMediaOptions
): number

参数

类型

说明

token

string

鉴权 Token,测试环境可传空字符串

channelId

string

频道名

uid

number

用户 ID,传 0 由 SDK 自动分配

options

ChannelMediaOptions

频道媒体选项

返回值:Constants.ErrorCode.ERR_OK(0)表示成功,其他值为错误码,可通过 RtcEngine.getErrorDescription(code) 获取描述。


RtcEngine.leaveChannel()

离开当前频道。

leaveChannel(): number

RtcEngine.destroy()

销毁 RtcEngine 实例,释放所有资源。销毁后如需再次使用须重新调用 create()

RtcEngine.destroy(): Promise<void>

RtcEngineConfig 参数说明

字段

类型

说明

mAppId

string

应用 ID,在全时云控制台申请

mContext

Context

应用上下文,通常为 UIAbilityContext

mEventHandler

IRtcEngineEventHandler

事件回调接口

mLogConfig

LogConfig

可选,日志配置

areaCode

Constants.AreaCode

可选,区域码,默认 GLOB

ChannelMediaOptions 常用参数

字段

类型

默认值

说明

publishCameraTrack

boolean

true

是否发布摄像头视频

publishMicrophoneTrack

boolean

true

是否发布麦克风音频

autoSubscribeAudio

boolean

true

是否自动订阅远端音频

autoSubscribeVideo

boolean

true

是否自动订阅远端视频

channelProfile

number

频道场景,见下表

clientRoleType

number

用户角色,见下表

channelProfile 取值:

说明

Constants.ChannelProfile.COMMUNICATION (0)

通信模式,适用于 1v1 或小组通话

Constants.ChannelProfile.LIVE_BROADCASTING (1)

直播模式,区分主播与观众

clientRoleType 取值:

说明

Constants.ClientRole.BROADCASTER (1)

主播,可发送和接收流

Constants.ClientRole.AUDIENCE (2)

观众,仅接收流

常用事件回调

回调

说明

onJoinChannelSuccess

成功加入频道

onLeaveChannel

离开频道

onUserJoined

远端用户加入

onUserOffline

远端用户离开

onError

发生错误

onConnectionStateChanged

连接状态变化

onRequestToken

Token 无效,需重新申请

onTokenPrivilegeWillExpire

Token 即将过期

onAudioVolumeIndication

说话者音量提示

onRemoteVideoStateChanged

远端视频状态变化

onRemoteAudioStateChanged

远端音频状态变化