npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hxa-rn/react-native-webrtc

v1.0.0

Published

WebRTC for React Native — HarmonyOS (OpenHarmony) adaptation of @livekit/react-native-webrtc

Readme

@hxa-rn/react-native-webrtc for HarmonyOS

本项目基于 @livekit/react-native-webrtc 开发,为 React Native 鸿蒙(OpenHarmony)适配版本。

版本对应关系

| 鸿蒙适配包版本 | 原始库版本 | 支持 RN 版本 | Autolink | 编译 API 版本 | | ------------ | ---------- | ------------ | -------- | ------------- | | 1.0.0 | 144.0.0 | 0.72+ | 是 | API12+ |

最低 HarmonyOS API 版本:12。HAR 在 oh-package.json5 中以 compatibleSdkVersion: 12 声明。 底线由实际调用的接口决定:Crypto Architecture Kit 的 HKDFSpec(API 12+,数据通道 E2EE 用)、 PiPWindow.create(config, contentNode)(API 12+,画中画用),以及原生引擎 @ohos/webrtc 自身的基线。 npm 包使用独立的鸿蒙适配版本号;本版 1.0.0 对应上游 @livekit/[email protected]。HAR 内的 ohpm 模块版本仍保留为 144.0.0,便于追踪上游基线。

原生依赖:本 HAR 依赖 ohpm 官方仓的 WebRTC 引擎 @ohos/webrtc(Apache-2.0), 已写入 harmony/webrtc/oh-package.json5 的 dependencies,宿主工程 ohpm install 会自动拉取。 引擎基线为 libwebrtc M120;上游库标称 M144。差异体现在编解码器集合与个别新接口上, 能力域本身不受影响 —— 编解码能力请以 RTCRtpSender.getCapabilities() 的实际返回为准,不要硬编码。

🔴 媒体帧级 E2EE 需要「增补引擎 HAR」,官方引擎给不了:官方 @ohos/webrtc 的 NAPI 层没有把 libwebrtc 的帧变换器挂接点引出来(随包 webrtc.d.ts 全文检索 framecryptor|insertable|encodedstream|keyprovider|cryptor|transform 零命中), 因此 frameCryptor* 6 个方法 + keyProviderSetSifTrailer 在官方引擎上无法工作。 本仓在同一基线(@ohos/[email protected] 对应提交 306d400f)上补齐了这层 NAPI 绑定并重建引擎, 以分叉 HAR 形式分发(ohos-webrtc-<基线>-e2ee.<n>.har),宿主通过 overrides 接入 —— 见 Link 章「步骤 1. Overrides」。 不接入也能用:除帧侧那 7 个方法外的全部能力(含数据通道 E2EE)在官方引擎上完整可用。 引擎说明与分发脚本见 engine/README.md 和 scripts/README-webrtc-packaging.md。

安装

npm install @hxa-rn/[email protected] --save-exact

使用

import { useEffect, useState } from 'react';
import { Button, StyleSheet, View } from 'react-native';
import {
  mediaDevices,
  permissions,
  RTCView,
  type MediaStream,
} from '@livekit/react-native-webrtc';

const styles = StyleSheet.create({ fill: { flex: 1 } });

export default function LocalPreview() {
  const [stream, setStream] = useState<MediaStream | null>(null);

  // 1) 权限:camera / microphone 均为 user_grant,未授权时会弹系统弹窗
  const start = async () => {
    await permissions.request({ name: 'camera' });

    // 2) 设备枚举:videoinput / audioinput / audiooutput
    const devices = await mediaDevices.enumerateDevices();
    console.log(devices);

    // 3) 本地采集:返回的轨道此时已经真实在采集
    const s = await mediaDevices.getUserMedia({
      audio: true,
      video: { width: 1280, height: 720, facingMode: 'user' },
    });

    setStream(s as MediaStream);
  };

  useEffect(() => () => stream?.release(), [stream]);

  return (
    <View style={styles.fill}>
      <Button title="开始采集" onPress={start} />
      {/* 4) 预览:streamURL 取 stream.toURL() */}
      <RTCView
        style={styles.fill}
        streamURL={stream ? stream.toURL() : ''}
        mirror
        objectFit="cover"
        onDimensionsChange={e => console.log(e.nativeEvent)}
      />
      {/* 5) 轨道控制 */}
      <Button
        title="切换前后置"
        onPress={() => stream?.getVideoTracks()[0]?._switchCamera()}
      />
    </View>
  );
}

