Unity | 用Azure实现文字转语音(详细讲解版)

#1024程序员节|征文#

 碎碎念

up发现了一个视频,讲什么是API,讲的很好,分享给大家,很适合新手理解。

到底什么是 API 接口?用全网最易懂的方式给你讲清楚!_哔哩哔哩_bilibili

一、前言

本文本只讲解Windows连接,其他的暂未测试。

文字转语音目前有两个方案:

1.用unity使用各个厂商做的sdk

根据不同厂商的政策收费不同,声音也相对自然。

2.unity商城里有个插件叫做RT-Voice PRO

插件一次性收费,但声音是机器音 

标题

二、简单介绍Azure

我们可能没有听过Azure,但是我们一定听过微软。微软是一个公司,做了很多计算机相关的东西,比如我们用的windows系统,office办公软件等,他的中国版官方网站为:

//很奇怪,链接一贴就损坏,就这样贴吧
https://www.microsoft.com/zh-cn

微软公司也开发了AI相关的功能,在官网内我们可以找到。

也可以直接进入链接:

人工智能解决方案 | Microsoft AI

在这些AI功能中,有一个功能就叫做Azure,中文名称是蔚蓝。

这里就有点类似于,百度的AI叫文心一言,科大讯飞的AI叫讯飞星火。

 在Azure中,有一项功能就是文字转语音服务,截止到up写本篇文章是每个月50万神经网络字符。

备注:

神经网络字符可以简单理解为字符,因为一个中文等于两个或多个字符,所以在这里可以约等于10万个中文汉字左右。 

Azure在Github上有公开的案例,链接如下:

https://github.com/Azure-Samples

三、安装环境

1.注册账号相关

官方说明文档:

面向开发人员的关键 Azure 服务 | Microsoft Learn

文本转语音的说明文档:

文本转语音文档 - 教程和 API 参考 - Azure AI 服务 - Azure AI services | Microsoft Learn

文本转语音的快速使用文档:

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

根据使用文档,我们首先要做的三件事为:

以上每件事都需要做,挨个去实现一下。 

2.安装SDK的环境 

对应的文档说明为:

安装SDK包的链接为:

安装语音 SDK - Azure AI services | Microsoft Learn


在上述链接中,我们只需要看Unity的解决方案就可以了。

标题

链接中有对环境的要求为:

1.就是在VS安装时,有一个组件,必须要安装。【Microsoft Visual C++ Redistributable(简称MSVC)是Windows操作系统中的基础类型库组件】

2.Unity要求的版本。【略】

3.VS要求的版本。【略】

余下的就是根据你的硬件情况,看需要。

备注:

Windows ARM64和我们平时说的Windows并不是一个东西。

  • Windows:我们平时说的Windows是指x86-64(AMD64或Intel x86-64)
  • Windows ARM64:一般在移动设备和嵌入式系统中用
3.下载unitySDK

找到链接中的这句话,就可以直接下载。然后把下载好的SDK拖入Unity中。

四、SDK使用

关于SDK使用,官方在gitHub上有Demo。

GitHub - Azure-Samples/cognitive-services-speech-sdk: Sample code for the Microsoft Cognitive Services Speech SDK

但是这个demo有些问题:

1.它并不是写在携程里的,所以在转换的时候会卡死

2.音频转换时无法停止, PCMSetPositionCallback方法会一直走10分钟最多。

所以对这个demo的代码进行了修改,对应的注释如下:

using UnityEngine;
using UnityEngine.UI;
using Microsoft.CognitiveServices.Speech;
using System.Collections;
using System.Threading.Tasks;

public class TTSManeger : MonoBehaviour
{
    //提示框
    public Text outputText;
    //输入框
    public InputField inputField;
    //按钮
    public Button speakButton;
    //音乐
    public AudioSource audioSource;

    //秘钥
    private const string SubscriptionKey = "这里填你自己的秘钥";
    //订阅服务的地区
    private const string Region = "eastasia";
    //采样率
    private const int SampleRate = 24000;
    //信息
    private string message;

