三文带你轻松上手鸿蒙的AI语音01-实时语音识别

三文带你轻松上手鸿蒙的AI语音01-实时语音识别

前言

HarmonyOSNext中集成了强大的AI功能。Core Speech Kit(基础语音服务)是它提供的众多AI功能中的一种。

Core Speech Kit(基础语音服务)集成了语音类基础AI能力,包括文本转语音(TextToSpeech)及语音识别(SpeechRecognizer)能

力,便于用户与设备进行互动,实现将实时输入的语音与文本之间相互转换。

简单来讲Core Speech Kit主要提供了两大语音AI功能:

  1. 语音识别
  2. 文本转语音

语音识别介绍

语音识别功能可以将一段音频信息(短语音模式不超过60s,长语音模式不超过8h)转换为文本。

其中语音识别又可以实现:

  1. 实时语音转文本
  2. 声音文件转文本

实时语音转文本

实现流程

先介绍语音识别的流程,后面的文字转语音大同小异

  1. 申请权限
  2. 创建AI语音引擎
  3. 设置监听回调
  4. 开始监听

tips: 完整代码在每一个功能的末尾,可以结合封装后的代码来阅读

申请权限

image-20240828222453973

因为在开发功能过程中,需要调用手机的麦克风功能。所以需要主动申请权限。

image-20240828222047223

申请权限分成3个步骤

  1. 声明权限
  2. 检查是否拥有权限
  3. 申请权限

声明权限

  1. \entry\src\main\module.json5中添加以下配置代码 requestPermissions

    {"module": {..."requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "$string:voice_reason","usedScene": {"abilities": ["FormAbility"],"when": "always"}}],}
    }
    
  2. \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中关于权限的代码,都是没有经过封装的,难以使用。所以这里提供了封装好的版本。

没有封装过的示例代码:

image-20240828224125035


封装好的代码

entry\src\main\ets\utils\permissionMananger.ets

// 导入必要的模块,包括权限管理相关的功能
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';export class PermissionManager {// 静态方法用于检查给定的权限是否已经被授予static checkPermission(permissions: Permissions[]): boolean {// 创建一个访问令牌管理器实例let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();// 初始化tokenID为0,稍后将获取真实的tokenIDlet tokenID: number = 0;// 获取本应用的包信息const bundleInfo =bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);// 设置tokenID为应用的访问令牌IDtokenID = bundleInfo.appInfo.accessTokenId;// 如果没有传入任何权限,则返回false表示没有权限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();// 获取上下文(这里假设getContext是一个可以获取到UI能力上下文的方法)let context: Context = getContext() as common.UIAbilityContext;// 请求用户授权指定的权限const result = await atManager.requestPermissionsFromUser(context, permissions);// 检查请求结果是否成功(authResults数组中每个元素都应该是0,表示成功)return !!result.authResults.length && result.authResults.every(authResults => authResults === 0);}
}

页面中使用权限代码

Index.ets

import { PermissionManager } from '../utils/permissionMananger'
import { Permissions } from '@kit.AbilityKit'@Entry
@Component
struct Index {// 1 申请权限fn1 = async () => {// 准备好需要申请的权限 麦克风权限const permissions: Permissions[] = ["ohos.permission.MICROPHONE"]// 检查是否拥有权限const isPermission = await PermissionManager.checkPermission(permissions)if (!isPermission) {//   如果没权限,就主动申请PermissionManager.requestPermission(permissions)}}build() {Column() {Button("申请权限").onClick(this.fn1)}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}

image-20240828224918956

实时语音识别相关步骤

以下主要实现实时语音识别

创建AI语音引擎

创建AI语音引擎主要有以下几个步骤

  1. 声明AI语音引擎配置参数,主要有语种、区域信息等

    image-20240828225611828

  2. 调用开始创建 createEngine 方法开始创建,并且返回 AI语音实例引擎

设置AI语音监听回调

在开始语音识别之前,需要先设置语音识别回调 setListener 。它主要有以下几个分类

  1. 开始识别回调
  2. 事件回调
  3. 识别结果回调
  4. 识别完成回调
  5. 识别错误回调

image-20240828225832286

开始监听实时语音

需要先配置监听的参数,便可以调用startListening实现语音识别了

参数配置 其中,实时语音识别和语音文件识别的主要配置在 recognitionMode 字段, 0 表示实时语音识别

image-20240828230419298

封装好的语音识别代码

\entry\src\main\ets\utils\SpeechRecognizerManager.ets

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',/*** 离线模式:1*/online: 1,extraParams: this.extraParam};/*** 引擎*/private static asrEngine: speechRecognizer.SpeechRecognitionEngine | null = null/*** 录音结果*/static speechResult: speechRecognizer.SpeechRecognitionResult | null = null/*** 会话ID*/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 = resultcallback && callback(result)},// 识别完成回调onComplete(sessionId: string, eventMessage: string) {},// 错误回调,错误码通过本方法返回// 如:返回错误码1002200006,识别引擎正忙,引擎正在识别中// 更多错误码请参考错误码参考onError(sessionId: string, errorCode: number, errorMessage: string) {},}// 设置回调SpeechRecognizerManager.asrEngine?.setListener(setListener);}/*** 开始监听* */static startListening() {// 设置开始识别的相关参数let recognizerParams: speechRecognizer.StartParams = {// 会话idsessionId: 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);};/*** 取消识别*/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()}
}export default SpeechRecognizerManager

