[chatgpt+Azure]unity AI二次元小女友之使用微软Azure服务实现RestfulApi->语音识别+语音合成

news2024/11/24 9:51:37

1.简述

        如题所述,这个小项目是在unity引擎端,使用了chatgpt+微软azure的一个AI二次元女友对话的项目,实现原理也比较简单,即在unity端实现AI二次元女友的交互界面,接入chatgpt-3.5-turbo的api接口,借助chatgpt的自然语言生成能力,作为这个项目的聊天引擎。聊天功能也比较简单,通过接入微软Azure的语音识别api,在unity客户端接入麦克风采集说话的声音,调用语音识别api返回识别的文本,再通过拼接prompt,调用chatgpt接口,得到回复信息文本之后,再调用azure的语音合成接口,得到音频,最后播放出来,关联live2d模型的口型同步,这样基本上就实现了我希望的效果。这个项目我已经在Gitee开源有一段时间了,本来也有计划要写一些相关文档的,一直没有时间,这次就抽时间把项目里涉及到的Azure语音服务部分的代码整理成文档,也方面想学习这个小伙伴一个参考。

2.微软Azure

        微软 Azure是微软基于云计算的操作系统,是微软“软件和服务”技术的名称。Windows Azure的主要目标是为开发者提供一个平台,帮助开发可运行在云服务器、数据中心、Web和PC上的应用程序。 说这么多,其实Azure就是微软提供给开发者各种云服务,其中就包括了AI相关的服务,比如语音服务。

Azure地址传送门:

云计算服务 | Microsoft Azure

        关于Azure服务的使用,需要首先申请一个Azure的账号,申请账号成功之后,就可以申请使用Azure的各种服务了。Azure提供了不少免费的服务,对于白嫖党来说简直就是福利。但是这里有一点需要说明了,就是申请Azure账号的时候,需要填写一个visa或万事达的信用卡账号,如果没有的话,就申请不了账号了,这个可能会是一个门槛。注册成功之后,微软会给你的账号赠送200美元的体验金,这个有效期有一年的时间,也算是一个相当好的福利了,就是信用卡的问题,必须解决,这里算是一个经验提示吧。

        在申请语音服务的订阅过程,第一个月可以申请试用的订阅,有效期是一个月的时间,可以免费提供50万字的语音合成额度,基本上自己用完全无压力。到第二个月就需要更新订阅了,更新完订阅,语音服务依然可以选择免费的F0订阅,享受50万字每月的额度。

3.Azure语音合成的代码实现

        在Azure语音的代码实现方面,微软官方实际上提供有sdk,其中也有适用unity的插件包可用,插件的传送门如下:

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

        不过本文所介绍的代码实现并不是使用上述插件的代码实现,主要是因为之前我用这个sdk发现发布到webgl就不可用了,只能windows使用,这个有点坑,所以就查阅了Azure的官方文档,找到了restful api的实现方式,所以就实现了调用restful api实现语音识别和语音合成的代码,在这边文章做一下记录和分享,下面,分享一下具体的代码实现。

3.1.Azure语音识别

        实现语音识别这部分功能,首先在unity端是有获取麦克风声音的接口,可以直接获取电脑接入的麦克风,采集声音信息的功能的,所以只需要关注如何使用restful api调用Azure语音识别api的方法就可以了。

        Azure语音识别的api地址:

        https://{region}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=zh-CN

        这里面,region的值就是你在Azure语音服务里订阅的地区码,比如我订阅的是东亚地区的,所以这个地区码就是“eastasia”。