JS/TS import 继续使用原库名 '@livekit/react-native-webrtc',而不是 npm 包名 @hxa-rn/react-native-webrtc 或 ohpm 模块名 @oh-rn/react-native-webrtc(由 RNOH alias 映射)。

平台差异:

  • 本适配提供完整的端到端通话能力:对等连接与协商、收发管线、数据通道、媒体设备枚举与采集、 屏幕内容捕获、视频渲染、画中画,底层为 ohpm 上的 @ohos/webrtc 引擎。
  • 数据通道端到端加密(KeyProvider + DataPacketCryptor,12 个方法) 由本适配基于 Crypto Architecture Kit 自建(AES-256-GCM + HKDF/PBKDF2 棘轮,纯软件、免额外权限)。
  • 媒体帧级端到端加密(FrameCryptor,7 个方法)需接入增补引擎 HAR:官方 @ohos/webrtc 的 NAPI 层 未暴露编码后 / 解码前的帧管线挂接点,在它之上这 7 个方法无法工作;接入本仓的增补引擎(Link 步骤 1 的 override ②)后完整可用,密文线格式与 LiveKit 生态逐字节一致。详见「未实现功能」末尾说明。
  • ScreenCapturePickerView 在鸿蒙无对应物(渲染为零内容占位);屏幕共享本身可用, 直接调用 mediaDevices.getDisplayMedia() 即可,系统会弹出自己的捕获确认。
  • mediaDevices.ondevicechange 由 Audio Kit 的路由变化与引擎设备变化共同驱动。
  • track.applyConstraints() / track._switchCamera() 通过「按新约束重新采集 + 换到所有 sender 与所属 MediaStream」实现,JS 侧 track.id 保持不变、无需重协商。

权限要求:

  • 需在应用 entry/src/main/module.json5 声明 ohos.permission.CAMERA 与 ohos.permission.MICROPHONE(二者均为 user_grant,usedScene.when 建议 inuse),并配置对应的 reason 字符串资源。
  • 运行时由 permissions.request({ name }) 触发 abilityAccessCtrl.requestPermissionsFromUser 动态申请;getUserMedia() 内部也会先申请再采集。已授权时不再弹窗。

Link

| 版本 | 是否支持 Autolink | |------|------------------| | 1.0.0 | 是 |

本包随附 harmony/webrtc.har 与 Autolinking 元数据。Autolink 与下面的 Manual Link 必须二选一;本仓示例保留 autolinking: {},由 RNOH 插件生成 CMake 链接配置。

说明:本模块需要同时在 C++ 侧和 ETS 侧注册 Package。

1. Overrides(必需):RN SDK + WebRTC 引擎

本 HAR 的 oh-package.json5 把 @rnoh/react-native-openharmony 声明为 file:../react_native_openharmony_release.har——那是本库构建工程内的相对路径,在宿主工程里不可解析。因此消费方必须在工程根目录 oh-package.json5 的 overrides 中把它指向自己的 RNOH HAR,否则 ohpm install 会解析失败:

{
  "overrides": {
    // ① 必需:指向宿主工程实际使用的 RNOH HAR,路径按自己的工程结构调整
    "@rnoh/react-native-openharmony": "file:../node_modules/@react-native-oh/react-native-harmony/react_native_openharmony.har",

    // ② 仅当需要**媒体帧级 E2EE**(frameCryptor* / keyProviderSetSifTrailer)时加这一行:
    //    把 WebRTC 引擎重定向到本仓的增补引擎 HAR(官方引擎没引出帧变换器挂接点,见文首说明)。
    //    ⚠️ 文件名必须带版本号——`file:` 依赖的 HAR 换了内容却不换文件名时,宿主会用**陈旧缓存**(rn 分册坑 RK-13)。
    "@ohos/webrtc": "file:./libs/ohos-webrtc-1.0.2-e2ee.1.har"
  }
}

若 RNOH 以源码目录形式接入,则写成目录路径(例如 "./react_native_openharmony")。

