HarmonyOS 鸿蒙Next AI语音-实时语音识别
HarmonyOS 鸿蒙Next AI语音-实时语音识别
三文带你轻松上手鸿蒙的AI语音01-实时语音识别
前言
HarmonyOSNext中集成了强大的AI功能。Core Speech Kit(基础语音服务)是它提供的众多AI功能中的一种。
Core Speech Kit(基础语音服务)集成了语音类基础AI能力,包括文本转语音(TextToSpeech)及语音识别(SpeechRecognizer)能力,便于用户与设备进行互动,实现将实时输入的语音与文本之间相互转换。
简单来讲Core Speech Kit主要提供了两大语音AI功能:
- 语音识别
- 文本转语音
语音识别介绍
语音识别功能可以将一段音频信息(短语音模式不超过60s,长语音模式不超过8h)转换为文本。
其中语音识别又可以实现:
- 实时语音转文本
- 声音文件转文本
实时语音转文本
实现流程
先介绍语音识别的流程,后面的文字转语音大同小异
- 申请权限
- 创建AI语音引擎
- 设置监听回调
- 开始监听
tips: 完整代码在每一个功能的末尾,可以结合封装后的代码来阅读
申请权限
申请权限分成3个步骤
- 声明权限
- 检查是否拥有权限
- 申请权限
声明权限
- 在
entry\src\main\module.json5
中添加以下配置代码requestPermissions
{
"module": {
...
"requestPermissions": [
{
"name": "ohos.permission.MICROPHONE",
"reason": "$string:voice_reason",
"usedScene": {
"abilities": [
"FormAbility"
],
"when": "always"
}
}
],
}
}
- 在
entry\src\main\resources\base\element\string.json
添加 申请原因voice_reason
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "voice_reason",
"value": "用于获取用户的录音"
}
]
}
检查权限
实际开发中,我们在申请权限之前可以先调用接口checkAccessTokenSync
,检查下是否已经拥有权限。如果没有,则主动申请权限
申请权限
当我们需要申请某个功能的权限时,可以通过调用 requestPermissionsFromUser
来实现
封装好的权限代码
因为HarmonyOSNext中关于权限的代码,都是没有经过封装的,难以使用。所以这里提供了封装好的版本。
没有封装过的示例代码:
封装好的代码
// 导入必要的模块,包括权限管理相关的功能
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';
export class PermissionManager {
// 静态方法用于检查给定的权限是否已经被授予
static checkPermission(permissions: Permissions[]): boolean {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let tokenID: number = 0;
const bundleInfo =
bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
tokenID = bundleInfo.appInfo.accessTokenId;
if (permissions.length === 0) {
return false;
} else {
return permissions.every(permission =>
abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED ===
atManager.checkAccessTokenSync(tokenID, permission)
);
}
}
// 异步静态方法用于请求用户授权指定的权限
static async requestPermission(permissions: Permissions[]): Promise<boolean> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
const context: Context = getContext() as common.UIAbilityContext;
const result = await atManager.requestPermissionsFromUser(context, permissions);
return !!result.authResults.length && result.authResults.every(authResults => authResults === 0);
}
}
页面中使用权限代码
import { PermissionManager } from '../utils/permissionMananger'
import { Permissions } from '@kit.AbilityKit'
@Entry
@Component
struct Index {
@State
text: string = ""
fn1 = async () => {
const permissions: Permissions[] = ["ohos.permission.MICROPHONE"]
const isPermission = await PermissionManager.checkPermission(permissions)
if (!isPermission) {
PermissionManager.requestPermission(permissions)
}
}
fn2 = () => {
SpeechRecognizerManager.init(res => {
console.log("实时语音识别", JSON.stringify(res))
this.text = res.result
})
}
build() {
Column({ space: 10 }) {
Text(this.text)
Button("申请权限")
.onClick(this.fn1)
Button("实时语音识别")
.onClick(this.fn2)
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
实时语音识别相关步骤
以下主要实现实时语音识别
创建AI语音引擎
创建AI语音引擎主要有以下几个步骤
-
声明AI语音引擎配置参数,主要有语种、区域信息等
-
调用开始创建
createEngine
方法开始创建,并且返回 AI语音实例引擎
设置AI语音监听回调
在开始语音识别之前,需要先设置语音识别回调 setListener
。它主要有以下几个分类
- 开始识别回调
- 事件回调
- 识别结果回调
- 识别完成回调
- 识别错误回调
开始监听实时语音
需要先配置监听的参数,便可以调用startListening
实现语音识别了
参数配置 其中,实时语音识别和语音文件识别的主要配置在 recognitionMode
字段, 0 表示实时语音识别
封装好的语音识别代码
import { speechRecognizer } from '@kit.CoreSpeechKit';
class SpeechRecognizerManager {
private static extraParam: Record<string, Object> = { "locate": "CN", "recognizerMode": "long" };
private static initParamsInfo: speechRecognizer.CreateEngineParams = {
language: 'zh-CN',
online: 1,
extraParams: this.extraParam
};
private static asrEngine: speechRecognizer.SpeechRecognitionEngine | null = null
static speechResult: speechRecognizer.SpeechRecognitionResult | null = null
private static sessionId: string = "asr" + Date.now()
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) {
},
onError(sessionId: string, errorCode: number, errorMessage: string) {
},
}
SpeechRecognizerManager.asrEngine?.setListener(setListener);
}
static startListening() {
let recognizerParams: speechRecognizer.StartParams = {
sessionId: SpeechRecognizerManager.sessionId,
audioInfo: {
audioType: 'pcm',
sampleRate: 16000,
soundChannel: 1,
sampleBit: 16
},
extraParams: {
"recognitionMode": 0,
maxAudioDuration: 60000
}
}
SpeechRecognizerManager.asrEngine?.startListening(recognizerParams);
};
static cancel() {
SpeechRecognizerManager.asrEngine?.cancel(SpeechRecognizerManager.sessionId)
}
static shutDown() {
SpeechRecognizerManager.asrEngine?.shutdown()
}
static async release() {
SpeechRecognizerManager.cancel()
SpeechRecognizerManager.shutDown()
}
static async init(callback: (srr: speechRecognizer.SpeechRecognitionResult) => void = () => {
}) {
await SpeechRecognizerManager.createEngine()
SpeechRecognizerManager.setListener(callback)
SpeechRecognizerManager.startListening()
}
}
export default SpeechRecognizerManager
页面中调用语音识别代码
import { PermissionManager } from '../utils/permissionMananger'
import { Permissions } from '@kit.AbilityKit'
import SpeechRecognizerManager from '../utils/SpeechRecognizerManager'
@Entry
@Component
struct Index {
@State
text: string = ""
fn1 = async () => {
const permissions: Permissions[] = ["ohos.permission.MICROPHONE"]
const isPermission = await PermissionManager.checkPermission(permissions)
if (!isPermission) {
PermissionManager.requestPermission(permissions)
}
}
fn2 = () => {
SpeechRecognizerManager.init(res => {
console.log("实时语音识别", JSON.stringify(res))
this.text = res.result
})
}
build() {
Column({ space: 10 }) {
Text(this.text)
Button("申请权限")
.onClick(this.fn1)
Button("实时语音识别")
.onClick(this.fn2)
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
语音识别结果分析
语音识别成功后的数据格式如下
实时语音识别 {"isFinal":false,"isLast":false,"result":"是"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I 实时语音识别 {"isFinal":false,"isLast":false,"result":"是否给你"}
I
更多关于HarmonyOS 鸿蒙Next AI语音-实时语音识别的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
版本是API14,尝试了但是运行不了,这里尝试了之后发现权限获取可以,引擎创建一直失败并且找不到报错原因
尝试用官方文档的写法之后,点击按钮直接退出软件并报错
更多关于HarmonyOS 鸿蒙Next AI语音-实时语音识别的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
用的是真机吗,模拟器不支持,
用的是真机,不是模拟器,也试过重装系统也不可以,经过定位我能定位创建引擎错误,AI说是创建模型这里出错的,但是代码上没有错误,而且点击也可以找到,
牛的,感谢楼主分享。
谢谢支持,
基本信息
- 姓名: 张三
- 年龄: 28
- 职业: 软件工程师
大赞!!!
大赞!!!
语音识别,如何不重复,我说“你好”,结果出来很多“你好”
找HarmonyOS工作还需要会Flutter技术的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:BV1S4411E7LY/?p=17
通过合理搭配 isCompleted
和 isFinal
来处理即可,
参考 链接,
isCompleted是啥,判断isFinal会导致有一定识别延迟,我对比了下感觉没有安卓的速度快。
设置为long,就是报引擎异常
你好,我反复试了好几遍,不管官网的例子,还是你这个代码,都跑着试了,模式设置为short是正常,但是设置成long,创建引擎时就会报错(https://developer.huawei.com/consumer/cn/doc/harmonyos-references/errorcode-corespeech-0000001748511022#section48792273468),你这里有碰到这种情况吗?
官网文档我看在Beta1中创建引擎时是有这项配置的,但DP2中就没有了,但是我目前用的也是Beta1,
不会,你的运行环境是什么,
和我环境是一样的。你手机重置 出厂设置 试试。
请问第2个例子实时语音识别,需要真机运行吗?试过运行在模拟器时,报错如下。
是的,这个硬件能力需要真机执行。
感谢分享。
感谢评论,
基本信息
- 姓名: 张三
- 年龄: 28
- 职位: 软件工程师
技能
- Python
- Java
- C++
HarmonyOS 鸿蒙Next的AI语音-实时语音识别功能基于鸿蒙系统的分布式能力和AI技术,能够实现高效、低延迟的语音识别。该功能通过鸿蒙的分布式软总线技术,将语音数据在设备间快速传输,结合端侧AI模型进行实时处理,减少对云端依赖,提升响应速度和隐私保护。鸿蒙Next的AI语音识别支持多设备协同,用户可以在不同设备上无缝切换语音交互场景。系统内置的语音识别引擎支持多种语言和方言,并具备噪声抑制、回声消除等优化技术,确保在复杂环境下的识别准确率。开发者可以通过鸿蒙提供的AI Kit接口,集成实时语音识别功能到应用中,支持语音转文字、语音指令识别等场景。
HarmonyOS鸿蒙Next的AI语音实时语音识别功能,依托于先进的神经网络算法和本地化处理,能够在设备端实现高效、低延迟的语音转文字。该技术支持多语种识别,并具备噪声抑制和上下文理解能力,确保在复杂环境下仍能保持高准确率。通过系统级的深度优化,鸿蒙Next的实时语音识别不仅提升了用户体验,还增强了隐私保护,因为所有处理均在设备本地完成,无需上传云端。