Unity 工具 之 Azure 微软连续语音识别ASR的简单整理

Unity 工具 之 Azure 微软连续语音识别ASR的简单整理

目录

Unity 工具 之 Azure 微软连续语音识别ASR的简单整理

一、简单介绍

二、实现原理

三、注意实现

四、实现步骤

 五、关键脚本


一、简单介绍

Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。

本节介绍,这里在使用微软的Azure 进行语音合成的两个方法的做简单整理,这里简单说明,如果你有更好的方法,欢迎留言交流。

官网注册:

面向学生的 Azure - 免费帐户额度 | Microsoft Azure

官网技术文档网址:

技术文档 | Microsoft Learn

官网的TTS:

语音转文本快速入门 - 语音服务 - Azure AI services | Microsoft Learn

Azure Unity SDK  包官网:

安装语音 SDK - Azure Cognitive Services | Microsoft Learn

SDK具体链接:

https://aka.ms/csspeech/unitypackage

二、实现原理

1、官网申请得到语音识别对应的 SPEECH_KEY 和 SPEECH_REGION

2、因为语音识别需要用到麦克风,移动端需要申请麦克风权限

3、开启语音识别,监听语音识别对应事件,即可获取到识别结果

三、注意实现

1、注意如果有卡顿什么的,注意主子线程切换,可能可以适当解决你的卡顿现象

2、注意电脑端(例如windows)运行可以不申请麦克风权限,但是移动端(例如Android)运行要申请麦克风权限,不然无法开启识别成功,可能会报错:Exception with an error code: 0x15

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

System.ApplicationException: Exception with an error code: 0x15 at Microsoft.CognitiveServices.Speech.Internal.SpxExceptionThrower.ThrowIfFail (System.IntPtr hr) [0x00000] in <00000000000000000000000000000000>:0 at Microsoft.CognitiveServices.Speech.Recognizer.StartContinuousRecognition () [0x00000] in <00000000000000000000000000000000>:0 at Microsoft.CognitiveServices.Speech.Recognizer.DoAsyncRecognitionAction (System.Action recoImplAction) [0x00000] in <00000000000000000000000000000000>:0 at System.Threading.Tasks.Task.Execute () [0x00000] in <00000000000000000000000000000000>:0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0 at System.Threading.Tasks.Task.ExecuteWithThreadLocal (System.Threading.Tasks.Task& currentTaskSlot) [0x00000] in

四、实现步骤

1、下载好SDK 导入

2、简单的搭建场景

3、编写对应脚本,测试语音识别功能

4、把测试脚本添加到场景中,并赋值

5、如果移动端,例如 Android 端,勾选如下,添加麦克风权限

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

5、运行,点击对应按钮,开始识别,Console 中可以看到识别结果

 五、关键脚本

1、TestSpeechRecognitionHandler


using UnityEngine;
using UnityEngine.Android;
using UnityEngine.UI;

public class TestSpeechRecognitionHandler : MonoBehaviour
{
    #region Data
    
    /// <summary>
    /// 按钮,文本
    /// </summary>
    public Button QuitButton;
    public Button ASRButton;
    public Button StopASRButton;
    public Text ASRText;

    /// <summary>
    /// m_SpeechAndKeywordRecognitionHandler
    /// </summary>
    SpeechRecognitionHandler m_SpeechAndKeywordRecognitionHandler;
    #endregion
    #region Liefecycle function

    /// <summary>
    /// Start
    /// </summary>
    void Start()
    {
        QuitButton.onClick.AddListener(OnClickQuitButton);
        ASRButton.onClick.AddListener(OnClickASRButton);
        StopASRButton.onClick.AddListener(OnClickStopASRButton);

        // 请求麦克风权限
        RequestMicrophonePermission();
    }

    /// <summary>
    /// 应用退出
    /// </summary>
    async void OnApplicationQuit() {
        await m_SpeechAndKeywordRecognitionHandler.StopContinuousRecognizer();
    }

    #endregion

