LiveKit定制WebRTC音视频模块
| Files | Last commit | Last update |
|---|---|---|
| 28 days ago | ||
| 19 days ago | ||
| 19 days ago | ||
| 20 days ago | ||
| 28 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 28 days ago | ||
| 20 days ago | ||
| 1 month ago | ||
| 19 days ago | ||
| 19 days ago | ||
| 1 month ago | ||
| 19 days ago | ||
| 1 month ago |
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() | MediaStreamConstraints | Promise<MediaStream> | 申请麦克风、相机权限并采集本地媒体流。 |
mediaDevices.getDisplayMedia() | DisplayMediaStreamConstraints | Promise<MediaStream> | 采集屏幕内容并返回媒体流。 |
RTCPeerConnection | RTCConfiguration | 类 | 创建对等连接,管理 SDP、ICE、轨道、发送端、接收端和数据通道。 |
RTCIceCandidate | RTCIceCandidateInit | 类 | 表示 ICE candidate,可与信令服务交互。 |
RTCSessionDescription | RTCSessionDescriptionInit | 类 | 表示 offer / answer 等 SDP 描述。 |
RTCView | RTCVideoViewProps | React 组件 | 渲染本地或远端媒体流视频画面。 |
RTCPIPView | RTCVideoViewProps | React 组件 | 承载画中画相关视频视图。 |
ScreenCapturePickerView | 组件属性 | React 组件 | 承载屏幕捕获选择入口。 |
RTCDataChannel | 由 createDataChannel 创建 | 对象 | 提供点对点数据通道发送、接收和状态事件。 |
RTCRtpSender / RTCRtpReceiver / RTCRtpTransceiver | 由 PeerConnection 创建或返回 | 对象 | 管理 RTP 发送、接收和收发方向。 |
RTCFrameCryptor / RTCFrameCryptorFactory | participantId、sender / receiver、algorithm、keyProvider | 对象 / 工厂 | 创建并控制音视频帧端到端加密。 |
RTCDataPacketCryptor / RTCDataPacketCryptorFactory | algorithm、keyProvider 等 | 对象 / 工厂 | 提供数据包加密和解密能力。 |
RTCKeyProvider | 密钥配置与参与者标识 | 对象 | 管理 E2EE 密钥、ratchet 与共享密钥。 |
registerGlobals() | 无 | void | 向全局对象挂载 WebRTC 构造器和 navigator.mediaDevices。 |
startIOSPIP() / stopIOSPIP() | viewTag | Promise<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 协议一致。请自由地享受和参与开源。