②接入后的自检(两项同核,缺一不可)——ohpm install 之后:

# a. 引擎实现在位:须 11,286,064 B
#    (官方版 = 10,691,296 B〔1.0.2〕/ 11,150,120 B〔1.0.3〕,读到这两个数说明 override 没生效)
ls -l oh_modules/.ohpm/@ohos+webrtc*/oh_modules/@ohos/webrtc/libs/arm64-v8a/libohos_webrtc.so

# b. 类型声明在位:官方 = 0,接入增补引擎后 > 0
#    ⚠️ 探针必须用 FrameCryptor,不能用 onstatechange —— 官方 d.ts 本来就有 3 个 onstatechange
#       (RTCDtlsTransport / RTCIceTransport / RTCSctpTransport 各一),拿它当探针区分不出来
grep -c FrameCryptor oh_modules/.ohpm/@ohos+webrtc*/oh_modules/@ohos/webrtc/src/main/libohos_webrtc/webrtc.d.ts

# c. 采集启停声明在位:官方基线可能缺失,接入增补引擎后必须命中
grep -c "startCapture(): void" oh_modules/.ohpm/@ohos+webrtc*/oh_modules/@ohos/webrtc/src/main/libohos_webrtc/webrtc.d.ts

三项必须同时满足:只有 a 会编译报错(声明缺失),只有 b 则编译通过但真机上帧侧 E2EE 静默失效,没有任何编译期信号。

增补引擎 HAR 怎么来:由本仓 engine/pack-engine-har.js 从官方基线包打出 ——

curl -sSL -o webrtc-1.0.2.har https://ohpm.openharmony.cn/ohpm/@ohos/webrtc/-/webrtc-1.0.2.har
sha256sum webrtc-1.0.2.har   # 须 = a1f0e71a3d0462fcdfb835397b178fd91fb55bc4f445d2e72796c155e3a1b6b6
node engine/pack-engine-har.js --base webrtc-1.0.2.har --tag 1
# → engine/dist/ohos-webrtc-1.0.2-e2ee.1.har(不入仓)

基线取 1.0.2 而非 1.0.3 有实测依据(门面能力须 ≤ .so 能力;且 1.0.3 起官方包不再带 libc++_shared.so,而自建 .so DT_NEEDED 它)——见 scripts/README-webrtc-packaging.md; 引擎本身的由来见 engine/README.md。 当前 demo / auto 已改为 npm install 准备本地 harmony/webrtc.har 与 engine/dist/ohos-webrtc-1.0.2-e2ee.1.har, DevEco 编译时通过 file: 依赖直接安装补丁版 @ohos/webrtc。如果本机残留旧 oh_modules,先清理后重新执行 npm install / DevEco Sync。

2. 引入原生端依赖

打开 entry/oh-package.json5,添加:

"dependencies": {
  "@oh-rn/react-native-webrtc": "file:../../node_modules/@hxa-rn/react-native-webrtc/harmony/webrtc.har"
}

执行 ohpm install。

3. 配置 CMakeLists

打开 entry/src/main/cpp/CMakeLists.txt,添加:

set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")

add_subdirectory("${OH_MODULES}/@oh-rn/react-native-webrtc/src/main/cpp" ./webrtc)

target_link_libraries(rnoh_app PUBLIC webrtc)

4. 注册 Package(C++ 侧)

打开 entry/src/main/cpp/PackageProvider.cpp,添加:

#include "WebrtcPackage.h"

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<WebrtcPackage>(ctx),
    };
}

5. 注册 Package(ETS 侧)

打开 entry/src/main/ets/RNPackagesFactory.ets,添加:

import { WebrtcPackage } from '@oh-rn/react-native-webrtc/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new WebrtcPackage(ctx),
  ];
}

属性 / API