页面中调用语音识别代码

import { PermissionManager } from '../utils/permissionMananger'
import { Permissions } from '@kit.AbilityKit'
import SpeechRecognizerManager from '../utils/SpeechRecognizerManager'@Entry
@Component
struct Index {@Statetext: string = ""// 1 申请权限fn1 = async () => {// 准备好需要申请的权限 麦克风权限const permissions: Permissions[] = ["ohos.permission.MICROPHONE"]// 检查是否拥有权限const isPermission = await PermissionManager.checkPermission(permissions)if (!isPermission) {//   如果没权限,就主动申请PermissionManager.requestPermission(permissions)}}// 2 实时语音识别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)}
}

PixPin_2024-08-28_23-19-49


语音识别结果分析

语音识别成功后的数据格式如下

实时语音识别 {"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":true,"isLast":false,"result":"是否给你承诺的太多?"}
I     实时语音识别 {"isFinal":false,"isLast":false,"result":""}

其中需要关注的是:

  1. 识别功能是持续触发的,当收集到声音时持续触发

  2. isFinal 表示一个句子是否结束

    image-20240828232352345

  3. isLast 表示这一次语音识别是否结束

总结

HarmonyOSNext中集成了强大的AI功能。Core Speech Kit(基础语音服务)是它提供的众多AI功能中的一种。

Core Speech Kit(基础语音服务)集成了语音类基础AI能力,包括文本转语音(TextToSpeech)及语音识别(SpeechRecognizer)能

力,便于用户与设备进行互动,实现将实时输入的语音与文本之间相互转换。

简单来讲Core Speech Kit主要提供了两大语音AI功能:

  1. 语音识别
  2. 文本转语音

其中语音识别又可以实现:

  1. 实时语音转文本
  2. 声音文件转文本

本文主要实现了 实时语音转文本声音文件转文本 将会在下文讲解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/417760.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis - 主从复制

文章目录 目录 文章目录 前言 1. 配置 建立复制 断开复制 传输延时 2. 主从拓扑结构 一主一从 一主多从 树状 三. 原理 数据同步 psync replicationid/replid(复制id) master_replid 和 master_replid2 offset (偏移量) psync 运行流程 全量复制 部分复制 …

echarts多个环形图