    #region Private function
    /// <summary>
    /// RequestMicrophonePermission
    /// </summary>
    void RequestMicrophonePermission()
    {
        // 检查当前平台是否为 Android
        if (Application.platform == RuntimePlatform.Android)
        {
            // 检查是否已经授予麦克风权限
            if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
            {
                // 如果没有权限,请求用户授权
                Permission.RequestUserPermission(Permission.Microphone);
            }
        }
        else
        {
            // 在其他平台上,可以执行其他平台特定的逻辑
            Debug.LogWarning("Microphone permission is not needed on this platform.");
        }

        SpeechInitialized();
    }

    /// <summary>
    /// SpeechInitialized
    /// </summary>
    private void SpeechInitialized() {
        ASRText.text = "";
        m_SpeechAndKeywordRecognitionHandler = new SpeechRecognitionHandler();
        m_SpeechAndKeywordRecognitionHandler.onRecognizingAction = (str) => { Debug.Log("onRecognizingAction: " + str); };
        m_SpeechAndKeywordRecognitionHandler.onRecognizedSpeechAction = (str) => { Loom.QueueOnMainThread(() => ASRText.text += str);  Debug.Log("onRecognizedSpeechAction: " + str); };
        m_SpeechAndKeywordRecognitionHandler.onErrorAction = (str) => { Debug.Log("onErrorAction: " + str); };
        m_SpeechAndKeywordRecognitionHandler.Initialized();
    }
    /// <summary>
    /// OnClickQuitButton
    /// </summary>
    private void OnClickQuitButton() {
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false;

#else
                Application.Quit();
#endif 
    }
    /// <summary>
    /// OnClickASRButton
    /// </summary>
    private void OnClickASRButton() {
        m_SpeechAndKeywordRecognitionHandler.StartContinuousRecognizer();
    }

    /// <summary>
    /// OnClickStopASRButton
    /// </summary>
    private async void OnClickStopASRButton()
    {
        await m_SpeechAndKeywordRecognitionHandler.StopContinuousRecognizer();
    }

    #endregion
}

2、SpeechRecognitionHandler

using UnityEngine;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using System;
using Task = System.Threading.Tasks.Task;

/// <summary>
/// 语音识别转文本和关键词识别
/// </summary>
public class SpeechRecognitionHandler
{
    #region Data

    /// <summary>
    /// 
    /// </summary>
    const string TAG = "[SpeechAndKeywordRecognitionHandler] ";

    /// <summary>
    /// 识别配置
    /// </summary>
    private SpeechConfig m_SpeechConfig;

    /// <summary>
    /// 音频配置
    /// </summary>
    private AudioConfig m_AudioConfig;

    /// <summary>
    /// 语音识别
    /// </summary>
    private SpeechRecognizer m_SpeechRecognizer;

    /// <summary>
    /// LLM 大模型配置
    /// </summary>
    private ASRConfig m_ASRConfig;

    /// <summary>
    /// 识别的事件
    /// </summary>
    public Action<string> onRecognizingAction;
    public Action<string> onRecognizedSpeechAction;
    public Action<string> onErrorAction;
    public Action<string> onSessionStoppedAction;


    #endregion
    #region Public function

    /// <summary>
    /// 初始化
    /// </summary>
    /// <returns></returns>
    public async void Initialized()
    {
        m_ASRConfig = new ASRConfig();

        Debug.Log(TAG + "m_LLMConfig.AZURE_SPEECH_RECOGNITION_LANGUAGE " + m_ASRConfig.AZURE_SPEECH_RECOGNITION_LANGUAGE);
        Debug.Log(TAG + "m_LLMConfig.AZURE_SPEECH_REGION " + m_ASRConfig.AZURE_SPEECH_REGION);

        m_SpeechConfig = SpeechConfig.FromSubscription(m_ASRConfig.AZURE_SPEECH_KEY, m_ASRConfig.AZURE_SPEECH_REGION);
        m_SpeechConfig.SpeechRecognitionLanguage = m_ASRConfig.AZURE_SPEECH_RECOGNITION_LANGUAGE;


        m_AudioConfig = AudioConfig.FromDefaultMicrophoneInput();

        Debug.Log(TAG + " Initialized 2 ====");

        // 根据自己需要处理(不需要也行)
        await Task.Delay(100);
    }

    #endregion

    #region Private function