    //语音常规设置
    private SpeechConfig speechConfig;
    //语音合成器
    private SpeechSynthesizer synthesizer;

    void Start()
    {
        Application.runInBackground = true;

        //重置输入框文字
        inputField.text = "请输入想要阅读的文字";
        //添加按钮方法
        speakButton.onClick.AddListener(ButtonClick);

        //账户配置,需要你的秘钥和地区,这是sdk中已经写好的方法
        speechConfig = SpeechConfig.FromSubscription(SubscriptionKey, Region);

        //微软有一个通用的格式叫RIFF,这个格式可以是图片,也可以是音频
        //但是我们要的是我们能识别的音频,所以我们要把数据稍微修改一下
        //把数据改成raw的格式,质量就设置成Raw24Khz16BitMonoPcm
        //(Raw的/采样率为24,000赫兹/每个采样使用16位/单声道音频/脉冲编码调制)
        speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm);

        //按照设置,初始化语音合成器,并且有两个参数            //这个null是音频设置(AudioConfig)
        synthesizer = new SpeechSynthesizer(speechConfig, null);

        //当语音合成器取消时
        synthesizer.SynthesisCanceled += (s, e) =>
        {
            //从结果中找到语音取消的详细情况                   //当前语音合成器的结果 
            var cancellation = SpeechSynthesisCancellationDetails.FromResult(e.Result);
            //记录获取到的情况
            message = $"取消:\n" +
                      $"原因:[{cancellation.Reason}]\n" +
                      $"错误细节:[{cancellation.ErrorDetails}]\n" +
                      $"是否订阅了信息?";
        };
    }

    void Update()
    {
        //实时更新信息
        if (outputText != null)
        {
            outputText.text = message;
        }
    }

    //点击
    public void ButtonClick()
    {
        speakButton.interactable = false;

        //重置信息
        string newMessage = null;

        //如果没有输入信息,就不折腾了
        if (inputField.text == null)
        {
            speakButton.interactable = true;
            return;
        }

        //设置任务
        Task<SpeechSynthesisResult> task = synthesizer.SpeakTextAsync(inputField.text);

        StartCoroutine(CheckSynthesizer(task, speechConfig, synthesizer));
    }

    private IEnumerator CheckSynthesizer(Task<SpeechSynthesisResult> task,
            SpeechConfig config,
            SpeechSynthesizer synthesizer)
    {
        //重置信息
        string newMessage = null;
        //等待转换完成
        yield return new WaitUntil(() => task.IsCompleted);
        var result = task.Result;

        //如果是已完成
        if (result.Reason == ResultReason.SynthesizingAudioCompleted)
        {
            var sampleCount = result.AudioData.Length / 2;
            var audioData = new float[sampleCount];

            //音频转换
            for (int i = 0; i < sampleCount; ++i)
            {
                audioData[i] = (short)(result.AudioData[i * 2 + 1] << 8 | result.AudioData[i * 2]) / 32768.0F;
            }
            var audioClip = AudioClip.Create("SynthesizedAudio", sampleCount,
              1, 16000, false);
            audioClip.SetData(audioData, 0);
            audioSource.clip = audioClip;

            newMessage = "音频转换成功";

            //把创建好的音频给到audioSource
            audioSource.clip = audioClip;
            //播放音频
            audioSource.Play();

        }

        if (newMessage != null)
        {
            message = newMessage;
        }

        yield return new WaitForSeconds(1f);
        //打开按钮
        speakButton.interactable = true;
    }


    void OnDestroy()
    {
        //如果语音合成器还在,清理掉它
        if (synthesizer != null)
        {
            synthesizer.Dispose();
        }
    }
}

五、场景布置

直接下载gitHub上的Demo,然后把代码改掉就可以了,我没有对场景进行其他更改。

看在这么认真的注释份上,点个赞再走吧~^_^~

猜你喜欢

转载自blog.csdn.net/weixin_49427945/article/details/143163333
今日推荐