livekit-react-native-webrtc:基于 React Native 鸿蒙生态的 WebRTC 音视频能力库项目

LiveKit定制WebRTC音视频模块

Branch3Tags5

livekit-react-native-webrtc

本项目基于 livekit/react-native-webrtc 开发。如果在使用过程中有任何问题,可以在 GitCode 提交 Issue,会及时跟进。

项目介绍

livekit-react-native-webrtc(npm 适配包版本 144.0.2,为上游基线 @livekit/react-native-webrtc@144.0.0 之上的鸿蒙修复版)是面向 HarmonyOS/OpenHarmony React Native 工程的 WebRTC 音视频能力库,适用于实时音视频通话、会议、直播连麦、屏幕共享、数据通道通信、视频渲染、画中画和端到端加密等业务场景。

鸿蒙侧以 RNOH TurboModule、Fabric 组件与 ArkTS HAR 形式提供。npm 包名为 @hxa-rn/react-native-webrtc,HAR 内的 ohpm 模块名为 @oh-rn/react-native-webrtc,JS/TS 使用者仍通过 @livekit/react-native-webrtc 导入。调用方通过 mediaDevices、RTCPeerConnection、RTCView、RTCPIPView、RTCDataChannel、RTCFrameCryptor 和 registerGlobals() 完成媒体采集、连接协商、数据传输、视频渲染、画中画和加密链路。

核心能力包括:

  • 媒体采集:支持设备枚举、摄像头/麦克风权限申请、本地音视频采集和屏幕内容捕获。
  • 对等连接:支持 RTCPeerConnection、SDP、ICE、轨道添加移除、收发器、统计查询和连接状态事件。
  • 数据通道:支持 RTCDataChannel 的文本、二进制消息收发和状态回调。
  • 视频渲染:支持 RTCView、RTCPIPView、ScreenCapturePickerView、尺寸回调、镜像、填充模式和画中画入口。
  • 端到端加密:支持 RTCKeyProvider、RTCDataPacketCryptor、RTCFrameCryptor 等数据侧与帧侧加密能力。
  • 全局注册与宿主扩展:支持 registerGlobals()、音频会话入口、日志开关和宿主侧 WebRTC 扩展配置。

集成指南

1. 安装 JS 依赖

npm install @hxa-rn/react-native-webrtc@144.0.3 --save-exact

安装后本包位于 node_modules/@hxa-rn/react-native-webrtc/,并携带已构建的 harmony/webrtc.har 与 engine/dist/ohos-webrtc-1.0.2-e2ee.2.har。安装过程不会在使用者机器上重新编译原生库。JS 侧仍按原库名导入 @livekit/react-native-webrtc,由包内 harmony.alias 映射到鸿蒙适配包。

2. 生成鸿蒙侧 JS Bundle

需要生成宿主 React Native 应用在鸿蒙侧加载的 JS bundle。文件名以宿主工程的 RNApp 配置为准,下面示例使用 index.bundle:

npx react-native bundle-harmony --dev false \
  --bundle-output harmony/entry/src/main/resources/rawfile/index.bundle \
  --assets-dest harmony/entry/src/main/resources/rawfile

@oh-rn/react-native-webrtc 是 HAR 内的鸿蒙模块名,JS 业务代码继续使用 @livekit/react-native-webrtc。原生侧的链接与 Package 注册见第 4 步,同一个 Package 只能注册一次。

3. 接入鸿蒙原生依赖

在宿主鸿蒙工程根目录的 harmony/oh-package.json5(需要落到与 OH_MODULES_DIR 一致的 harmony/oh_modules)中加入。overrides 指向宿主正在使用的 RNOH HAR,下例为 RNOH 官方预编译包,与本仓示例相同:

{
  dependencies: {
    "@oh-rn/react-native-webrtc": "file:../node_modules/@hxa-rn/react-native-webrtc/harmony/webrtc.har",
    "@ohos/webrtc": "file:../node_modules/@hxa-rn/react-native-webrtc/engine/dist/ohos-webrtc-1.0.2-e2ee.2.har",
  },
  overrides: {
    // 必须与宿主 RNOH har 保持一致:覆盖 webrtc.har 内部指向
    "@rnoh/react-native-openharmony": "file:../node_modules/@react-native-oh/react-native-harmony/react_native_openharmony_release.har",
    // webrtc.har 声明依赖 @ohos/webrtc 1.0.2;指向包内自带的 E2EE 引擎 HAR,否则会从 ohpm 公仓拉取不含本库 E2EE 能力的官方引擎
    "@ohos/webrtc": "file:../node_modules/@hxa-rn/react-native-webrtc/engine/dist/ohos-webrtc-1.0.2-e2ee.2.har",
  },
}

如果宿主工程模板要求 harmony/entry/oh-package.json5 显式声明,也可在该文件中使用同一 HAR 路径(相对路径多一层,写 file:../../node_modules/...);两处指向的 HAR 需保持一致。

在宿主 RN 工程根目录执行:

cd harmony
ohpm install

如果 ohpm install --all 长时间无输出,可用 ohpm install --all --fetch_timeout 10000 --retry_times 0 --log_level debug 观察依赖解析进度。Windows 下工程根目录的完整路径建议不超过 40 个字符,否则原生构建的中间文件路径可能超过系统上限。

4. 链接并注册 Package(C++ 与 ETS)

本库含 C++ 代码:C++ 侧要链接库并注册 Package,ETS 侧也要注册 Package,每一侧只注册一次。宿主启用 Autolink(harmony/hvigorfile.ts 中 createRNOHModulePlugin 配了 autolinking: {})时,插件会生成 autolinking.cmake 和已含 WebrtcPackage 的 RNOHPackagesFactory(.h / .ets);宿主若已在 PackageProvider.cpp、RNPackagesFactory.ets 中使用这两个生成列表,就不要再按下面 ②③ 手写 WebrtcPackage。

本仓 example 的做法(可对照 example/harmony/entry/src/main/cpp/ 与 example/harmony/entry/src/main/ets/RNPackagesFactory.ets):保留 autolinking: {},C++ 库由生成的 autolinking.cmake 链接;Package 按下面 ②③ 手写,各注册一次,不使用生成的 RNOHPackagesFactory。

① 链接 C++ 库(harmony/entry/src/main/cpp/CMakeLists.txt):启用 Autolink 时保留模板中的 include("${CMAKE_CURRENT_SOURCE_DIR}/autolinking.cmake") 和 autolink_libraries(rnoh_app);未启用 Autolink 时改为手动添加:

add_subdirectory("${OH_MODULES_DIR}/@oh-rn/react-native-webrtc/src/main/cpp" ./webrtc)
target_link_libraries(rnoh_app PUBLIC webrtc)

OH_MODULES_DIR 指向 harmony/oh_modules(本仓示例 CMakeLists 中为 ${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules)。

② 注册 C++ Package(harmony/entry/src/main/cpp/PackageProvider.cpp):

#include "RNOH/PackageProvider.h"
#include "WebrtcPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx)
{
    return {
        std::make_shared<WebrtcPackage>(ctx),
        // ...保留宿主已有的其他 Package
    };
}

③ 注册 ETS Package(harmony/entry/src/main/ets/RNPackagesFactory.ets):

import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
import { WebrtcPackage } from '@oh-rn/react-native-webrtc';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new WebrtcPackage(ctx),
    // ...保留宿主已有的其他 Package
  ];
}

宿主页面接线:RTCView / RTCPIPView 与 ScreenCapturePickerView 由本库的 ArkTS 组件 RTCVideoView、ScreenCapturePickerView 渲染。请在宿主创建 RNApp 的页面(RNOH 工程模板为 harmony/entry/src/main/ets/pages/Index.ets)补齐以下三处,否则视频画面不挂载(与本仓示例相同):

import { RTCVideoView, ScreenCapturePickerView } from '@oh-rn/react-native-webrtc';