| API | 描述 | 参数 | 返回值 | HarmonyOS 支持 | |-----|------|------|--------|----------------| | permissions.query | 查询 camera / microphone 权限态 | { name: 'camera' \| 'microphone' } | Promise<'granted' \| 'prompt'> | 支持(鸿蒙无法区分「未申请」与「已拒绝」,未授权统一为 prompt) | | permissions.request | 申请权限(已授权不弹窗) | { name } | Promise<boolean> | 完全支持 | | mediaDevices.enumerateDevices | 枚举摄像头 / 音频输入输出设备;每项 deviceId / kind / label / groupId,videoinput 项另带 facing('front' / 'environment' / 'unknown',同上游) | 无 | Promise<MediaDeviceInfo[]> | 完全支持 | | mediaDevices.getUserMedia | 打开摄像头 / 麦克风并返回媒体流 | constraints: { audio?, video? } | Promise<MediaStream> | 完全支持 | | mediaDevices.getDisplayMedia | 屏幕内容捕获(实时帧流,非录制落盘) | 无 | Promise<MediaStream> | 完全支持(无需 ohos.permission.CAPTURE_SCREEN) | | mediaDevices.ondevicechange | 设备变化事件 | (event) => void | — | 支持 | | MediaStream 容器操作 | new / addTrack / removeTrack / getTracks / getTrackById / toURL / active / release | 见原库 | 见原库 | 完全支持 | | MediaStreamTrack.enabled / stop() / release() | 启停与释放轨道 | 见原库 | 见原库 | 完全支持 | | MediaStreamTrack.getSettings() / getConstraints() | 读取生效值 / 请求约束 | 无 | 见原库 | 完全支持 | | MediaStreamTrack.applyConstraints() | 按新约束重采并热替换底层轨道 | constraints? | Promise<void> | 支持(约束无法满足时按 W3C 语义 reject,不回填请求值) | | MediaStreamTrack._switchCamera() | 前 / 后置切换(走 applyConstraints) | 无 | void | 完全支持 | | MediaStreamTrack._setVolume() | 音量增益 | volume: number | void | 支持(引擎 AudioSource.setVolume) | | MediaStreamTrack._setVideoEffects() | 视频特效(模糊 / 虚拟背景) | names: string[] | void | 不支持(引擎无特效管线,见「未实现功能」) | | track.onended / onmute / onunmute | 轨道生命周期事件 | — | — | 支持(引擎无轨道级回调,由原生侧状态观察器上报真实状态迁移,粒度约 1s) | | RTCPeerConnection 全家族 | 协商 / ICE / 收发轨道 / getStats / restartIce / setConfiguration | 见原库 | 见原库 | 完全支持 | | RTCDataChannel / createDataChannel | 数据通道(文本 + 二进制) | 见原库 | 见原库 | 完全支持 | | RTCRtpSender / RTCRtpReceiver / RTCRtpTransceiver | 收发参数、替换轨道、方向、编解码偏好、统计 | 见原库 | 见原库 | 完全支持 | | RTCRtpSender.getCapabilities / RTCRtpReceiver.getCapabilities | 查询编解码能力 | kind: 'audio' \| 'video' | RTCRtpCapabilities | 支持(返回引擎 M120 的实际能力集,与 M144 略有差异) | | RTCFrameCryptorFactory.createDefaultKeyProvider | 创建密钥提供者 | RTCKeyProviderOptions | RTCKeyProvider | 完全支持(数据侧 E2EE 的唯一入口) | | RTCKeyProvider 的 setSharedKey / ratchetSharedKey / exportSharedKey / setKey / ratchetKey / exportKey / dispose | 密钥管理与棘轮 | 见原库 | 见原库 | 完全支持 | | RTCDataPacketCryptorFactory / RTCDataPacketCryptor | 数据包加解密 | 见原库 | 见原库 | 完全支持(AES-256-GCM) | | RTCKeyProvider.setSifTrailer | 服务端注入帧标识 | Uint8Array | Promise | 完全支持(帧侧能力,由 engine/ 自建引擎增补承担) | | RTCFrameCryptorFactory.createFrameCryptorForRtpSender/Receiver、RTCFrameCryptor 全部方法 | 媒体帧级 E2EE | 见原库 | 见原库 | 完全支持(engine/ 自建引擎补齐 KeyProvider / FrameCryptor NAPI 绑定,密文线格式与上游一致;升级 @ohos/webrtc 须重新应用 engine/src/bindings.patch 并重建 .so) | | RTCView / RTCPIPView | 视频渲染组件 | streamURL、mirror、objectFit、zOrder、iosPIP、onDimensionsChange | — | 完全支持 | | startIOSPIP / stopIOSPIP | 画中画开关 | ref | Promise<boolean> | 支持(映射到 @ohos.PiPWindow,需为该视图传入 iosPIP 且其 enabled 为 true) | | ScreenCapturePickerView | iOS 广播选择器视图 | ViewProps | — | 不支持(零内容占位;屏幕共享请直接用 getDisplayMedia) | | RTCAudioSession | iOS AVAudioSession 通知 | 无 | void | 显式空操作(鸿蒙无该概念,方法保留以维持接口完整) | | registerGlobals() | 注入 navigator.mediaDevices / RTCPeerConnection 等全局量 | 无 | void | 完全支持 | | 纯 JS 数据类 | RTCIceCandidate、RTCSessionDescription、RTCRtpEncodingParameters 等 | 见原库 | 见原库 | 完全支持(与平台无关) |