echarts图表集 var dataValue [{name:今日待分配方量,value:49}, {name:今日已分配方量,value:602}, {name:今日完成方量,value:1037}]var piedata1 [{name: 1#拌和机,value: 20},{name: 2#拌和机,value: 22},{name: 3#拌和机 ,value: 17},{name: 4#拌和机,value: 18},{name…

基于“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展应用

近年来&#xff0c;国内外学者在生态系统的敏感性、适应能力和潜在影响等方面开展了大量的生态脆弱性研究&#xff0c;他们普遍将生态脆弱性概念与农牧交错带、喀斯特地区、黄土高原区、流域、城市等相结合&#xff0c;评价不同类型研究区的生态脆弱特征&#xff0c;其研究内容…

【JAVA基础】StringUtils.isEmpty、StringUtils.isBlank()、Objects.isNull()三者区别

&#x1f4dd;个人主页&#x1f339;&#xff1a;个人主页 ⏩收录专栏⏪&#xff1a;日常经验 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339;&#xff0c;让我们共同进步&#xff01; 总是区分不清楚这几个的差别&#xff1a;我们来直接验证一下&#…

活动系统开发之采用设计模式与非设计模式的区别-数据库设计及代码设计

1、数据库ER图 2、应用框架选用 PHP语言对应的thinkphp6.1应用框架 3、功能代码设计(后端) a、父类Base.php i&#xff1a;控制登录&#xff0c;只能登录后管理员才能操作&#xff1b; ii&#xff1a;控制按钮权限&#xff0c;管理员不仅要登录&#xff0c;且必须要有对应菜单…

【操作系统】进程同步之共享内存

进程的线程共享进程资源&#xff0c;而进程共享计算机资源。 在某种程度上&#xff0c;多进程是共享物理内存的。 由于操作系统的进程管理&#xff0c;不同的进程有自己独立的内存空间&#xff0c;互不干扰。 但是共享内存可以打破这个限制。 共享内存允许不相关的进程访问同…

Linux云计算学习笔记11 (计划任务)

一.基本概念 在Linux操作系统中&#xff0c;除了用户即时执行的命令操作以外&#xff0c;还可以配置在指定的时间、指定的日期执行预先计划好的系统管理任务&#xff08;如定期备份、定期采集监测数据&#xff09;。试想一下&#xff0c;如果系统要求在业务不那么繁忙的半夜进行…

【2024数学建模国赛赛题思路】C题第四套思路已出丨仅供参考

问题一思路分析 假定各种农作物未来的预期销售量、种植成本、亩产量和销售价格相对于2023年保持稳定&#xff0c;每季种植的农作物在当季销售。如果某种作物每季的总产量超过相应的预期销售量&#xff0c;超过部分不能正常销售。请针对以下两种情况&#xff0c;分别给出该乡村…

免费申请aws一年免费服务器使用教程

由于近期要测试一个公网项目&#xff0c;对比之下&#xff0c;选择了aws服务器&#xff0c;免费使用一年。 准备&#xff1a;一个visa信用卡即可&#xff0c;需要一个外网邮箱&#xff08;我这边使用的hotmail&#xff09; 注册的步骤不再赘述&#xff0c;切记几个点&#xff0…

景联文科技:专业图像采集服务,助力智能图像分析

景联文科技是专业数据服务公司&#xff0c;致力于为人工智能企业提供从数据采集、清洗到标注的全流程解决方案。协助客户解决AI开发过程中数据处理环节的关键问题&#xff0c;助力企业实现智能化转型。 1.多样化的图像采集服务 景联文科技提供多样化的图像采集服务&#xff0c…

udp网络通信 socket

套接字是实现进程间通信的编程。IP可以标定主机在全网的唯一性&#xff0c;端口可以标定进程在主机的唯一性&#xff0c;那么socket通过IP端口号就可以让两个在全网唯一标定的进程进行通信。 套接字有三种&#xff1a; 域间套接字&#xff1a;实现主机内部的进程通信的编程 …

Kettle发送邮件功能如何配置以实现自动化?

kettle发送邮件如何设置&#xff1f;Kettle配置发送邮件的方法&#xff1f; Kettle发送邮件功能能够帮助用户在数据处理过程中自动发送电子邮件&#xff0c;极大地提高了工作效率。AokSend将详细介绍如何配置Kettle发送邮件功能&#xff0c;以实现自动化操作。 Kettle发送邮件…

C++笔记19•数据结构:红黑树(RBTree)•

红黑树 1.简介&#xff1a; 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍…

使用百度飞桨PaddleOCR进行OCR识别

1、代码及文档 代码&#xff1a;https://github.com/PaddlePaddle/PaddleOCR?tabreadme-ov-file 介绍文档&#xff1a;https://paddlepaddle.github.io/PaddleOCR/ppocr/overview.html 2、依赖安装 在使用过程中需要安装库&#xff0c;可以依据代码运行过程中的提示安装。…

MySQL Email验证流程详解:从注册到激活!

MySQL Email通知系统搭建教程&#xff01;如何从MySQL发送邮件&#xff1f; MySQL Email验证是一个至关重要的环节&#xff0c;它确保了用户注册过程的安全性和有效性。AokSend将详细介绍从用户注册到MySQL Email激活的完整流程&#xff0c;帮助开发者更好地理解和实现这一功能…

视频编码与传输 学习笔记 1 一些视频压缩算法的介绍

大概是这么个结构&#xff1a; 说白了&#xff0c;就是视频太大&#xff0c;不压缩不行&#xff0c;因此我们会用压缩比非常夸张但对于视频来说效果很好的压缩方法先对视频压缩&#xff08;source coding&#xff09;然后把压缩后的视频发出去&#xff0c;要看的时候再解压。 就…

青岛实训 8月22号 day34

一、回顾 1.主从复制&#xff08;高可用&#xff09; 2.传统的主从复制 3.gtids事务型的主从复制 4.注意 1&#xff09;server_id唯一 2&#xff09;8.X版本需要get_ssl_pub_key 3&#xff09;5.X不需要 4&#xff09;change master to 5&#xff09;stop | start slave 5.非…

HIVE 数据仓库工具之第二部分(数据库相关操作)

HIVE 数据仓库工具之第二部分&#xff08;数据库相关操作&#xff09; 一、Hive 对数据库的操作1.1 创建数据库1.1.1 创建数据库语法1.1.3 示例 1.2 使用数据库1.2.1 使用数据库语法1.2.2 示例 1.3 修改数据库1.3.1 修改数据库的语法1.3.2 示例 1.4 删除数据库1.4.1 删除数据库…

Aloudata CAN 发布:真正实现企业指标的管理、研发与消费一体化

对于企业的运营和管理来说&#xff0c;集自动化数据生产、业务化数据语言、智能化数据分析的指标管理方案至关重要。 指标是对业务过程和结果的度量&#xff0c;正如德鲁克所说&#xff0c;“如果无法度量就无法管理”。 指标管理痛点爆发&#xff0c;管、研、用一体方案备受青…

python-简单的dos攻击

前言 这个是DOS攻击学习(注意&#xff1a;千万别去攻击有商业价值的服务器或应用&#xff0c;不然会死的很惨(只有一个IP通过公网访问容易被抓),前提是网站没有攻击防御) 创建一个以python编写的后端web服务(好观察) 安装flask pip install flask from flask import Flaskapp …