public string subscriptionKey = string.Empty;//服务令牌
public string serviceRegion = string.Empty;//地区码
public string language = string.Empty;//语言 

 /// <summary>
    /// 识别语音
    /// </summary>
    /// <param name="audioData"></param>
    /// <param name="_callback"></param>
    /// <returns></returns>
    private IEnumerator SendAudioData(byte[] audioData, Action<string> _callback)
    {
        // Construct the request URL
        string url = "https://" + serviceRegion + ".stt.speech.microsoft.com/speech/recognition/" +
            mode + "/cognitiveservices/v1?language=" + language;

        // Create the request object
        UnityWebRequest request = UnityWebRequest.Post(url, "application/octet-stream");
        request.SetRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
        request.SetRequestHeader("Content-Type", "audio/wav; codec=audio/pcm; samplerate=44100");

        // Attach the audio data to the request
        request.uploadHandler = new UploadHandlerRaw(audioData);
        request.uploadHandler.contentType = "application/octet-stream";

        // Send the request and wait for the response
        yield return request.SendWebRequest();

        // Check for errors
        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("Speech recognition request failed: " + request.error);
            yield break;
        }

        // Parse the response JSON and extract the recognition result
        string json = request.downloadHandler.text;
        SpeechRecognitionResult result = JsonUtility.FromJson<SpeechRecognitionResult>(json);
        string recognizedText = result.DisplayText;

        // Display the recognized text in the console
        Debug.Log("Recognized text: " + recognizedText);
        _callback(recognizedText);
    }

用到的工具类:

[System.Serializable]
public class SpeechRecognitionResult
{
    public string RecognitionStatus;
    public string DisplayText;
}
using UnityEngine;
using System.IO;

public static class WavUtility
{
    /// <summary>
    /// Converts an AudioClip to a byte array containing a WAV file.
    /// </summary>
    public static byte[] FromAudioClip(AudioClip clip)
    {
        // Create a new WAV file
        MemoryStream stream = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(stream);

        // Write the WAV header
        writer.Write(new char[4] { 'R', 'I', 'F', 'F' });
        writer.Write(36 + clip.samples * 2);
        writer.Write(new char[4] { 'W', 'A', 'V', 'E' });
        writer.Write(new char[4] { 'f', 'm', 't', ' ' });
        writer.Write(16);
        writer.Write((ushort)1);
        writer.Write((ushort)clip.channels);
        writer.Write(clip.frequency);
        writer.Write(clip.frequency * clip.channels * 2);
        writer.Write((ushort)(clip.channels * 2));
        writer.Write((ushort)16);
        writer.Write(new char[4] { 'd', 'a', 't', 'a' });
        writer.Write(clip.samples * 2);

        // Write the audio data
        float[] samples = new float[clip.samples];
        clip.GetData(samples, 0);
        int intMax = 32767; // max value for a 16-bit signed integer
        for (int i = 0; i < clip.samples; i++)
        {
            writer.Write((short)(samples[i] * intMax));
        }

        // Clean up
        writer.Close();
        byte[] wavBytes = stream.ToArray();
        stream.Close();
        return wavBytes;
    }
}

3.2.Azure语音合成

        Azure语音合成部分的功能,需要将合成的文本,POST到Azure语音合成的restful api服务即可实现语音的合成功能,代码示例如下:

public string subscriptionKey = string.Empty;//服务令牌
public string serviceRegion = string.Empty;//地区码
public string language = string.Empty;//语言 

    /// <summary>
    /// 朗读的角色
    /// </summary>
    [Header("朗读声音设置")]
    public string voiceName = "zh-CN-XiaomoNeural";
    /// <summary>
    /// 情绪
    /// </summary>
    [Header("朗读的情绪设置" +
        "")]
    public string style = "chat";//chat  cheerful  angry  excited  sad

/// <summary>
    /// restful api语音合成
    /// </summary>
    /// <param name="_msg"></param>
    /// <param name="_callback"></param>
    /// <returns></returns>
    private IEnumerator GetVoice(string _msg, Action<AudioClip> _callback)
    {
        string textToSpeechEndpoint = string.Format("https://{0}.tts.speech.microsoft.com/cognitiveservices/v1", serviceRegion);
        //发送报文
        string textToSpeechRequestBody = GenerateTextToSpeech(language, voiceName, style, 2, _msg);

        using (UnityWebRequest speechRequest = new UnityWebRequest(textToSpeechEndpoint,"POST"))
        {
            byte[] data = System.Text.Encoding.UTF8.GetBytes(textToSpeechRequestBody);
            speechRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(data);
            speechRequest.downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(speechRequest.uri, AudioType.MPEG);

            speechRequest.SetRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
            speechRequest.SetRequestHeader("X-Microsoft-OutputFormat", "audio-16khz-32kbitrate-mono-mp3");
            speechRequest.SetRequestHeader("Content-Type", "application/ssml+xml");

            yield return speechRequest.SendWebRequest();

            if (speechRequest.responseCode == 200)
            {
                AudioClip audioClip = DownloadHandlerAudioClip.GetContent(speechRequest);
                _callback(audioClip);
            }
            else
            {
                Debug.LogError("语音合成失败: " + speechRequest.error);
            }
        }
    }

        语音合成设置参数中,涉及到朗读的声音,具体的声音编码可已到Azure的官方文档查阅,有详细的介绍,这里需要注意,有些声音的选择需要同步修改语言编码,这个根据官方文档来就可以了。官方文档地址:

Text to speech overview - Speech service - Azure Cognitive Services | Microsoft Learn

4.结束语

        本文介绍了一下微软Azure语音服务的restful api的使用代码示例。我在自己的开源项目AI二次元小姐姐聊天机器人里使用到了相关的技术,只停留在应用方面。当然在服务调用方法方面,官方也提供有多个不同语言的代码示例以及SDK,大家可以根据自己的实际需求选择技术方案。

        上述的代码示例并不是完整可以直接执行的代码,我只是将我的项目代码中,涉及到微软语音服务的关键部分提取出来了,源码还有部分unity客户端的代码逻辑,所以上面的代码实现仅供有编码基础的朋友参考,不要直接丢到自己的项目里使用。

        对我这个项目感兴趣的朋友,可以上我的B站号查看,我也做有详细的教程,相关源码可以在的哔哩哔哩主站找到相关视频,在视频介绍以及评论区获取。

【chatGPT+unity+Azure+VRoid】AI女友对话,源码分享,零基础手搓二次元妹子,打造专属的AI女友不是梦

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探讨餐饮行业油烟污染与治理措施

安科瑞 华楠 摘 要&#xff1a; 近年来我国餐饮行业油烟污染已成为城市大气污染的主要来源之一。如今环境问题日益突出严重制约到人们的身体健康&#xff0c;需要引起重视采取一系列有效的措施来治理餐饮行业的油烟污染。 关键词&#xff1a;餐饮业&#xff1b;污染&#xf…

STM32驱动ADS1256串口输出-AD转换

STM32驱动ADS1256串口输出-AD转换 ADS1256ADS1256简介芯片特点引脚说明模块相关寄存器与命令相关程序初始化 实验效果接线实验现象 ADS1256 ADS1256简介 ADS1256是TI推出的一款微功耗、高精度、8 通道、24 位高性能模数转换器。该芯片还带有4个可编程的I/O口、输入缓冲器和可编…

Spring依赖注入Bean类型的8种情况详解

1、普通对象 这没什么好说的&#xff0c;大家都这么用的&#xff0c;比如需要用到 UserService&#xff0c;直接 Autowired 就可以了。 Autowired private UserService userService;2、Collection 及其子接口 除了支持注入一个单一的对象之外&#xff0c;Autowired 还支持注…

100天精通Golang(基础入门篇)——第16天:深入解析Go语言包的使用和包管理

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

java微信公众号新建草稿并发布

java实现公众号发起新建草稿&#xff0c;并且发布得到文章链接首先要先去微信公众号的设置与开发–基础设置 查看公众号的各个参数&#xff0c;这里我是存储到数据库&#xff0c;方便后期使用&#xff0c;实体类如下&#xff1a; Data public class WeChatOfficial {private st…

蛙色Web3D编辑器全面更新,会员能力解析

导语&#xff1a; 在数字化时代&#xff0c;创意设计和虚拟展示成为了营销领域的关键。然而&#xff0c;传统的创作方式往往需要复杂的软件和技术支持&#xff0c;给用户带来了诸多麻烦。 幸运的是&#xff0c;蛙色Web3D编辑器作为一款领先的在线编辑工具&#xff0c;通过全面…

Sentieon | 每周文献-Epidemiology-第五期

流行病学系列文章-1 标题&#xff08;英文&#xff09;&#xff1a;Rare Variants in Inborn Errors of Immunity Genes Associated With Covid-19 Severity标题&#xff08;中文)&#xff1a;与Covid-19严重程度相关的免疫基因先天性缺陷的罕见变异发表期刊&#xff1a;《Fron…

背包问题学习笔记