宿主侧原生扩展点(WebRTCModuleOptions)

上游 Android / iOS 各有一个宿主原生侧单例 WebRTCModuleOptions,供宿主 App 在模块初始化前注入编解码工厂、 音频设备模块、原生日志等(JS 不可达)。鸿蒙侧对等物 = HAR 导出的 ArkTS 单例 WebRTCModuleOptions (harmony/webrtc/src/main/ets/WebRTCModuleOptions.ets),在 RN 实例创建之前(如 EntryAbility.onCreate)设置, WebRTCModule 首次初始化时读取一次:

// entry/src/main/ets/entryability/EntryAbility.ets
import webrtc from '@ohos/webrtc';
import { WebRTCModuleOptions } from '@oh-rn/react-native-webrtc';

const options = WebRTCModuleOptions.getInstance();
options.videoEncoderFactory = new webrtc.SoftwareVideoEncoderFactory();      // 缺省:引擎硬编优先
options.audioDeviceModule = new webrtc.AudioDeviceModule({ useHardwareAcousticEchoCanceler: true });
options.audioProcessing = new webrtc.AudioProcessingFactory().create();
options.injectableLogger = { logMessage: (msg, severity, tag) => console.log(`[${tag}] ${msg}`) };
options.loggingSeverity = 1;                                                 // 引擎 severity:0 VERBOSE / 1 INFO / 2 WARNING / 3 ERROR
options.defaultTrackVolume = 0.8;                                            // 远端音轨到达时应用,缺省 1.0

| 上游字段(Android / iOS) | 鸿蒙字段 | 引擎承载 | |---|---|---| | videoEncoderFactory / videoDecoderFactory | 同名 | PeerConnectionFactoryOptions.videoEncoderFactory / videoDecoderFactory;可注入 HardwareVideoEncoderFactory / SoftwareVideoEncoderFactory / HardwareVideoDecoderFactory / SoftwareVideoDecoderFactory | | audioDeviceModule / audioDevice | audioDeviceModule | PeerConnectionFactoryOptions.adm;注入的是引擎自带 AudioDeviceModule 的配置实例(采样率 / 声道 / 硬件 AEC·NS 等),引擎不提供自定义 ADM 协议 | | audioProcessingFactoryFactory / audioProcessingModule | audioProcessing | PeerConnectionFactoryOptions.audioProcessing(new AudioProcessingFactory().create()) | | injectableLogger + loggingSeverity | 同名 | NativeLogging.injectLoggable;只设 loggingSeverity 则 NativeLogging.enableLogToDebugOutput | | defaultTrackVolume | 同名 | 远端音轨首次到达时 setVolume;1.0 时不调用 | | fieldTrials | 无 | 引擎 NAPI 层无对应入口(随包 webrtc.d.ts 检索 fieldTrial 零命中),已登记为平台缺口 | | enableMediaProjectionService / enableMultitaskingCameraAccess | 无 | Android / iOS 平台专属开关,鸿蒙无对应概念 |

设置了任一工厂级字段(编解码工厂 / ADM / 音频处理)时,本库以这些选项构造引擎 PeerConnectionFactory 并调用 PeerConnectionFactory.setDefault,使引擎的 getUserMedia / getDisplayMedia 采集也走同一 ADM / 工厂; 一个字段都不设时与既往行为完全一致(new PeerConnectionFactory(),不动引擎默认工厂)。

