HarmonyOS 鸿蒙Next AI语音02-声音文件转文本
HarmonyOS 鸿蒙Next AI语音02-声音文件转文本
三文带你轻松上手鸿蒙的AI语音02-声音文件转文本
接上一文
前言
本文主要实现 使用鸿蒙的AI语音功能将声音文件识别并转换成文本
实现流程
- 利用
AudioCapturer
录制声音,生成录音文件 - 利用AI语音功能,实现识别
两个录音库介绍
在 HarmonyOS NEXT 应用开中,实现录音的两个核心库分别为
- AudioCapturer
- AVRecorder
AVRecorder录制出来的声音封装格式只能是aac,这个文件格式我们的AI语音引擎不支持,AI语音引擎只支持pcm格式,而 AudioCapturer录制的声音封装格式则是pcm。因此我们选择使用 AudioCapturer 来录制声音
AudioCapturer 介绍
AudioCapturer是音频采集器,用于录制PCM(Pulse Code Modulation)音频数据,适合有音频开发经验的开发者实现更灵活的录制功
能。
主要流程
- 创建 AudioCapturer 实例
- 调用 start 方法开始录音
- 调用 stop 方法停止录音
- 调用 release 方法释放实例
创建 AudioCapturer 实例
文末会提供封装好,可以直接使用的代码 下面的代码示例都是基于封装好的代码进行的
我们通过调用 createAudioCapturer 方法实现创建 AudioCapturer 实例,其中该方法需要传递相关参数。
调用 start 方法开始录音
开始调用 start 方法时,需要准备相关数据。如
- 提供录音的文件名,可以自定义
- 写入录音数据的回调函数(在录制声音的过程中持续触发)
- 调用 start 方法
调用 stop 方法停止录音
调用 stop 方法则相对简单,直接调用即可
调用 release 方法释放实例
同理
封装好的录音代码
entry/src/main/ets/utils/AudioCapturerManager.ets
下面是这个类的属性和方法的总结:
属性
- static audioCapturer: 类型是
audio.AudioCapturer | null
,是一个静态属性,用于存储当前的音频捕获器实例。 - private static recordFilePath: 类型是
string
,是一个静态私有属性,用于存储录音文件的路径。
方法
- static async createAudioCapturer(): 如果
audioCapturer
已经存在,则直接返回该实例;否则创建一个新的音频捕获器实例,并设置其音频流信息和音频捕获信息,然后创建并返回新的实例。 - static async startRecord(fileName: string): 异步静态方法,用于启动录音过程。首先调用
createAudioCapturer()
方法确保有一个音频捕获器实例。之后初始化缓冲区大小,并打开或创建一个指定名称的.wav
录音文件。定义一个读取数据的回调函数,用于将捕获到的数据写入文件中。最后开始录音,并记录下录音文件的路径。 - static async stopRecord(): 异步静态方法,用于停止录音过程。停止音频捕获器的工作,释放其资源,并清除
audioCapturer
实例。
页面中开始录音
可以通过以下路径查看录音文件是否真实生成
/data/app/el2/100/base/你的项目的boundle名称/haps/entry/files
使用AI语音功能 实现声音文件转文本
该流程其实和和上一章的实时识别声音功能类似,只是多了一个步骤
- 创建AI语音引擎
- 注册语音监听事件
- 开始监听
- 读取录音文件
创建AI语音引擎
/**
* 创建引擎
*/
private static async createEngine() {
// 设置创建引擎参数
SpeechRecognizerManager.asrEngine = await speechRecognizer.createEngine(SpeechRecognizerManager.initParamsInfo)
}
注册语音监听事件
/**
* 设置回调
*/
private static setListener(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}) {
// 创建回调对象
let setListener: speechRecognizer.RecognitionListener = {
// 开始识别成功回调
onStart(sessionId: string, eventMessage: string) {
},
// 事件回调
onEvent(sessionId: string, eventCode: number, eventMessage: string) {
},
// 识别结果回调,包括中间结果和最终结果
onResult(sessionId: string, result: speechRecognizer.SpeechRecognitionResult) {
SpeechRecognizerManager.speechResult = result
callback && callback(result)
},
// 识别完成回调
onComplete(sessionId: string, eventMessage: string) {
},
// 错误回调,错误码通过本方法返回
// 如:返回错误码1002200006,识别引擎正忙,引擎正在识别中
// 更多错误码请参考错误码参考
onError(sessionId: string, errorCode: number, errorMessage: string) {
console.log("errorMessage", errorMessage)
},
}
// 设置回调
SpeechRecognizerManager.asrEngine?.setListener(setListener);
}
开始监听
需要设置 recognitionMode 为 1 表示识别语音文件
/**
* 开始监听
*/
static startListening2() {
try { // 设置开始识别的相关参数
let recognizerParams: speechRecognizer.StartParams = {
// 会话id
sessionId: SpeechRecognizerManager.sessionId,
// 音频配置信息。
audioInfo: {
// 音频类型。 当前仅支持“pcm”
audioType: 'pcm',
// 音频的采样率。 当前仅支持16000采样率
sampleRate: 16000,
// 音频返回的通道数信息。 当前仅支持通道1。
soundChannel: 1,
// 音频返回的采样位数。 当前仅支持16位
sampleBit: 16
},
// 录音识别
extraParams: {
// 0:实时录音识别 会自动打开麦克风 录制实时语音
// 1 识别语音文件
"recognitionMode": 1,
// 最大支持音频时长
maxAudioDuration: 60000
}
}
// 调用开始识别方法
SpeechRecognizerManager.asrEngine?.startListening(recognizerParams);
} catch (e) {
console.log("e", e.code, e.message)
}
};
读取录音文件
需要调用 SpeechRecognizerManager.asrEngine?.writeAudio 来监听语音文件
/**
*
* @param fileName {string} 语音文件名称
*/
private static async writeAudio(fileName: string) {
let ctx = getContext();
let filePath: string = `${ctx.filesDir}/${fileName}.wav`;
let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE);
let buf: ArrayBuffer = new ArrayBuffer(1280);
let offset: number = 0;
while (1280 == fileIo.readSync(file.fd, buf, {
offset: offset
})) {
let uint8Array: Uint8Array = new Uint8Array(buf);
// 调用AI语音引擎识别
SpeechRecognizerManager.asrEngine?.writeAudio(SpeechRecognizerManager.sessionId, uint8Array);
// 延迟40ms
await SpeechRecognizerManager.sleep(40)
offset = offset + 1280;
}
fileIo.closeSync(file);
}
/**
* 加入延迟 否则录音文件识别会出错
* @param time
* @returns
*/
static sleep(time: number) {
const promise = new Promise<void>((resolve: Function) => {
setTimeout(() => {
resolve()
}, time)
})
return promise
}
一步调用
/**
* 初始化ai语音转文字引擎
*/
static async init2(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}, fileName: string) {
try {
await SpeechRecognizerManager.createEngine()
SpeechRecognizerManager.setListener(callback)
SpeechRecognizerManager.startListening2()
SpeechRecognizerManager.writeAudio(fileName)
} catch (e) {
console.log("e", e.message)
}
}
完整代码
import { speechRecognizer } from '@kit.CoreSpeechKit';
import { fileIo } from '@kit.CoreFileKit';
class SpeechRecognizerManager {
static speechResult: speechRecognizer.SpeechRecognitionResult | null = null
private static extraParam: Record<string, Object> = { "locate": "CN", "recognizerMode": "short" };
private static initParamsInfo: speechRecognizer.CreateEngineParams = {
/**
* 地区信息
*/
language: 'zh-CN',
/**
* 离线模式:1
*/
online: 1,
extraParams: this.extraParam
};
private static asrEngine: speechRecognizer.SpeechRecognitionEngine | null = null
private static sessionId: string = "asr" + Date.now()
/**
* 开始监听
*/
static startListening() {
try { // 设置开始识别的相关参数
let recognizerParams: speechRecognizer.StartParams = {
// 会话id
sessionId: SpeechRecognizerManager.sessionId,
// 音频配置信息。
audioInfo: {
// 音频类型。 当前仅支持“pcm”
audioType: 'pcm',
// 音频的采样率。 当前仅支持16000采样率
sampleRate: 16000,
// 音频返回的通道数信息。 当前仅支持通道1。
soundChannel: 1,
// 音频返回的采样位数。 当前仅支持16位
sampleBit: 16
},
// 录音识别
extraParams: {
// 0:实时录音识别 会自动打开麦克风 录制实时语音
"recognitionMode": 0,
// 最大支持音频时长
maxAudioDuration: 60000
}
}
// 调用开始识别方法
SpeechRecognizerManager.asrEngine?.startListening(recognizerParams);
} catch (e) {
console.log("e", e.code, e.message)
}
};
/**
* 开始监听
*/
static startListening2() {
try { // 设置开始识别的相关参数
let recognizerParams: speechRecognizer.StartParams = {
// 会话id
sessionId: SpeechRecognizerManager.sessionId,
// 音频配置信息。
audioInfo: {
// 音频类型。 当前仅支持“pcm”
audioType: 'pcm',
// 音频的采样率。 当前仅支持16000采样率
sampleRate: 16000,
// 音频返回的通道数信息。 当前仅支持通道1。
soundChannel: 1,
// 音频返回的采样位数。 当前仅支持16位
sampleBit: 16
},
// 录音识别
extraParams:
{
// 0:实时录音识别 会自动打开麦克风 录制实时语音
// 1 识别语音文件
"recognitionMode": 1,
// 最大支持音频时长
maxAudioDuration: 60000
},
}
// 调用开始识别方法
SpeechRecognizerManager.asrEngine?.startListening(recognizerParams);
} catch (e) {
console.log("e", e.code, e.message)
}
};
/**
* 取消识别
*/
static cancel() {
SpeechRecognizerManager.asrEngine?.cancel(SpeechRecognizerManager.sessionId)
}
/**
* 释放ai语音转文字引擎
*/
static shutDown() {
SpeechRecognizerManager.asrEngine?.shutdown()
}
/**
* 停止并且释放资源
*/
static async release() {
SpeechRecognizerManager.cancel()
SpeechRecognizerManager.shutDown()
}
/**
* 初始化ai语音转文字引擎
*/
static async init(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}) {
await SpeechRecognizerManager.createEngine()
SpeechRecognizerManager.setListener(callback)
SpeechRecognizerManager.startListening()
}
/**
* 初始化ai语音转文字引擎
*/
static async init2(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}, fileName: string) {
try {
await SpeechRecognizerManager.createEngine()
SpeechRecognizerManager.setListener(callback)
SpeechRecognizerManager.startListening2()
SpeechRecognizerManager.writeAudio(fileName)
} catch (e) {
console.log("e", e.message)
}
}
/**
* 创建引擎
*/
private static async createEngine() {
// 设置创建引擎参数
SpeechRecognizerManager.asrEngine = await speechRecognizer.createEngine(SpeechRecognizerManager.initParamsInfo)
}
/**
* 设置回调
*/
private static setListener(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}) {
// 创建回调对象
let setListener: speechRecognizer.RecognitionListener = {
// 开始识别成功回调
onStart(sessionId: string, eventMessage: string) {
},
// 事件回调
onEvent(sessionId: string, eventCode: number, eventMessage: string) {
},
// 识别结果回调,包括中间结果和最终结果
onResult(sessionId: string, result: speechRecognizer.SpeechRecognitionResult) {
SpeechRecognizerManager.speechResult = result
callback && callback(result)
},
// 识别完成回调
onComplete(sessionId: string, eventMessage: string) {
},
// 错误回调,错误码通过本方法返回
// 如:返回错误码1002200006,识别引擎正忙,引擎正在识别中
// 更多错误码请参考错误码参考
onError(sessionId: string, errorCode: number, errorMessage: string) {
console.log("errorMessage", errorMessage)
},
}
// 设置回调
SpeechRecognizerManager.asrEngine?.setListener(setListener);
}
/**
*
* @param fileName {string} 语音文件名称
*/
private static async writeAudio(fileName: string) {
let ctx = getContext();
let filePath: string = `${ctx.filesDir}/${fileName}.wav`;
let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE);
let buf: ArrayBuffer = new ArrayBuffer(1280);
let offset: number = 0;
while (1280 == fileIo.readSync(file.fd, buf, {
offset: offset
})) {
let uint8Array: Uint8Array = new Uint8Array(buf);
// 调用AI语音引擎识别
SpeechRecognizerManager.asrEngine?.writeAudio(SpeechRecognizerManager.sessionId, uint8Array);
// 延迟40ms
await SpeechRecognizerManager.sleep(40)
offset = offset + 1280;
}
fileIo.closeSync(file);
}
/**
* 加入延迟 否则录音文件识别会出错
* @param time
* @returns
*/
static sleep(time: number) {
const promise = new Promise<void>((resolve: Function) => {
setTimeout(() => {
resolve()
}, time)
})
return promise
}
}
export default SpeechRecognizerManager
更多关于HarmonyOS 鸿蒙Next AI语音02-声音文件转文本的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS(鸿蒙Next)中,AI语音功能支持将声音文件转换为文本。该功能通过调用鸿蒙的AI语音识别API实现。开发者可以使用AudioCapturer
类捕捉音频数据,并将其传递给AI语音识别引擎进行处理。识别结果以文本形式返回。具体流程包括初始化语音识别引擎、配置音频参数、启动录音、获取音频数据、调用识别API、处理识别结果等步骤。鸿蒙的AI语音识别引擎支持多种音频格式和语言模型,能够在设备端或云端进行识别,具体实现方式取决于开发者的需求和设备性能。
更多关于HarmonyOS 鸿蒙Next AI语音02-声音文件转文本的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,AI语音功能支持将声音文件转换为文本。你可以使用AudioRecorder
录制音频,并通过SpeechRecognition
服务将音频文件转换为文本。首先,确保设备具备麦克风权限,然后初始化SpeechRecognition
实例,调用其startListening
方法开始识别。识别完成后,系统会返回文本结果。此功能适用于语音笔记、语音输入等场景,提升交互效率。