react-native-voice:基于 React Native 鸿蒙生态的实时语音识别项目

语音转文字识别库

Branch3Tags2
FilesLast commitLast update
18 days ago
18 days ago
19 days ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
28 days ago
19 days ago
18 days ago
18 days ago
1 month ago
18 days ago
1 month ago

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.audio AudioCapturer(麦克风采集,定长 640/1280 字节分帧)。
  • 迁移面合计:1 个 TurboModule / 8 个方法 / 7 个 device 事件 / 0 Fabric 组件。

集成指南

本节用于接入已有 RN 鸿蒙应用;运行本仓库示例请参见「快速验证(运行 Example)」。

1. 安装适配包

当前 npm 适配包为 @hxa-rn/react-native-voice-voice@3.2.5(与上游基线同号),业务代码仍从上游包名 @react-native-voice/voice 导入。在 RN 应用根目录执行:

npm install @hxa-rn/react-native-voice-voice@3.2.5 --save-exact --legacy-peer-deps

peerDependencies:{"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 不可用时,保留宿主已有配置,补齐以下四处:

  1. 在 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"
  1. 在 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)
  1. 在 harmony/entry/src/main/cpp/PackageProvider.cpp 添加头文件,并把实例加入已有 getPackages 返回集合(本仓库模板可加入 ManualLinkingPackage 列表):
#include "VoicePackage.h"

// 加入已有 Package 集合:
std::make_shared<rnoh::VoicePackage>(ctx)
  1. 在 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 的 module.requestPermissions 中声明麦克风权限(与本仓示例相同):

"requestPermissions": [
  {
    "name": "ohos.permission.MICROPHONE",
    "reason": "$string:microphone_permission_reason",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  }
]

$string:microphone_permission_reason 需在 harmony/entry/src/main/resources/base/element/string.json 中定义(例如「用于录制麦克风音频以进行语音识别」);abilities 填宿主实际承载 RN 页面的 Ability。运行时授权弹窗由本库在 Voice.start() 时自动发起,宿主无需另行申请;用户拒绝时回抛 onSpeechError(code: permission_denied),不会开麦。设备需支持 CoreSpeechKit 识别引擎。

使用说明

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 要求)
DevEco Studio 6.1.1 及以上(示例 targetSdkVersion 为 6.1.1(24))
HarmonyOS SDK API 18+(example/harmony 的 compatibleSdkVersion 为 5.1.0(18))
路径 Windows 下仓库根目录的完整路径不超过 40 个字符,否则原生构建的中间文件路径会超过系统上限

运行步骤

1. 克隆仓库

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

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

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

cd example
npm install --legacy-peer-deps

Example 从 npm 公仓安装 @hxa-rn/react-native-voice-voice@3.2.5,不需要在仓根执行 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 后重新执行再运行。

常见问题

  • 找不到 JS 模块:检查适配包安装、Metro 别名及对应入口,修改 Metro 后重启打包进程。
  • 找不到 npm 包或 HAR:核对 example/node_modules/@hxa-rn/react-native-voice-voice/harmony/voice.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/voice@3.2.4
RN / RNOH RN 0.72.5 + @react-native-oh/react-native-harmony@0.72.143

权限:

  • 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 参与共建。