@hxa-rn/react-native-voice-voice
v1.0.0
Published
HarmonyOS implementation for @react-native-voice/voice
Readme
react-native-voice
react-native-voice 基于上游 @react-native-voice/voice 开发。如果在使用过程中有任何问题,欢迎在GitCode提交Issue,会及时跟进。
项目介绍
react-native-voice 为 React Native 提供实时语音识别能力:开始 / 停止 / 取消 / 销毁识别会话,查询识别可用性与当前是否正在识别,并通过 7 个 device 事件把识别开始、结束、识别中、部分结果、最终结果、音量变化、错误逐一回抛给 JS。
react-native-voice 是 OpenHarmony(RNOH)适配版,落成一个 ArkTS TurboModule(Voice),不含 Fabric 组件:
- 上游基线
v3.2.4(MIT),旧架构NativeModules直接取模块,无 codegen 输入;鸿蒙侧Platform.OS === 'harmony'使上游 JS 走与 iOS 相同的调用分支(2 参、无options),故本端以 iOS 原生导出面为基准实现。 - 底层能力 = CoreSpeechKit
speechRecognizer(识别,本地引擎)+@ohos.multimedia.audioAudioCapturer(麦克风采集,定长 640/1280 字节分帧)。 - 迁移面合计:1 个 TurboModule / 8 个方法 / 7 个 device 事件 / 0 Fabric 组件。
集成指南
本节用于接入已有 RN 鸿蒙应用;运行本仓库示例请参见「快速验证(运行 Example)」。
1. 安装适配包
当前 npm 适配包为 @hxa-rn/[email protected],业务代码仍从上游包名 @react-native-voice/voice 导入。在 RN 应用根目录执行:
npm install @hxa-rn/[email protected] --save-exact --legacy-peer-depspeerDependencies:{"react":">=18","react-native":">=0.72"}。还需已有可运行的 RNOH 宿主工程。
2. 配置 Metro 并导入
适配包已声明 harmony.alias。宿主 metro.config.js 合并以下配置,并保留原有的自定义设置:
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');
module.exports = mergeConfig(
getDefaultConfig(__dirname),
createHarmonyMetroConfig({
reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}),
);业务代码:
import Voice from '@react-native-voice/voice';3. 注册鸿蒙原生模块
本包声明了 Autolinking 元数据:CMake 目标 voice,ohpm 包 @oh-rn/voice,C++ / ETS 类 VoicePackage。宿主启用 RNOH Autolinking 后,应检查生成的 HAR 依赖、CMake 链接及 C++ / ETS Package 注册是否齐全;已自动注册时不要重复手动注册。
Autolinking 不可用时,保留宿主已有配置,补齐以下四处:
- 在
harmony/entry/oh-package.json5的dependencies追加下项,然后在harmony/entry执行ohpm install并同步工程:
"@oh-rn/voice": "file:../../node_modules/@hxa-rn/react-native-voice-voice/harmony/voice.har"- 在
harmony/entry/src/main/cpp/CMakeLists.txt添加子目录,并在已有add_library(rnoh_app ...)之后链接:
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
add_subdirectory("${OH_MODULE_DIR}/@oh-rn/voice/src/main/cpp" ./voice)
# 放在 rnoh_app 目标创建之后:
target_link_libraries(rnoh_app PUBLIC voice)- 在
PackageProvider.cpp添加头文件,并把实例加入已有getPackages返回集合(本仓库模板可加入ManualLinkingPackage列表):
#include "VoicePackage.h"
// 加入已有 Package 集合:
std::make_shared<rnoh::VoicePackage>(ctx)- 在
harmony/entry/src/main/ets/RNPackagesFactory.ets添加默认导入,并把实例加入已有createRNPackages返回数组:
import VoicePackage from '@oh-rn/voice';
// 加入 createRNPackages(ctx) 返回数组:
new VoicePackage(ctx)确保宿主 RNApp 使用上述 createRNPackages,并启用 enableCAPIArchitecture: true。完成后重新生成宿主 Bundle、构建并安装 HAP;只刷新 JS 不会加载新增的原生模块。若 HAR 内 RNOH 相对依赖无法解析,在宿主鸿蒙根 oh-package.json5 的 overrides 中将 @rnoh/react-native-openharmony 指向宿主正在使用的同一 RNOH HAR,勿混用 debug/release 或不同版本。
4. 麦克风与识别环境
在宿主 harmony/entry/src/main/module.json5 声明 ohos.permission.MICROPHONE,配置 reason 字符串及实际使用的 Ability,并处理运行时授权。可参照 example 的同名配置。需要设备支持 CoreSpeechKit 识别引擎;拒绝授权时检查 onSpeechError,不应继续采集。
使用说明
import Voice from '@react-native-voice/voice';
import { useEffect } from 'react';
useEffect(() => {
Voice.onSpeechStart = () => console.log('start');
Voice.onSpeechEnd = () => console.log('end');
Voice.onSpeechPartialResults = (e) => console.log('partial:', e.value);
Voice.onSpeechResults = (e) => console.log('final:', e.value);
Voice.onSpeechVolumeChanged = (e) => console.log('volume:', e.value);
Voice.onSpeechError = (e) => console.log(e.error.code, e.error.message);
return () => {
Voice.destroy();
};
}, []);
await Voice.start('zh-CN'); // 空串回落 zh-CN
await Voice.stop(); // 结束识别,必定收到 onSpeechEnd
await Voice.cancel(); // 取消识别,必定收到 onSpeechEnd
await Voice.destroy(); // 销毁会话并清空全部事件监听
const available = await Voice.isAvailable();
const busy = await Voice.isRecognizing();接口文档
方法(8 个):
| 方法 | 签名 | 说明 |
|---|---|---|
| start | (locale: string) => Promise<void> | 开始识别;空串回落 zh-CN;识别中再次调用会先收束前一会话(补发一次 onSpeechEnd)再启动新会话 |
| stop | () => Promise<void> | 结束识别;必定收到 onSpeechEnd |
| cancel | () => Promise<void> | 取消识别;由本适配主动补发 onSpeechEnd,非引擎自然发出 |
| destroy | () => Promise<void> | 销毁会话并释放资源,连带执行 removeAllListeners() |
| isAvailable | () => Promise<0 \| 1> | 查询识别能力是否可用 |
| isRecognizing | () => Promise<0 \| 1> | 查询当前是否正在识别 |
| getSpeechRecognitionServices | () => Promise<undefined> | 鸿蒙侧既定空结果(对齐上游 iOS 分支行为),非 [] / null |
| removeAllListeners | () => void | 清除全部事件监听;可重复调用不抛异常;清除后可重新 start 并重建订阅 |
事件(7 个,字面事件名,无 top 前缀):
| 事件 | 触发时机 | payload |
|---|---|---|
| onSpeechStart | start() 生效 | {} |
| onSpeechEnd | stop() / cancel() / 识别自然结束 | {} |
| onSpeechRecognized | 识别到语音片段 | { isFinal: boolean } |
| onSpeechResults | 最终结果 | { value: string[] } |
| onSpeechPartialResults | 中间结果 | { value: string[] } |
| onSpeechVolumeChanged | 每帧音频自算 | { value: number }(0~10 区间) |
| onSpeechError | 引擎错误 / 权限拒绝 | { error: { message, code } }(嵌套) |
⚠️ onSpeechStart / onSpeechEnd 的 payload 恰为空对象 {};结果类事件的载荷键是 value(不是 values)。
快速验证(运行 Example)
前置条件
- Node.js >= 20(以示例 engines 为准),npm,以及 DevEco Studio 配套的 ohpm / SDK。
- 示例版本:React Native
0.72.5、RNOH0.72.143。 - 鸿蒙工程配置:targetSdkVersion=6.1.1(24),compatibleSdkVersion=5.1.0(18)。设备应满足最低版本及本库系统能力要求。
- 在 DevEco Studio 中配置与当前应用包名匹配的签名,不能直接使用其他电脑上的证书路径。
运行步骤
1. 克隆仓库
git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-voice.git
cd react-native-voice以下步骤使用 example 展示工程;example_auto 的依赖与构建输出独立,不要混用。Windows 建议使用较短目录,避免 RNOH 原生构建中间路径过长。
2. 安装示例依赖
示例已锁定 npmjs 上的 @hxa-rn/[email protected]。进入示例目录安装:
cd example
npm install --legacy-peer-deps3. 生成 JS Bundle
npm run dev确认生成 example/harmony/entry/src/main/resources/rawfile/bundle.harmony.js。先解决命令报错,再进入原生构建。
4. 同步与运行鸿蒙工程
用 DevEco Studio 打开 example/harmony,完成依赖同步。缺少 ohpm 依赖时,在该目录使用 DevEco 配套工具执行 ohpm install --all,再同步。保留示例已有的 RNOH HAR 路径和版本。
示例已配置本库运行所需的依赖与接线,无需重复添加 Package。选择设备、配置签名并点击运行,生成并安装 HAP。修改 JS 后重新生成 Bundle;修改原生依赖后重新构建安装 HAP。
常见问题
- 找不到 JS 模块:检查适配包安装、Metro 别名及对应入口,修改 Metro 后重启打包进程。
- 找不到本地包或 HAR:核对当前目录、文件名及准备步骤;不要将
example_auto的 node_modules 当成example的依赖。 - 原生模块或组件未注册:检查 HAR、CMake、C++ 和 ETS 注册,排除重复注册并重建 HAP。
- SDK / 签名报错:按当前工程配置安装对应 SDK,并重新配置本机签名。
- Ninja
.rsp创建失败:查看完整日志;确认是路径长度问题后,缩短工程目录、清理旧路径构建缓存再构建。
约束与限制
兼容性:
| 项 | 值 |
|---|---|
| 鸿蒙最低兼容 API | API 18(compatibleSdkVersion 5.1.0(18)) |
| 目标 API | API 24(targetSdkVersion 6.1.1(24)) |
| 已验证通过的设备与档位 | API22 / API23 / API24 / API26 真机,共四档 |
| 上游 SDK 版本 | @react-native-voice/[email protected] |
| RN / RNOH | RN 0.72.5 + [email protected] |
权限:
ohos.permission.MICROPHONE(麦克风)—— 由宿主module.json5声明,用于语音识别采集音频。库本身不声明任何权限。- 未授予权限时不开麦,回抛
onSpeechError(code: permission_denied)。
使用约束:
getSpeechRecognitionServices恒返回undefined:该方法不落原生实现,与上游 iOS 分支行为一致,不是缺陷。- 音量值范围为
[0, 10]的非负数:与上游 Android 的 dBFS 语义不同,鸿蒙侧由 CoreSpeechKit 归一化给出。 - 识别语言/文案质量由系统引擎决定,非
react-native-voice判定范围。
开源license
react-native-voice 基于 The MIT License (MIT),请自由地享受和参与开源。
问题反馈渠道
使用过程中发现任何问题,欢迎在GitCode 提交 Issue,也欢迎提交 PR 参与共建。