    /// <summary>
    /// 设置识别回调事件
    /// </summary>
    private void SetRecoginzeCallback()
    {
        Debug.Log(TAG + " SetRecoginzeCallback == ");
        if (m_SpeechRecognizer != null)
        {
            m_SpeechRecognizer.Recognizing += OnRecognizing;

            m_SpeechRecognizer.Recognized += OnRecognized;

            m_SpeechRecognizer.Canceled += OnCanceled;

            m_SpeechRecognizer.SessionStopped += OnSessionStopped;

            Debug.Log(TAG+" SetRecoginzeCallback OK ");
        }
    }

    #endregion

    #region Callback
    /// <summary>
    /// 正在识别
    /// </summary>
    /// <param name="s"></param>
    /// <param name="e"></param>
    private void OnRecognizing(object s, SpeechRecognitionEventArgs e)
    {
        Debug.Log(TAG + "RecognizingSpeech:" + e.Result.Text + " :[e.Result.Reason]:" + e.Result.Reason);
        if (e.Result.Reason == ResultReason.RecognizingSpeech )
        {
            Debug.Log(TAG + " Trigger onRecognizingAction is null :" + onRecognizingAction == null);

            onRecognizingAction?.Invoke(e.Result.Text);
        }
    }

    /// <summary>
    /// 识别结束
    /// </summary>
    /// <param name="s"></param>
    /// <param name="e"></param>
    private void OnRecognized(object s, SpeechRecognitionEventArgs e)
    {
        Debug.Log(TAG + "RecognizedSpeech:" + e.Result.Text + " :[e.Result.Reason]:" + e.Result.Reason);
        if (e.Result.Reason == ResultReason.RecognizedSpeech )
        {
            bool tmp = onRecognizedSpeechAction == null;
            Debug.Log(TAG + " Trigger onRecognizedSpeechAction is null :" + tmp);

            onRecognizedSpeechAction?.Invoke(e.Result.Text);
        }
    }

    /// <summary>
    /// 识别取消
    /// </summary>
    /// <param name="s"></param>
    /// <param name="e"></param>
    private void OnCanceled(object s, SpeechRecognitionCanceledEventArgs e)
    {
        Debug.LogFormat(TAG+"Canceled: Reason={0}", e.Reason );

        if (e.Reason == CancellationReason.Error)
        {
            onErrorAction?.Invoke(e.ErrorDetails);
        }
    }

    /// <summary>
    /// 会话结束
    /// </summary>
    /// <param name="s"></param>
    /// <param name="e"></param>
    private void OnSessionStopped(object s, SessionEventArgs e)
    {
        Debug.Log(TAG+"Session stopped event." );
        onSessionStoppedAction?.Invoke("Session stopped event.");
    }

    
    #endregion


    #region 连续语音识别转文本

    /// <summary>
    /// 开启连续语音识别转文本
    /// </summary>
    public void StartContinuousRecognizer()
    {
        Debug.LogWarning(TAG + "StartContinuousRecognizer");

        try
        {
            // 转到异步中(根据自己需要处理)
            Loom.RunAsync(async () => {
                try
                {
                    if (m_SpeechRecognizer != null)
                    {
                        m_SpeechRecognizer.Dispose();
                        m_SpeechRecognizer = null;
                    }

                    if (m_SpeechRecognizer == null)
                    {
                        m_SpeechRecognizer = new SpeechRecognizer(m_SpeechConfig, m_AudioConfig);

                        SetRecoginzeCallback();
                    }

                    await m_SpeechRecognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);

                    Loom.QueueOnMainThread(() => {
                        Debug.LogWarning(TAG + "StartContinuousRecognizer QueueOnMainThread ok");
                    });
                    Debug.LogWarning(TAG + "StartContinuousRecognizer RunAsync ok");
                }
                catch (Exception e)
                {
                    Loom.QueueOnMainThread(() =>
                    {
                        Debug.LogError(TAG + " StartContinuousRecognizer 0 " + e);
                    });
                }

            });
        }
        catch (Exception e)
        {
            Debug.LogError(TAG + " StartContinuousRecognizer 1 " + e);
        }

    }

    /// <summary>
    /// 结束连续语音识别转文本
    /// </summary>
    public async Task StopContinuousRecognizer()
    {
        try
        {
            if (m_SpeechRecognizer != null)
            {
                await m_SpeechRecognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
                //m_SpeechRecognizer.Dispose();
                //m_SpeechRecognizer = null;
                Debug.LogWarning(TAG + " StopContinuousRecognizer");
            }
        }
        catch (Exception e)
        {
            Debug.LogError(TAG + " StopContinuousRecognizer Exception : " + e);
        }
    }

    #endregion

}

