基于 react-native-audio 的 OpenHarmony 适配版,用于录制音频
当前访问频次受限,请登录后继续访问
文档模板:v0.4.2
react-native-audio
本项目基于 react-native-audio 开发。
该第三方库的仓库已迁移至 Gitcode,且支持直接从 npm 下载,新的包名为:@react-native-ohos/react-native-audio 版本所属关系如下:
| 三方库名称 | 三方库版本(npm地址) | 发布信息 | 支持RN版本 | Autolink | 编译API版本 | 社区基线版本 | 源码地址 |
|---|---|---|---|---|---|---|---|
| @react-native-ohos/react-native-audio | ~ 4.2.4 | Gitcode Releases | 0.72.* | 是 | API12+ | 4.2.2 | br_rnoh0.72 |
| @react-native-oh-tpl/react-native-audio | <= 4.3.1-0.1.0@deprecated | Github Releases(deprecated) | 0.72.* | 否 | API12+ | 4.3.0 | sig |
简介
react-native-audio 是一个 React Native 音频录制扩展库,提供麦克风权限申请、录音参数配置、开始/暂停/恢复/停止录制,以及录制进度与完成回调等能力。鸿蒙侧基于系统 AVRecorder 实现,接口与上游社区库保持一致,import 包名不变。
下载安装
进入到工程目录并输入以下命令:
npm
npm install @react-native-ohos/react-native-audio
yarn
yarn add @react-native-ohos/react-native-audio
Link
| 是否支持autolink | RN框架版本 | |
|---|---|---|
| ~ 4.2.4 | 是 | 0.72 |
| <= 4.3.1-0.1.0@deprecated | 否 | 0.72 |
使用 AutoLink 的工程需要根据 Autolink 框架指导文档 配置。
如您使用的版本支持 Autolink,并且工程已接入 Autolink,可跳过ManualLink配置。
ManualLink: 此步骤为手动配置原生依赖项的指导
首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 harmony。
1. Overrides RN SDK
为了让工程依赖同一个版本的 RN SDK,需要在工程根目录的 oh-package.json5 添加 overrides 字段,指向工程需要使用的 RN SDK 版本。替换的版本既可以是一个具体的版本号,也可以是一个模糊版本,还可以是本地存在的 HAR 包或源码目录。
关于该字段的作用请阅读官方说明
{
"overrides": {
"@rnoh/react-native-openharmony": "~0.72.140" // ohpm 在线版本
// "@rnoh/react-native-openharmony" : "./react_native_openharmony.har" // 指向本地 har 包的路径
// "@rnoh/react-native-openharmony" : "./react_native_openharmony" // 指向源码路径
}
}
2. 引入原生端代码
目前有两种方法:
- 通过 har 包引入;
- 直接链接源码。
方法一:通过 har 包引入(推荐)
har 包位于三方库安装路径的 `harmony` 文件夹下。
打开 entry/oh-package.json5,添加以下依赖:
"dependencies": {
"@react-native-ohos/react-native-audio": "file:../../node_modules/@react-native-ohos/react-native-audio/harmony/audio.har"
}
点击右上角的 sync 按钮,或在命令行终端执行:
cd entry
ohpm install
方法二:直接链接源码
如需使用直接链接源码,请参考[直接链接源码说明](https://gitcode.com/CPF-RN/usage-docs/blob/master/zh-cn/link-source-code.md)
3. 配置 CMakeLists 和引入 AudioPackage
打开 entry/src/main/cpp/CMakeLists.txt,添加:
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
# RNOH_BEGIN: manual_package_linking_1
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-audio/src/main/cpp" ./audio)
# RNOH_END: manual_package_linking_1
# RNOH_BEGIN: manual_package_linking_2
+ target_link_libraries(rnoh_app PUBLIC rnoh_audio)
# RNOH_END: manual_package_linking_2
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "AudioPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<AudioPackage>(ctx)
};
}
4. 在 ArkTs 侧引入 AudioPackage
打开 entry/src/main/ets/RNPackagesFactory.ets,添加:
...
+ import {AudioPackage} from '@react-native-ohos/react-native-audio/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
+ new AudioPackage(ctx)
];
}
运行
点击右上角的 sync 按钮,或在命令行终端执行:
cd entry
ohpm install
然后编译、运行即可。
约束与限制
兼容性
本文档内容基于以下版本验证通过:
- RNOH: 0.72.140; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
权限要求
录音功能需要在 HarmonyOS 工程 entry/src/main/module.json5 中声明麦克风权限:
"requestPermissions": [
{
"name": "ohos.permission.MICROPHONE",
"reason": "$string:permission_microphone",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
编译运行 API 要求
当前三方库所有版本均已实现版本隔离,支持在 `API12+` 工程编译,及 `API12+` ROM 运行。
使用示例
下面的代码展示了这个库的基本使用场景:
使用时 import 的库名不变。
import React, { useEffect } from 'react';
import { SafeAreaView, Text, Button, View } from 'react-native';
import { AudioRecorder, AudioUtils, AudioSource } from 'react-native-audio';
export default function App() {
const initRecording = async () => {
await AudioRecorder.requestAuthorization();
await AudioRecorder.checkAuthorizationStatus();
await AudioRecorder.prepareRecordingAtPath(
`${AudioUtils.FilesDirectoryPath}/audio_demo.m4a`,
{
SampleRate: 44100,
Channels: 2,
AudioQuality: 'High',
AudioEncoding: 'aac',
AudioEncodingBitRate: 32000,
AudioSource: AudioSource.MIC,
OutputFormat: 'm4a',
MeteringEnabled: false,
IncludeBase64: false,
}
);
AudioRecorder.onProgress = (data) => {
console.log('currentTime:', data.currentTime);
};
AudioRecorder.onFinished = (data) => {
console.log('finished:', data.audioFileURL, data.duration);
};
};
useEffect(() => {
initRecording();
}, []);
return (
<SafeAreaView>
<View style={{ flexDirection: 'row', gap: 8, padding: 16 }}>
<Button title="start" onPress={() => AudioRecorder.startRecording()} />
<Button title="pause" onPress={() => AudioRecorder.pauseRecording()} />
<Button title="resume" onPress={() => AudioRecorder.resumeRecording()} />
<Button title="stop" onPress={() => AudioRecorder.stopRecording()} />
</View>
</SafeAreaView>
);
}
使用说明
录音流程
- 调用
requestAuthorization申请麦克风权限; - 调用
prepareRecordingAtPath(path, options)初始化录音参数并订阅原生事件; - 设置
AudioRecorder.onProgress/AudioRecorder.onFinished回调; - 调用
startRecording开始录音,可pauseRecording/resumeRecording; - 调用
stopRecording停止录音;约 200ms 后会自动移除事件订阅并清空回调引用; - 开始新的录音会话前,需重新调用
prepareRecordingAtPath并重新设置回调。
prepareRecordingAtPath 默认参数
JS 层默认值(与上游社区库对齐)如下,鸿蒙/Android 未显式传入 AudioEncoding 时会自动将 ima4 替换为 aac,并默认 AudioSource: 1(MIC):
| 参数 | 默认值 |
|---|---|
| SampleRate | 44100 |
| Channels | 2 |
| AudioQuality | High |
| AudioEncoding | ima4(Android/HarmonyOS 默认转为 aac) |
| OutputFormat | mpeg_4 |
| AudioEncodingBitRate | 32000 |
| MeteringEnabled | false |
| MeasurementMode | false |
| IncludeBase64 | false |
AudioUtils 路径(HarmonyOS)
鸿蒙平台提供以下目录路径,用于拼接录音文件保存位置:
| 属性 | 说明 |
|---|---|
| FilesDirectoryPath | 应用文件目录 |
| CacheDirectoryPath | 应用缓存目录 |
| TempsDirectoryPath | 应用临时目录 |
AudioEncoding 格式支持
| 值 | iOS | Android | HarmonyOS Support |
|---|---|---|---|
| aac | yes | yes | yes |
| aac_eld4.2.5+ | yes | yes | yes(API 22+) |
| he_aac4.2.5+ | no | yes | yes(API 22+) |
| amr_nb4.2.5+ | yes | yes | yes(API 18+) |
| amr_wb4.2.5+ | no | yes | yes(API 18+) |
| mp34.2.5+ | no | no | yes(API 12+) |
| ima4 | yes | no | no |
| vorbis | no | yes | no |
| lpcm | yes | no | no |
| alac | yes | no | no |
OutputFormat 格式支持
| 值 | iOS | Android | HarmonyOS Support |
|---|---|---|---|
| mpeg_44.2.5+ | no | yes | yes |
| m4a | no | yes | yes |
| aac_adts4.2.5+ | no | yes | yes(API 20+) |
| amr_nb | no | yes | no |
| amr_wb | no | yes | no |
| three_gpp4.2.5+ | no | yes | yes(API 18+) |
| mp34.2.5+ | no | no | yes |
| webm | no | yes | no |
OutputFormat为 Android 专用参数;iOS 通过文件扩展名与AudioEncoding决定输出格式。MP3 编码须配合OutputFormat=mp3。
AudioSource 常量
| 常量 | 值 | iOS | Android | HarmonyOS Support |
|---|---|---|---|---|
| DEFAULT | 0 | no | yes | yes |
| MIC | 1 | no | yes | yes |
| VOICE_UPLINK | 2 | no | yes | no |
| VOICE_DOWNLINK | 3 | no | yes | no |
| VOICE_CALL | 4 | no | yes | no |
| CAMCORDER4.2.5+ | 5 | no | yes | yes |
| VOICE_RECOGNITION4.2.5+ | 6 | no | yes | yes |
| VOICE_COMMUNICATION4.2.5+ | 7 | no | yes | yes |
| REMOTE_SUBMIX | 8 | no | yes(API 19+) | no |
| UNPROCESSED | 9 | no | yes(API 24+) | no |
电平计量(MeteringEnabled4.2.5+)
当 MeteringEnabled: true 时,onProgress 回调除 currentTime 外还会包含 currentMetering 与 currentPeakMetering 字段。
接口说明
"Platform" 列表示该属性在原三方库上支持的平台。
"HarmonyOS Support" 列为 **yes** 表示 HarmonyOS 平台支持该属性;标注 **API xx+** 表示需对应 HarmonyOS SDK API 级别;**no** 则表示不支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
**版本角标**:名称旁标注 4.2.5+ 表示该 API / 参数 / 枚举值自 **4.2.5+** 起在 HarmonyOS 侧新增或增强支持;
事件回调
| 名称 | 类型 | 参数类型 | 返回值 | 必填 | 平台 | OpenHarmony平台支持 | 描述 |
|---|---|---|---|---|---|---|---|
| onProgress | function | data: { currentTime: number, currentMetering?: number, currentPeakMetering?: number } | void | no | Android/iOS | yes | 录音进度回调。接收 { currentTime: number };当 MeteringEnabled: true 时还包含 currentMetering、currentPeakMetering |
| onFinished | function | data: { base64?: string, duration: number, status: string, audioFileURL: string, audioFileSize: number } | void | no | Android/iOS | yes | 录音完成回调。接收 { base64, duration, status, audioFileURL, audioFileSize };base64 仅在 IncludeBase64: true 时有值 |
注意:
stopRecording会在约 200ms 延迟后自动移除原生事件订阅并清除onProgress/onFinished回调引用。开始新的录音会话前,必须重新调用prepareRecordingAtPath并重新设置回调。
API
| 名称 | 类型 | 参数类型 | 返回值 | 必填 | 平台 | OpenHarmony平台支持 | 描述 |
|---|---|---|---|---|---|---|---|
| requestAuthorization | function | / | Promise | no | Android/iOS | yes | 请求麦克风权限 |
| checkAuthorizationStatus | function | / | Promise | no | Android/iOS | yes | 检查授权状态。返回值存在平台差异:iOS 返回 string 枚举值('granted' / 'denied' / 'undetermined'),Android/HarmonyOS 返回 boolean |
| prepareRecordingAtPath | function | path: string, options: RecordingOptions | Promise | no | Android/iOS | yes | 初始化录音实例参数 |
| startRecording | function | / | Promise | no | Android/iOS | yes | 开始录音 |
| pauseRecording | function | / | Promise | no | Android/iOS | yes | 暂停录音 |
| resumeRecording | function | / | Promise | no | Android/iOS | yes | 恢复录音 |
| stopRecording | function | / | Promise | no | Android/iOS | yes | 停止录音 |
| getAllPath | function | / | { FilesDirectoryPath: string, CacheDirectoryPath: string, TempsDirectoryPath: string } | no | HarmonyOS | yes | 获取应用文件/缓存/临时目录路径;模块加载时用于生成鸿蒙平台 AudioUtils |
| removeListeners | function | / | void | no | Android/iOS | yes | 移除录音进度和完成事件订阅;stopRecording 延迟后会自动调用,通常无需手动调用 |
| clearCallback | function | / | void | no | HarmonyOS | yes | 清空 onProgress / onFinished 回调引用;stopRecording 延迟后会自动调用,通常无需手动调用 |
prepareRecordingAtPath 参数(RecordingOptions)
| 名称 | 参数类型 | 默认值 | 必填 | 平台 | OpenHarmony平台支持 | 描述 |
|---|---|---|---|---|---|---|
| SampleRate | number | 44100 | yes | Android/iOS | yes | 采样率(Hz) |
| Channels | number | 2 | yes | Android/iOS | yes | 声道数 |
| AudioQuality4.2.5+ | 'Low' / 'Medium' / 'High' |
High | no | iOS/Android | yes | 音质档位,影响码率:Low=32000、Medium=64000、High=使用 AudioEncodingBitRate |
| AudioEncoding4.2.5+ | string | aac(Android/HarmonyOS) | yes | Android/iOS | yes | 编码格式,见上方「AudioEncoding 格式支持」(部分枚举值需 API 12+/18+/22+) |
| AudioEncodingBitRate | number | 32000 | yes | Android/iOS | yes | 编码码率(bps) |
| AudioSource4.2.5+ | number | 1(MIC) | yes | Android | yes | 音源类型,见上方「AudioSource 常量」(扩展音源需 API 12+) |
| OutputFormat4.2.5+ | string | mpeg_4 | yes | Android | yes | 封装格式,见上方「OutputFormat 格式支持」(部分枚举值需 API 12+/18+/20+) |
| MeteringEnabled4.2.5+ | boolean | false | no | iOS/Android | yes | 是否开启电平计量 |
| MeasurementMode | boolean | false | no | iOS | no | iOS 专用测量模式 |
| IncludeBase64 | boolean | false | yes | Android/iOS | yes | 停止录音时是否返回 base64 数据 |
AudioUtils 属性
库导出的目录路径常量(均为 string 类型),用于拼接录音文件保存位置;按平台取值不同:
| 名称 | 类型 | 必填 | 平台 | OpenHarmony平台支持 | 描述 |
|---|---|---|---|---|---|
| FilesDirectoryPath | string | no | HarmonyOS | yes | 应用文件目录 |
| CacheDirectoryPath | string | no | HarmonyOS | yes | 应用缓存目录 |
| TempsDirectoryPath | string | no | HarmonyOS | yes | 应用临时目录 |
| MainBundlePath | string | no | Android/iOS | no | 应用安装包主目录 |
| CachesDirectoryPath | string | no | Android/iOS | no | 应用缓存目录(鸿蒙侧名称为 CacheDirectoryPath) |
| DocumentDirectoryPath | string | no | Android/iOS | no | 应用文档目录 |
| LibraryDirectoryPath | string | no | Android/iOS | no | 应用 Library 目录 |
| PicturesDirectoryPath | string | no | Android | no | 系统图片目录 |
| MusicDirectoryPath | string | no | Android | no | 系统音乐目录 |
| DownloadsDirectoryPath | string | no | Android | no | 系统下载目录 |
鸿蒙平台取值来自
getAllPath()返回的应用沙箱目录,在模块加载时生成。
遗留问题
MeasurementMode为 iOS 专用参数,HarmonyOS 侧忽略ima4、vorbis、webm等格式在 HarmonyOS 侧不支持,请参见上方格式支持表AudioSource中VOICE_UPLINK、VOICE_DOWNLINK、VOICE_CALL、REMOTE_SUBMIX、UNPROCESSED在 HarmonyOS 侧不支持
其他
- 完整 API 演示可参考工程内
example/src/AudioDemo.tsx - 英文文档见 README_EN.md
目录结构
/rntpc_react-native-audio # 项目根目录
├── harmony # 鸿蒙适配代码
│ ├── audio.har # HAR 包(npm 发布产物)
│ └── audio # 鸿蒙适配核心模块
│ ├── index.ets
│ ├── oh-package.json5
│ └── src/main
│ ├── cpp # C++ TurboModule 与 codegen 产物
│ │ ├── AudioPackage.h
│ │ ├── CMakeLists.txt
│ │ └── generated/
│ └── ets
│ ├── AudioPackage.ets
│ ├── AudioModule.ts
│ ├── AudioRecordManager.ts
│ ├── AudioApiCompat.ts
│ ├── AudioType.ts
│ ├── StopWatch.ts
│ └── generated/ # codegen 产物
├── example # 示例工程
├── index.js # JS 入口
├── NativeAudio.ts # TurboModule 类型定义
├── package.json
├── README.md # 中文文档
├── README_EN.md # 英文文档
└── LICENSE
贡献代码
使用过程中发现任何问题都可以提交 Issue,也非常欢迎提交 PR。
开源协议
本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。