const arkTsComponentNames: string[] = [RTCVideoView.NAME, ScreenCapturePickerView.NAME];

@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
  // 保留宿主已有的分支,追加:
  Stack() {
    if (ctx.componentName === RTCVideoView.NAME) {
      RTCVideoView({ ctx: ctx.rnComponentContext, tag: ctx.tag })
    } else if (ctx.componentName === ScreenCapturePickerView.NAME) {
      ScreenCapturePickerView({ ctx: ctx.rnComponentContext, tag: ctx.tag })
    }
  }
  .position({ x: 0, y: 0 })
}

const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent)

// RNApp 参数中:
RNApp({
  rnInstanceConfig: {
    createRNPackages,
    enableCAPIArchitecture: true,
    arkTsComponentNames: arkTsComponentNames,
    // ...保留宿主原有配置
  },
  wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
  // ...保留宿主原有参数
})

5. 接入 WebRTC 宿主配置(可选)

如果业务需要默认远端音轨音量、日志注入、编解码工厂或音频处理扩展,可在创建 RN 实例前设置 WebRTCModuleOptions。未使用这些扩展时可以跳过本步骤,库会按默认 WebRTC 引擎能力运行:

import {
  WebRTCModuleOptions,
  setWebRTCDebugLogEnabled,
} from '@oh-rn/react-native-webrtc';

WebRTCModuleOptions.getInstance().defaultTrackVolume = 1.0;
setWebRTCDebugLogEnabled(true);

接入后即可在 JS/TS 代码中按原库名导入:

import { mediaDevices, RTCPeerConnection, RTCView } from '@livekit/react-native-webrtc';

6. 检查鸿蒙 SDK 版本

webrtc.har 面向 RNOH 工程使用。确认宿主 harmony/build-profile.json5 的 runtimeOS 为 HarmonyOS,并保证 compatibleSdkVersion、targetSdkVersion 与宿主 RNOH 版本要求一致;npm 包 144.0.2 内的 webrtc.har 声明 compatibleSdkVersion 13,需要宿主工程提供相匹配的 HarmonyOS SDK 与 RNOH 运行环境。

7. 编译、安装、启动

# DevEco Studio 打开 harmony/ 工程,等待后台任务完成
# File > Project Structure > Signing Configs 勾选自动签名
# 选 entry 运行配置,连接设备,Debug/Run

# 或命令行:
hvigorw --mode module -p module=entry@default -p product=default -p buildMode=release assembleHap

# 产物:harmony/entry/build/default/outputs/default/entry-default-signed.hap

# 装机与启动(设备已连接,hdc 可见设备):
hdc file send entry-default-signed.hap /data/local/tmp/entry.hap
hdc shell bm install -p /data/local/tmp/entry.hap
hdc shell aa start -a EntryAbility -b <你的 bundleName>   # 见 AppScope/app.json5

使用说明

初始化全局 WebRTC API

import {
  mediaDevices,
  RTCPeerConnection,
  RTCView,
  RTCFrameCryptorFactory,
  RTCKeyProvider,
  registerGlobals
} from '@livekit/react-native-webrtc';

registerGlobals();

枚举设备并采集媒体流

const devices = await mediaDevices.enumerateDevices();

const stream = await mediaDevices.getUserMedia({
  audio: true,
  video: {
    facingMode: 'user',
    width: 1280,
    height: 720,
    frameRate: 30
  }
});

创建 PeerConnection 并添加轨道

const pc = new RTCPeerConnection({
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' }
  ]
});

stream.getTracks().forEach(track => {
  pc.addTrack(track, stream);
});

pc.onicecandidate = event => {
  if (event.candidate) {
    // 将 candidate 发送给对端信令服务
  }
};

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

渲染本地或远端视频

export function VideoTile({ streamURL }: { streamURL: string }) {
  return (
    <RTCView
      streamURL={streamURL}
      objectFit="cover"
      mirror={true}
      style={{ width: 160, height: 240 }}
    />
  );
}