平台差异

  • 权限态:abilityAccessCtrl.checkAccessToken 只返回 GRANTED / DENIED,无法区分「从未申请」与「已永久拒绝」。 未授权统一映射为 W3C 的 'prompt'(与上游 Android 分支 granted ? GRANTED : PROMPT 一致), 避免应用误判为不可再申请。
  • enumerateDevices 的 facing:引擎 @ohos/webrtc 的设备项只有 deviceId / kind / label / groupId,朝向在其 NAPI 边界被丢弃; 适配层用相机 kit getCameraManager(context).getSupportedCameras() 按 cameraId(= 引擎视频 deviceId)回取 cameraPosition 映射为 'front' / 'environment',拿不到 context 或相机服务异常时按 label 关键字回退,仍辨不出写 'unknown'(与 iOS 同值)。 该查询不需要相机权限,失败不影响枚举本身。
  • applyConstraints:引擎 VideoSource 无运行期切换摄像头 / 重配分辨率的接口,故按新约束重新采集一路 视频轨道并热替换到所有 sender 与所属 MediaStream,JS 侧 track.id 不变。新轨道采集失败时抛错、保留原轨道。
  • onended / onmute / onunmute:引擎的 MediaStreamTrack 继承的是空 EventTarget,没有轨道级回调。 适配层以约 1s 粒度读取 readyState / MediaSource.state 的真实取值并在跃迁时上报; 本地轨道被显式 release() 时立即上报,不等轮询。无轨道被观察时定时器自动停摆。
  • 数据侧 E2EE 的密码学约定(跨端互通须一致):
    • 密钥材料 → 加密密钥:keyDerivationAlgorithm 为 HKDF(1) 时用 HKDF-SHA256(ikm=材料, salt=ratchetSalt, info=128 字节 0x00, L=32);为 PBKDF2(0) 时用 PBKDF2-SHA256(password=材料, salt=ratchetSalt, c=100000, L=32)。
    • 棘轮恒用 PBKDF2-SHA256(与上游 ratchet() 固定取 PBKDF2 参数一致)。
    • 数据包:AES-256-GCM,12 字节随机 IV,16 字节 authTag 追加在密文尾部,无 AAD。
    • 解密失败(密钥不符 / 密文被篡改)reject(await decrypt() 抛 Error('packet decryption failed'),与上游 Android / iOS 的 dataPacketCryptorDecryptFailed reject 同形态);ratchetWindowSize > 0 时会向前追赶至多 N 次棘轮再判失败。
  • 画中画的自动进入 / 退出(iosPIP.startAutomatically / stopAutomatically):由应用前后台切换驱动, 监听走免权限的 ApplicationContext.on('applicationStateChange')(不是需要 system_basic 级 ohos.permission.RUNNING_STATE_OBSERVER 的 appManager.on('applicationState'),普通应用申请不到该权限, 用它会导致这两个配置项在真机上永远不生效)。该监听在个别设备形态上可能不可用,注册失败时仅记录日志, 手动的 startIOSPIP / stopIOSPIP 不受影响。
  • zOrder 映射为该视图根节点的 ArkUI zIndex;跨 RN 兄弟视图的最终层叠仍受 RN 自身视图顺序影响。

未实现功能

| API | 原因 | |-----|------| | MediaStreamTrack._setVideoEffects() | 上游 Android/iOS 把宿主 App 经原生 ProcessorProvider.addProcessor 注册的帧处理器链挂到采集源上(Android GetUserMediaImpl.java:440-465、iOS WebRTCModule+RTCMediaStream.m:498-521)。@ohos/[email protected] / 1.0.3 的 NAPI 绑定层未把 VideoSource 的帧处理挂接点引出(随包 webrtc.d.ts 检索 effect、blur、background、beauty、VideoProcessor 零命中;VideoSource 只有采集启停 / 切换摄像头事件与 switchCamera() / release();原件归档 engine/reference/webrtc-1.0.{2,3}.d.ts),本仓亦无宿主侧处理器注册入口。桥方法保留在 ABI 上,仅记录日志、不伪装成功。补齐路线同 engine/ 的帧变换器增补(须重建 .so),已挂账、待客户用例触发后实施。 | | ScreenCapturePickerView | 对应 iOS RPSystemBroadcastPickerView(ReplayKit 广播扩展选择器),鸿蒙由系统在 getDisplayMedia() 时自行弹出确认,无对应的应用内选择器视图。屏幕共享功能本身可用。 | | RTCAudioSession.audioSessionDidActivate / ...DidDeactivate | 对应 iOS CallKit / AVAudioSession 语义,鸿蒙无该概念。方法保留在 ABI 上并记录日志,调用安全。 |

