Bing Speech微軟必應語音認知服務-文字語音互轉

山谷大叔發表於2017-09-06

本專案使用 Bing Speech APIBot FrameworkLUIS 實現在Unity內的中文語音文字互轉,還可以在UWP應用完成語義分析。


1.新增必應語音 API 到你的訂閱,地址 ,點選建立,並獲取API金鑰


2.修改 SpeechManager.cs的Subscription Key;


3.進入 LUIS管理後臺 ,新增LUIS App  

4、獲取 LUIS App Id 和 LUIS Endpoint Key 





5.修改SpeechToText.cs的App Id


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System;

public class TextToSpeech : Singleton<TextToSpeech>
{
    private static string SSML = "<speak version='1.0' xml:lang='zh-CN'><voice xml:lang='zh-CN' xml:gender='Male' name='Microsoft Server Speech Text to Speech Voice (zh-CN, Kangkang, Apollo)'>{0}</voice></speak>";
    AudioSource audioSource;
    public InputField inputText;
    // Use this for initialization
    void Start () {
        audioSource = gameObject.GetComponent<AudioSource>();
    }
	
	// Update is called once per frame
	void Update () {
		
	}

    /// <summary>
    /// 使用bing speech api,將文字轉為中文語音
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public IEnumerator<object> TextToAudio(string text)
    {
        string requestUri = "https://speech.platform.bing.com/synthesize";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(string.Format(SSML, text));
        var headers = new Dictionary<string, string>() {
            { "Authorization", "Bearer " + SpeechManager.Instance.GetToken() },
            { "Content-Type", @"application/ssml+xml" },
            { "X-Microsoft-OutputFormat", @"riff-16khz-16bit-mono-pcm"},
            { "X-Search-AppId", Guid.NewGuid().ToString().Replace("-", "")},
            { "X-Search-ClientID", Guid.NewGuid().ToString().Replace("-", "")},
            { "User-Agent", "TTSHololens"}
        };
        audioSource.Stop();
        WWW www = new WWW(requestUri, buffer, headers);
        yield return www;
        audioSource.clip = www.GetAudioClip(false, true, AudioType.WAV);
        audioSource.Play();
    }

