代码很简单没有难度,自己看一下应该就能明白。
OK 老规矩,直接上代码:
语音识别以及音频可视化
怎么说呢,就是这个语音识别的模块现在Unity只能识别关键字,并不能完整的识别语句以及语气,只能做一些简单的操作,不过如果需要更加复杂的语音识别以及牵扯到AI问答的逻辑,可以去桥接讯飞或则百度的SDK 进行语音训练或则更多的操作。
总体来说基础的应用也够用了,按需应用吧。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows.Speech;
/// <summary>
/// 语音识别
/// </summary>
[RequireComponent(typeof(AudioSource))]
public class ASR_ZH : MonoBehaviour
{
//语音识别短句
private PhraseRecognizer _PhraseASR;
[Header("关键字数组")]
public string[] _ListStrASR;
[Header("测试物体")]
public Transform _TestCube;
//执行布尔
private bool _bTest;
[Header("灯光")]
public Transform _TestLight;
[Header("精度")]
public ConfidenceLevel _PrecisionASR = ConfidenceLevel.Medium;
[Header("音波数组")]
public List<Transform> _AudioListPro;
[Header("音频数据")]
public AudioSource _AuduioASR;
//麦克风
private string _Device;
void Start()
{
//获取麦克风设备
_Device = Microphone.devices[0];
print(_Device);
//用设备开始录音
//设备的名称
//指示当达到长度秒时录音是否应该继续录制,并从音频剪辑开始绕圈录制
//录音产生的音频剪辑的长度
//44100 音频采样率
//_AuduioASR = Microphone.Start(_Device, true, 999, 44100);
if (_PhraseASR == null)
{
//创建语音识别
_PhraseASR = new KeywordRecognizer(_ListStrASR, _PrecisionASR);
//添加广播事件
_PhraseASR.OnPhraseRecognized += MonitorASR;
//开启语音识别
_PhraseASR.Start();
Debug.Log("创建识别器成功");
}
}
/// <summary>
/// 语音识别监听
/// 提供关于短语识别事件的信息
/// </summary>
/// <param 识别信息="_Args"></param>
private void MonitorASR(PhraseRecognizedEventArgs _Args)
{
switch (_Args.text)
{
case "启动":
_bTest = true;
_AuduioASR.Play();
break;
case "小哟":
StartCoroutine(TextToSpeech_ZH._World.GetAudioClip("您好!"));
break;
case "打开灯光":
StartCoroutine(TextToSpeech_ZH._World.GetAudioClip("好的,已正确执行。"));
_TestLight.gameObject.SetActive(true);
break;
case "关闭灯光":
StartCoroutine(TextToSpeech_ZH._World.GetAudioClip("好的,已正确执行。"));
_TestLight.gameObject.SetActive(false);
break;
case "停止":
_bTest = false;
_AuduioASR.Pause();
break;
default:
break;
}
print(_Args.text);
}
/// <summary>
/// 音频可视化
/// </summary>
private void UpdateGetAudio()
{
//分配音频空间
float[] _VolumeData = new float[256];
//用来自剪辑的样本数据填充数组
//_AuduioASR00.clip.GetData(_VolumeData, 1);
//提供一个监听器(主机)的频谱数据块
//参数:要用音频样本填充的数组 取样的通道 采样时使用的 FFTWindow 类型
AudioListener.GetSpectrumData(_VolumeData, 0, FFTWindow.Rectangular);
for (int i = 0; i < _AudioListPro.Count ; i++)
{
Debug.DrawLine(new Vector3(i , Mathf.Log(_VolumeData[i ]) + 10, 2), new Vector3(i, Mathf.Log(_VolumeData[i]) + 10, 2), Color.cyan);
//关联音波形成可视化
_AudioListPro[i].localScale = new Vector3(0.3f, _VolumeData[i] * 10 + 0.2f, 0.1f);
}
}
private void Update()
{
UpdateGetAudio();
if (_bTest)
{
_TestCube.Rotate(Vector3.one, 0.2f);
}
else
{
_TestCube.Rotate(Vector3.zero, 0.2f);
}
}
/// <summary>
/// Unity 官方提供的音频可视化脚本
/// </summary>
private void ShowASR()
{
float[] _ListBaty = new float[1024];
AudioListener.GetSpectrumData(_ListBaty, 0, FFTWindow.Rectangular);
for (int i = 1; i < _ListBaty.Length - 1; i++)
{
Debug.DrawLine(new Vector3(i - 1, _ListBaty[i] + 10, 0), new Vector3(i, _ListBaty[i + 1] + 10, 0), Color.red);
Debug.DrawLine(new Vector3(i - 1, Mathf.Log(_ListBaty[i - 1]) + 10, 2), new Vector3(i, Mathf.Log(_ListBaty[i]) + 10, 2), Color.cyan);
Debug.DrawLine(new Vector3(Mathf.Log(i - 1), _ListBaty[i - 1] - 10, 1), new Vector3(Mathf.Log(i), _ListBaty[i] - 10, 1), Color.green);
Debug.DrawLine(new Vector3(Mathf.Log(i - 1), Mathf.Log(_ListBaty[i - 1]), 3), new Vector3(Mathf.Log(i), Mathf.Log(_ListBaty[i]), 3), Color.blue);
}
}
private void OnDestroy()
{
//判断场景中是否存在语音识别
if (_PhraseASR != null)
{
//语音识别释放
_PhraseASR.Dispose();
}
}
}
百度文字转语音
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// 文字转语音
/// </summary>
public class TextToSpeech_ZH : MonoBehaviour
{
[Header("音源")]
public AudioSource _Audio;
//全局变量
public static TextToSpeech_ZH _World;
//网页文字转语音
private string _Url;
[Header("AI 发声器")]
public Pronouncer _Pronouncer = Pronouncer.Duyaya;
private void Start()
{
_World = this;
//_World.StartCoroutine(GetAudioClip("世界"));
}
//获取 Web网页音源信息并播放
public IEnumerator GetAudioClip(string AudioText)
{
_Url = "https://tsn.baidu.com/text2audio?tex=" + AudioText + "+&lan=zh&cuid=7919875968150074&ctp=1&aue=6&tok=自己的Token";
using (UnityWebRequest _AudioWeb = UnityWebRequestMultimedia.GetAudioClip(_Url, AudioType.WAV))
{
yield return _AudioWeb.SendWebRequest();
if (_AudioWeb.isNetworkError)
{
yield break;
}
AudioClip _Cli = DownloadHandlerAudioClip.GetContent(_AudioWeb);
_Audio.clip = _Cli;
_Audio.Play();
}
}
/// <summary>
/// 获取 Web网页音源信息并播放 附带延迟时间
/// </summary>
/// <param 播放文字="AudioText"></param>
/// <param 延迟时间="_DelayedTimer"></param>
/// <returns></returns>
public IEnumerator GetAudioClip(string AudioText,float _DelayedTimer)
{
//_Url = "https://tsn.baidu.com/text2audio?tex= AudioText &lan=zh&cuid=7919875968150074&ctp=1&aue=6&tok=25.3141e5ae3aa109abb6fc9a8179131181.315360000.1886566986.282335-17539441
// "";
yield return new WaitForSeconds(_DelayedTimer);
_Url = "http://tsn.baidu.com/text2audio?tex=" + AudioText +
"&tok=自己的Token" +
"&cuid=a7a0e3326da873c6fb0609e6385a82b934c9cb11" +
"&ctp=1" +
"&lan=zh" +
"&spd=5" +
"&pit=5" +
"&vol=10" +
"&per=" + (((int)_Pronouncer).ToString()) +
"&aue=6";
using (UnityWebRequest _AudioWeb = UnityWebRequestMultimedia.GetAudioClip(_Url, AudioType.WAV))
{
yield return _AudioWeb.SendWebRequest();
if (_AudioWeb.isNetworkError)
{
yield break;
}
AudioClip _Cli = DownloadHandlerAudioClip.GetContent(_AudioWeb);
_ASRMusic.clip = _Cli;
_ASRMusic.Play();
}
}
/// <summary>
/// AI 发音器
/// </summary>
public enum Pronouncer
{
//普通女声
Female,
//普通男生
Male,
//特殊男声
Teshunan,
//情感合成男生
Duxiaoyao,
//情感合成女生
Duyaya
}
}
微软文字转语音
using SpeechLib;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 微软文字转语音
/// </summary>
public class SpeechLibText_ZH : MonoBehaviour
{
//单例执行
public static SpeechLibText_ZH _Instance;
//微软组件
SpVoice _SpVoice = new SpVoice();
void Start()
{
_Instance = this;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
_Instance.SpeakText("kaighi ");
}
}
/// <summary>
/// 语音播放
/// </summary>
/// <param name="_SpeakText"></param>
public void SpeakText(string _SpeakText)
{
try
{
_SpVoice = new SpVoice();
//音量0-100
_SpVoice.Volume = 100;
//语速
_SpVoice.Rate = 0;
//开始执行
_SpVoice.Speak(_SpeakText, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
catch (Exception e)
{
Debug.Log($"播放失败原因: {e.Message}");
}
}
/// <summary>
/// 语音播放暂停
/// </summary>
public void Pause()
{
try
{
_SpVoice.Pause();
}
catch (Exception e)
{
Debug.Log($"暂停失败 原因: {e.Message}");
}
}
/// <summary>
/// 语音播放继续
/// </summary>
public void Resume()
{
try
{
_SpVoice.Resume();
}
catch (Exception e)
{
Debug.Log($"继续播放失败: {e.Message}");
}
}
/// <summary>
/// 语音播放停止
/// </summary>
public void StopPlaying()
{
try
{
_SpVoice.Speak(string.Empty, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);//停止
}
catch (Exception e)
{
Debug.Log($"停止失败: {e.Message}");
}
}
}
组件搭载:
最终效果以及调试输出:
暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路长远兮,与君共勉。