媒体帧级 E2EE(RTCFrameCryptor 全部方法与 setSifTrailer)已实现:由 engine/ 归档的自建引擎增补 提供 KeyProvider / FrameCryptor NAPI 绑定(LiveKit FrameCryptorTransformer 的直接绑定), 工厂方法只在对等连接 / sender / receiver 无法解析时返回空 id(触发上游既有的 Error when creating frame cryptor)。

使用限制

  • 需要 ohos.permission.INTERNET、ohos.permission.CAMERA、ohos.permission.MICROPHONE (后两者为 user_grant,需运行时申请)。屏幕共享不需要 ohos.permission.CAPTURE_SCREEN。
  • 引擎基线为 libwebrtc M120,与上游标称的 M144 在编解码器集合与个别新接口上有差异; 能力查询请以 getCapabilities() 的实际返回为准。
  • 数据侧 E2EE 与其它端互通时,双方须采用上文列出的同一套密码学约定。
  • 真机验证请使用本仓库 example 与 example_auto 按宿主工程流程逐项走查。

快速验证(运行 Example)

前置条件

| 依赖 | 版本要求 | |------|----------| | Node.js | >= 18 | | DevEco Studio | 5.0+ / 6.0+ | | HarmonyOS SDK | API 12+ |

运行步骤

1. 克隆仓库

git clone <仓库地址>
cd <仓库目录>

2. 安装依赖并构建

cd example
npm install

示例工程从 npm 安装精确版本 @hxa-rn/[email protected]。安装包已包含 harmony/webrtc.har 与增补引擎 HAR,不会在使用者机器上重新编译原生库。

3. 如需运行自动化示例,安装 example_auto 依赖

cd ../example_auto
npm install

4. 确认 JS Bundle

npm install 的 postinstall 会准备 Hvigor 插件并自动生成内置包:

harmony/entry/src/main/resources/rawfile/bundle.harmony.js

如需手工重建,可执行:

npm run dev

5. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio
  • 普通示例选择 example/harmony,自动化示例选择 example_auto/harmony
  • 等待 Sync 完成

6. 编译并运行 HAP

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

注意:Example 中已预置插件依赖和 Package 注册,无需手动配置 Link。

约束与限制

兼容性

  • RNOH: 0.72+
  • HarmonyOS SDK: API 12+
  • DevEco Studio: 5.0+

遗留问题

  1. 媒体帧级 E2EE 依赖增补引擎:帧侧 7 个桥方法由 engine/prebuilt/ 的增补引擎承担; 升级 @ohos/webrtc 时须在新基线上重新应用 engine/src/bindings.patch 并重建 .so,否则帧侧能力回退。 frameCryptionStateChanged 事件需 2026-08-14 之后重建的 .so。 分发方式正在切换(2026-09-15 拍板):旧 = ohpm install 后手工跑 apply-engine.js 覆盖 oh_modules —— 该做法有一个无声失效模式:ohpm install / DevEco Sync 会把 .so 还原成官方版,而 d.ts 的追加是幂等的, 于是出现「声明在、实现没了 ⇒ 编译通过、真机静默失效」;新 = 发分叉引擎 HAR 由 overrides 接入(Link 步骤 1), 装完即是对的、没有可被还原的补丁。方案与待实测清单见 scripts/README-webrtc-packaging.md, 切换尚未在构建机上验完,当前仍以旧链路为准。
  2. _setVideoEffects 未实现:引擎 NAPI 层未引出视频帧处理挂接点,见「未实现功能」。
  3. 真机验证:未覆盖的场景建议用本仓库 example 逐条走查。
  4. 数据侧 E2EE 的跨端互通未经对端实测:实现遵循上游 LiveKit 客户端 SDK 的密码学约定(见「平台差异」), 与其它端联调前建议先做一次往返比对。

开源协议

本项目基于 MIT License,详见 LICENSE 文件。