使用数据通道

const channel = pc.createDataChannel('chat');

channel.onopen = () => {
  channel.send('hello harmony');
};

channel.onmessage = event => {
  console.info(`message: ${event.data}`);
};

启用端到端加密能力

const keyProvider = new RTCKeyProvider();
const frameCryptor = RTCFrameCryptorFactory.createFrameCryptorForRtpSender(
  'participant-id',
  sender,
  0,
  keyProvider
);

await frameCryptor.setEnabled(true);

使用画中画入口

import { startIOSPIP, stopIOSPIP } from '@livekit/react-native-webrtc';

await startIOSPIP(viewTag);
await stopIOSPIP(viewTag);

鸿蒙侧保留 JS 名称 startIOSPIP / stopIOSPIP 以兼容上游调用,底层映射到鸿蒙画中画能力。

接口文档

接口参数 / 构造返回值 / 类型说明
mediaDevices.enumerateDevices()无Promise<MediaDeviceInfo[]>枚举音频输入、视频输入等媒体设备。
mediaDevices.getUserMedia()MediaStreamConstraintsPromise<MediaStream>申请麦克风、相机权限并采集本地媒体流。
mediaDevices.getDisplayMedia()DisplayMediaStreamConstraintsPromise<MediaStream>采集屏幕内容并返回媒体流。
RTCPeerConnectionRTCConfiguration类创建对等连接,管理 SDP、ICE、轨道、发送端、接收端和数据通道。
RTCIceCandidateRTCIceCandidateInit类表示 ICE candidate,可与信令服务交互。
RTCSessionDescriptionRTCSessionDescriptionInit类表示 offer / answer 等 SDP 描述。
RTCViewRTCVideoViewPropsReact 组件渲染本地或远端媒体流视频画面。
RTCPIPViewRTCVideoViewPropsReact 组件承载画中画相关视频视图。
ScreenCapturePickerView组件属性React 组件承载屏幕捕获选择入口。
RTCDataChannel由 createDataChannel 创建对象提供点对点数据通道发送、接收和状态事件。
RTCRtpSender / RTCRtpReceiver / RTCRtpTransceiver由 PeerConnection 创建或返回对象管理 RTP 发送、接收和收发方向。
RTCFrameCryptor / RTCFrameCryptorFactoryparticipantId、sender / receiver、algorithm、keyProvider对象 / 工厂创建并控制音视频帧端到端加密。
RTCDataPacketCryptor / RTCDataPacketCryptorFactoryalgorithm、keyProvider 等对象 / 工厂提供数据包加密和解密能力。
RTCKeyProvider密钥配置与参与者标识对象管理 E2EE 密钥、ratchet 与共享密钥。
registerGlobals()无void向全局对象挂载 WebRTC 构造器和 navigator.mediaDevices。
startIOSPIP() / stopIOSPIP()viewTagPromise<boolean>兼容上游 JS 名称,鸿蒙侧映射到画中画启停能力。
permissions权限类型对象封装媒体权限查询与申请能力。
WebRTCModuleOptions宿主侧原生扩展配置ArkTS 对象在 RN 实例创建前配置编解码、音频处理、日志和默认音量等扩展项。

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 20(示例工程 engines 要求)
DevEco Studio 含 HarmonyOS SDK 6.0.1(21) 及以上的版本
HarmonyOS SDK API 13+(example/harmony 的 compatibleSdkVersion 为 5.0.1(13))
路径 Windows 下仓库根目录的完整路径不超过 40 个字符,否则原生构建的中间文件路径会超过系统上限

运行步骤

1. 克隆仓库

git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/livekit-react-native-webrtc.git
cd livekit-react-native-webrtc

Windows 下可在克隆时指定短目录名,例如 git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/livekit-react-native-webrtc.git C:\rwrtc。

2. 进入 example 目录,安装依赖

cd example
npm install --legacy-peer-deps

Example 从 npm 公仓安装 @hxa-rn/react-native-webrtc@144.0.3,不需要在仓根执行 npm pack。

3. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

4. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio,选择 example/harmony 目录
  • 首次构建请在 File → Project Structure → Signing Configs 勾选 Automatically generate signature,Apply 后 Sync
  • 等待 Sync 完成

5. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备。

example_auto(自动化用例工程)步骤相同,把 example 换成 example_auto 即可,两者的依赖与构建输出相互独立。

注意:Example 已预置 Package 注册、Metro alias 与 HAR 依赖,无需手动 Link。编 HAP 前必须先执行 npm run dev;改过 JS 后重新执行再运行。Example 已声明网络、相机、麦克风权限,点击「申请权限」或首次采集时会弹出系统授权框;业务若使用相机、麦克风或屏幕采集,还需在宿主工程中按场景配置并申请相应权限。

约束与限制

兼容性

项 版本 / 说明
React Native >=0.72,鸿蒙适配包 peer dependency 为 react-native >=0.72
RNOH 0.72.143,宿主工程应使用同一版本的 @react-native-oh/react-native-harmony 与 @rnoh/react-native-openharmony
Node.js >=18
WebRTC 引擎 @ohos/webrtc 1.0.2,配套使用本库自建 E2EE 引擎
原生依赖 宿主无需另行引入原生库;WebRTC 引擎 HAR(ohos-webrtc-1.0.2-e2ee.2.har)的 libohos_webrtc.so 已静态内置所需原生库(含 libevent)
鸿蒙 SDK 以宿主 RNOH 工程为准;webrtc.har 声明 compatibleSdkVersion 13;随库示例工程为 compatibleSdkVersion 5.0.1(13),targetSdkVersion 6.0.1(21)
工程模型 React Native + RNOH 工程,鸿蒙侧通过 ArkTS HAR、TurboModule 和 Fabric 组件接入
支持设备类型 鸿蒙模块声明 default、tablet、2in1
上游形态 React Native WebRTC JS API + Android / iOS 原生 WebRTC 实现
鸿蒙侧形态 RNOH TurboModule、Fabric 组件、ArkTS HAR、HarmonyOS WebRTC/媒体能力映射

权限

本库会根据使用场景依赖 ohos.permission.CAMERA、ohos.permission.MICROPHONE 和 ohos.permission.INTERNET。需要媒体采集时,宿主应用应声明并在业务触发点申请相机和麦克风权限;需要信令、ICE、TURN/STUN 或业务网络时应具备网络访问能力。屏幕采集和画中画能力还受系统能力、用户授权和设备形态限制。库本身不保存业务音视频内容,实际上传、录制或转发行为由调用方业务链路决定。

功能约束

  • RNOH 手动接入:需要在宿主鸿蒙工程中注册 WebrtcPackage,并确保 @rnoh/react-native-openharmony 覆盖到宿主实际使用的 HAR。
  • 媒体权限由业务触发:getUserMedia、getDisplayMedia 等能力可能弹出系统授权,调用方应在用户明确触发后调用,并处理拒绝授权分支。
  • 设备能力差异:摄像头朝向、设备标签、屏幕捕获、画中画和硬件编解码能力受不同设备与系统版本影响,调用方应根据返回值和异常做兜底。
  • 信令服务不在库内:本库提供 WebRTC 客户端能力,不内置房间、信令、TURN/STUN 服务;业务需要自行接入信令和服务器配置。
  • 画中画名称兼容:JS 层保留上游 startIOSPIP / stopIOSPIP 命名,鸿蒙底层映射到 HarmonyOS 画中画能力。
  • 端到端加密接入成本较高:E2EE 需要调用方管理参与者标识、密钥、ratchet 与启停状态,建议在业务层统一封装。

开源 License

本项目基于 MIT License 开源,与上游 livekit/react-native-webrtc 协议一致。请自由地享受和参与开源。

问题反馈渠道

使用过程中发现任何问题,欢迎提交 Issue,也欢迎提交 PR 参与共建。

Introduction

LiveKit定制WebRTC音视频模块

Customize your domain