    public void SpeakText(string text)
    {
        StartCoroutine(TextToAudio(text));
    }
    public void SpeakText()
    {
        StartCoroutine(TextToAudio(inputText.text));
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using BotClient;
using UnityEngine.UI;
#if WINDOWS_UWP
using System.Threading.Tasks;
#endif

public class SpeechToText :Singleton<SpeechToText>
{
    public int messageLength = 3;      //錄音時間,單位:秒
    private bool recording = false;
    private static string deviceName = string.Empty;  //microphone裝置名稱
    private int samplingRate;          //取樣率
    private AudioClip audioClip;

    BotService botService;

    private AudioSource audioSource;

    void Start () {
        int unUsed;
        Microphone.GetDeviceCaps(deviceName, out unUsed, out samplingRate);
        botService = new BotService();
        audioSource = gameObject.GetComponent<AudioSource>();
#if WINDOWS_UWP
        botService.StartConversation();
#endif
    }

    void Update () {
        if (recording && !Microphone.IsRecording(deviceName))
        {
            RecordStop();
        }
	}


    public bool IsRecording()
    {
        return recording;
    }

    /// <summary>
    /// 使用Bing Speech API,將語音檔案轉成text
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    private IEnumerator<object> AudioToText(string filepath)
    {
        string requestUri = "https://speech.platform.bing.com/recognize";
        requestUri += @"?scenarios=smd";
        requestUri += @"&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//你的APP ID.
        requestUri += @"&locale=zh-CN";
        requestUri += @"&device.os=win10";
        requestUri += @"&version=3.0";
        requestUri += @"&format=json";
        requestUri += @"&instanceid=565D69FF-E928-4B7E-87DA-9A750B96D9E3";
        requestUri += @"&requestid=" + Guid.NewGuid().ToString();

        FileStream fs = null;
        using (fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = null;
            buffer = new Byte[(int)fs.Length];
            fs.Read(buffer, 0, buffer.Length);
            var headers = new Dictionary<string, string>() {
                { "Authorization", "Bearer " + SpeechManager.Instance.GetToken()},
                { "Content-Type", @"audio/wav; codec=""audio/pcm""; samplerate=16000" }
            };
            WWW www = new WWW(requestUri, buffer, headers);

            yield return www;
            try
            {
                string result = www.text;
                JSONObject jsonObj = new JSONObject(result);
                string resultStr = jsonObj.GetField("header").GetField("name").str;
                resultStr = TrimResultStr(resultStr);
                SpeechContronller.Instance.SetResponseText("口令:" + resultStr);
                TextToSpeech.Instance.SpeakText(resultStr);
                SpeechContronller.Instance.tipText.text ="";
#if WINDOWS_UWP
                SendMessage(resultStr);
#endif
            }
            catch
            {
               SpeechContronller.Instance.tipText.text="對不起,沒聽清";
               TextToSpeech.Instance.SpeakText("對不起,沒聽清");
            }
        }
    }
    //使用BotService進行語義分析(uwp平臺執行)
#if WINDOWS_UWP
    private async void SendMessage(string message)
    {
        string result = "對不起,無法回答您的問題";
        if (await botService.SendMessage(message))
        {
            ActivitySet messages = await botService.GetMessages();
            if (messages != null)
            {
                for (int i = 1; i < messages.activities.Length; i++)
                {
                    result = messages.activities[i].text;
                }
            }
        }
        UnityEngine.WSA.Application.InvokeOnAppThread(() =>
        {
            //把返回的文字讀出來
            TextToSpeech.Instance.SpeakText(result);
        }, false); 
    } 
#endif

    /// <summary>
    /// 對Speech API返回的結果進行處理,去除最後的句號,防止影響結果
    /// </summary>
    /// <param name="result"></param>
    /// <returns></returns>
    private string TrimResultStr(string result)
    {
        string resultStr = result;
        if (resultStr != null)
        {
            int index = resultStr.LastIndexOf("。");
            if (index > 0)
            {
                resultStr = resultStr.Remove(index, 1);
            }
        }
        return resultStr;
    }

    /// <summary>
    /// 開始錄音
    /// </summary>
    public void Record()
    {
        recording = true;
        audioSource.Stop();

        SpeechContronller.Instance.SetMicrophoneIcon(true);
        SpeechContronller.Instance.SetTipText("正在聆聽中");
        SpeechContronller.Instance.SetResponseText("");

        if (Microphone.IsRecording(deviceName))
        {
            return;
        }
        audioClip = StartRecording();
    }

    /// <summary>
    /// 停止錄音,將語音儲存成檔案
    /// </summary>
    public void RecordStop()
    {
        recording = false;

        SpeechContronller.Instance.SetMicrophoneIcon(false);
        SpeechContronller.Instance.SetTipText("思考中,請稍候");

        StopRecording();
        string filename = "myfile.wav";
        var filepath = Path.Combine(Application.persistentDataPath, filename);
        SavWav.Save(filename, audioClip);
        StartCoroutine(AudioToText(filepath));
    }

    /// <summary>
    /// 開始錄音
    /// </summary>
    /// <returns></returns>
    private AudioClip StartRecording()
    {
        return Microphone.Start(deviceName, false, messageLength, 16000);
    }

    /// <summary>
    /// 停止錄音
    /// </summary>
    private void StopRecording()
    {
        if (Microphone.IsRecording(deviceName))
        {
            Microphone.End(deviceName);
        }
    }
}


工程檔案地址

http://download.csdn.net/download/shanguuncle/9967050

參考資料

Bing Speech API文件
Bot Framework API文件



相關文章