3、ASRConfig



public class ASRConfig 
{
    #region Azure ASR

    /// <summary>
    /// AZURE_SPEECH_KEY
    /// </summary>
    public virtual string AZURE_SPEECH_KEY { get; } = @"098dc5aa21a14758a347dcac36d7eb66";
    /// <summary>
    /// AZURE_SPEECH_REGION
    /// </summary>
    public virtual string AZURE_SPEECH_REGION { get; } = @"eastasia";
    /// <summary>
    /// AZURE_SPEECH_RECOGNITION_LANGUAGE
    /// </summary>
    public virtual string AZURE_SPEECH_RECOGNITION_LANGUAGE { get; } = @"zh-CN";

    #endregion
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

书客、明基、好视力护眼台灯大比拼,哪款更胜一筹?

在现代生活中&#xff0c;我们经常面对着各种电子屏幕&#xff0c;给眼睛造成了一定的压力&#xff0c;时间一长&#xff0c;会发现眼睛很疲劳。很多家长仔细观察&#xff0c;当孩子长时间处在不合适地灯光下玩耍、学习&#xff0c;会发现他们有揉眼的动作&#xff0c;这就是不…

Mac 使用nvm use命令无法切换node版本

解决方案&#xff1a;先卸载使用brew安装的node&#xff08; 具体操作请移步使用brew卸载node&#xff09;&#xff0c;再使用nvm use命令切换node版本。 问题复现&#xff1a;使用nvm use命令显示切换成功&#xff0c;但是实际版本还是原来的node版本&#xff0c;应该是与bre…

HTTP响应码

1&#xff1a;1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码。 2&#xff1a;2xx(成功) 表示成功处理了请求的状态代码。 3&#xff1a;3xx(重定向) 表示要完成请求&#xff0c;需要进一步操作。 通常&#xff0c;这些状态代码用来重定向。 4&#xff1a;4…

SpringBoot原理(@Conditional)—三种自动配置方法、步骤详解

简介&#xff1a;我们一直在说基于SpringBoot开发简单、快捷&#xff0c;但是总是不太清楚为什么会有这样的便利&#xff0c;对于开发人员来说我们不仅要知其然&#xff0c;还要知其所以然&#xff0c;这篇文章就是说明SpringBoot的底层原理&#xff0c;让读者对SpringBoot底层…

深入理解 Flink(五)Flink Standalone 集群启动源码剖析

前言 Flink 集群的逻辑概念&#xff1a; JobManager(StandaloneSessionClusterEntrypoint) TaskManager(TaskManagerRunner) Flink 集群的物理概念&#xff1a; ResourceManager(管理集群所有资源&#xff0c;管理集群所有从节点) TaskExecutor(管理从节点资源&#xff0c;接…

order by 与 分页 的冲突

order by 与 分页 的冲突 问题背景 Oracle拼接SQL&#xff0c;JAVA使用SQLQueryExecutor执行拼接的SQL&#xff0c;SQL如下&#xff1a; SELECT col_key, col_other_info FROM tb_tableName WHERE col_where_info 一些筛选条件 order by col_updatetime desc 该表中的数…

python 计数器

这个Python脚本定义了一个名为new_counter()的函数&#xff0c;它读取系统时间并将其与存储在文件中的时间进行比较。然后根据比较结果更新存储在另一个文件中的计数器值。如果系统时间与存储的时间匹配&#xff0c;则计数器值增加1。如果系统时间与存储的时间不匹配&#xff0…

JS逆向实战案例1——某房地产url动态生成

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、 反爬分析 url&#xff1a;aHR0cHM6Ly9uZXdob3VzZS4wNTU3ZmRjLmNvbQ 该站点项目url通过点击JS生成&#xff0c;project_id与生成后…

SQL SERVER 19安装 SQL Prompt 10.02版本

SQL Prompt最新版官网下载地址&#xff1a;https://download.red-gate.com/SQLPromptDownload.exe 下载完成后&#xff0c;断开网络&#xff0c;全部点下一步。 注册机会报毒&#xff0c;安装前请先关闭杀毒软件&#xff01; 下载好附件之后解压&#xff0c;打开SQLPrompt_7…

深入理解 Flink(六)Flink Job 提交和 Flink Graph 详解

Flink Program 编程套路回顾 1、获取执行环境对象 StreamExecutionEnvironment env StreamExecutionEnvironment.getExecutionEnvironment(); 2、通过执行环境对象&#xff0c;注册数据源 Source&#xff0c;得到数据抽象 DataStream ds env.socketTextStream(...) 3、调用数…

【RabbitMQ】2 RabbitMQ介绍与架构

目录 简介架构Connection 和Channel关系工作流程生产者发送消息的流程消费者接收消息的过程 RabbitMQ数据存储存储机制 安装和配置RabbitMQRabbitMQ常用操作命令 简介 RabbitMQ&#xff0c;俗称“兔子MQ”&#xff08;可见其轻巧&#xff0c;敏捷&#xff09;&#xff0c;是目…

AI系统ChatGPT网站系统源码AI绘画详细搭建部署教程,支持GPT语音对话+DALL-E3文生图+GPT-4多模态模型识图理解

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…

2019年认证杯SPSSPRO杯数学建模C题(第一阶段)保险业的数字化变革全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 基于 CART 决策树和 SVR 的客户续保概率预测 C题 保险业的数字化变革 原题再现&#xff1a; 车险&#xff0c;即机动车辆保险。保险自身是一种分散风险、消化损失的经济补偿制度&#xff0c;车险即为分散机动车辆在行驶过程中可能发作的未知风…

PPT插件-大珩助手-修改素材名称及搜索功能演示

修改素材名称及搜索功能演示 大珩助手的素材库&#xff0c;支持修改素材的名称&#xff0c;支持动态查找素材&#xff0c;删除素材 移动素材到其他分类 软件介绍 PPT大珩助手是一款全新设计的Office PPT插件&#xff0c;它是一款功能强大且实用的PPT辅助工具&#xff0c;支持…

服务网格 Service Mesh

什么是服务网格&#xff1f; 服务网格是一个软件层&#xff0c;用于处理应用程序中服务之间的所有通信。该层由容器化微服务组成。随着应用程序的扩展和微服务数量的增加&#xff0c;监控服务的性能变得越来越困难。为了管理服务之间的连接&#xff0c;服务网格提供了监控、记…

使用阿里云镜像创建一个Spring Boot项目

由于现在的idea在创建项目时已经不支持Java8版本了&#xff0c;如果我们还想用8版本&#xff0c;可以使用阿里云镜像创建。所以得改变原有的地址为&#xff1a;https://start.aliyun.com springboot版本选择2开头的任意版本的。 1.配置6个依赖 2.改变下载依赖地址 下载依赖默认…

语境化语言表示模型-ELMO、BERT、GPT、XLnet

一.语境化语言表示模型介绍 语境化语言表示模型&#xff08;Contextualized Language Representation Models&#xff09;是一类在自然语言处理领域中取得显著成功的模型&#xff0c;其主要特点是能够根据上下文动态地学习词汇和短语的表示。这些模型利用了上下文信息&#xf…

Linux ----冯诺依曼体系结构与操作系统

目录 前言 一、冯诺依曼体系结构 二、为什么选择冯诺依曼体系结构&#xff1f; 三、使用冯诺依曼结构解释问题 问题1&#xff1a; 问题2: 四、操作系统 1.操作系统是什么 2.为什么需要操作系统 3.操作系统怎样管理的 4.如何给用户提供良好环境 五、我们是怎样调用系…

【冥想X理工科思维】场景6:我被调岗了…

冥想音频合集&#xff1a;职场解压冥想音频 压力场景&#xff1a; 领导把我调换到并不喜欢也不擅长的岗位&#xff0c;如何借助冥想面对职业发展或公司变动时的不确定性和焦虑&#xff1f; 点击看大图&#xff1a; 详细说明&#xff1a; 在面对工作中的挑战时&#xff0c;制定一…