笔记&#xff0c;不是博客&#xff0c;所以就只是粗略的写写 背包问题状态设置 1.小于等于某值&#xff0c;一般用于求在限制背包体积内的情况求解 状态设置 F(n) 表示此时的背包体积小于等于n&#xff0c;F数组初始化为0即可 例题&#xff1a;423. 采药 - AcWing题库 2.恰…

用Python采用Modbus-Tcp的方式读取485电子水尺数据

README.TXT 2023/6/15 V1.0 实现了单个点位数据通信、数据解析、数据存储 2023/6/17 V2.0 实现了多个点位数据通信、数据解析、数据存储 2023/6/19 V2.1 完善log存储&#xff0c;仅保留近3天的log记录&#xff0c;避免不必要的存储&#xff1b;限制log大小&#xff0c;2MB。架…

C#生成类库dll以及调用实例

本文讲解如何用C#语言生成类库并用winform项目进行调用 目录 创建C#类库项目 Winform调用dll 创建C#类库项目 编写代码 using System.Threading;namespace ClassLibrary1 {public class Class1{private Timer myTimer = null;//定义定时器用于触发事件//定义公共的委托和调…

HW5300V3-ISCSI存储运维,看这一篇就够了01——流程图

一、存储使用流程图 二、块存储-配置流程图

【Hippo4j源码的方式安装部署教程】

&#x1f680; 线程池管理工具-Hippo4j &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#…

Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)

目录 &#x1fa82; 演示 &#x1f6f9; 目录树 &#x1f414; 安装 &#x1f916; global.d.ts &#x1f637; zkConfettiCanvas.vue &#x1f30d; confetti.ts &#x1f38b; confettiIndex.ts &#x1f637; index.vue &#x1f970;&#x1f609; 谢谢观看 &…

哪款蓝牙耳机通话清楚,几款拥有通话降噪技术的骨传导耳机分享

嘿&#xff0c;你是音乐爱好者吗&#xff1f;还是热衷于锻炼身体&#xff1f;那么你一定不能错过骨传导耳机&#xff01;这种神奇的耳机通过骨头的振动来传递声音&#xff0c;绝不同于传统的耳道或鼓膜传播方式。你可保持对周围环境的警觉&#xff0c;同时避免对你的听力造成任…

【雕爷学编程】Arduino动手做(149)---MAX9814咪头传感器模块5

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

【unity实战】手搓一个网格放置功能,及装修建造种植功能(2d3d通用,附源码)

文章目录 前言开始项目和素材1. 素材来源2. 开始项目包&#xff08;两种选择一种下载导入即可&#xff09; 开始1. 修改鼠标指针显示2. 给鼠标对应的平面位置绑定对应的指示器3. 使用Shader Graph创建网格可视化3. 网格的大小缩放和颜色控制4. 优化5. 扩展说明5.1 我们就可以通…

总结:WEB流量劫持

一、背景 在整理WEB鉴权与登陆等技术的时候&#xff0c;会涉及到安全&#xff0c;而鉴权登陆不安全有个很大的可能就是流量被劫持了。 本篇文章主要是想弄明白黑客是怎么劫持的。 二、WEB流量劫持是如何做到的&#xff1f; WEB流量劫持是指黑客将受害者的网页请求重定向到攻…

python appium UI 自动化测试框架讨论

目录 前言&#xff1a; 框架共性总结 Auto_Analysis 权限弹窗识别 前言&#xff1a; Python Appium UI自动化测试框架是一种用于测试移动应用程序的工具&#xff0c;它结合了Python编程语言和Appium测试框架的功能。 框架共性总结 1 自动找设备 连接设备 2 自动启 appium …

Java设计模式之行为型-状态模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析 五、总结 一、基础概念 状态模式允许一个对象在其内部状态改变时改变它的行为&#xff0c;对象看起来似乎修改了它的类&#xff0c;状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况&a…

有必要买apple pencil吗?ipad pencil替代品

苹果的电容笔与一般的电容笔有什么不同&#xff1f;事实上&#xff0c;从外观上来看&#xff0c;两者并没有太大的区别。唯一不同的是&#xff0c;苹果电容笔的重量更大&#xff0c;笔尖内部有专门的重力感应器&#xff0c;可以感应到重力压感对线条的影响。因此苹果的这个产品…