【发布时间】:2018-09-14 07:25:06
【问题描述】:
我正在尝试在 Unity3D 中调用 Microsoft Bing Text to Speech API。
此 API 需要 accessToken 和其他将在请求标头中传递的参数。 首先,为了获得accessToken,我向Token API发送了一个POST请求,之后,我发送了请求头中的其他参数和它在 Postman 中完美运行(返回 Wav 音频剪辑),如下所示:
为了在 Unity 中实现这一点,我使用 UnityWebRequest 类发送两个 POST 请求(顺序),然后接收 音频响应 .
using System.Collections;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.Networking;
public class TextToSpeech : MonoBehaviour
{
public AudioSource audioSource;
public static readonly string accessUri = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
public static readonly string synthesizeUri = "https://speech.platform.bing.com/synthesize";
public string textToSpeak = "Oh yeah! Finally Dorot is speaking.";
private static string accessToken;
private static readonly string apiKey = "MY API KEY";
private string postStringData;
public TextToSpeech (string textToSpeak)
{
this.textToSpeak = textToSpeak;
}
public void Speak()
{
audioSource = gameObject.GetComponent<AudioSource>();
StartCoroutine(RequestToken(apiKey));
}
private string GenerateSsml(string textToSpeak)
{
var ssmlDoc = new XDocument(
new XElement("speak",
new XAttribute("version", "1.0"),
new XAttribute(XNamespace.Xml + "lang", "en-US"),
new XElement("voice",
new XAttribute(XNamespace.Xml + "lang", "en-US"),
new XAttribute(XNamespace.Xml + "gender", "Male"),
new XAttribute("name", "Microsoft Server Speech Text to Speech Voice (en-US, BenjaminRUS)"),
textToSpeak)));
return ssmlDoc.ToString();
}
public IEnumerator RequestToken(string apiKey)
{
var tokenRequest = UnityWebRequest.Post(accessUri, "data");
tokenRequest.SetRequestHeader("Ocp-Apim-Subscription-Key", apiKey);
var tokenResponse = tokenRequest.SendWebRequest();
yield return tokenResponse;
if (tokenRequest.isHttpError)
{
Debug.LogError("HTTP Error: " + tokenRequest.error + " Code: " + tokenRequest.responseCode);
}
else
{
postStringData = GenerateSsml(textToSpeak);
accessToken = tokenRequest.downloadHandler.text;
Debug.Log("Access token: " + accessToken);
StartCoroutine(Synthesize(postStringData, accessToken));
}
}
public IEnumerator Synthesize(string text, string token)
{
var synReq = UnityWebRequest.Post(synthesizeUri, text);
synReq.SetRequestHeader("Content-Type", "application/ssml+xml");
synReq.SetRequestHeader("X-Microsoft-OutputFormat", "riff-16khz-16bit-mono-pcm");
synReq.SetRequestHeader("X-Search-AppId", "07D3234E49CE426DAA29772419F436CA");
synReq.SetRequestHeader("X-Search-ClientID", "1ECFAE91408841A480F00935DC390960");
synReq.SetRequestHeader("User-Agent", "Dorot");
synReq.SetRequestHeader("Authorization", "Bearer " + token);
var synRes = synReq.SendWebRequest();
yield return synRes;
if (synReq.isHttpError)
{
Debug.LogError("HTTP Error: " + synReq.error + " Code: " + synReq.responseCode + " isNetworkError: " + synReq.isNetworkError + " isDone: " + synReq.isDone);
}
else
{
AudioClip cc = DownloadHandlerAudioClip.GetContent(synReq);
audioSource.clip = cc;
audioSource.Play();
}
}
}
结果,第一个 API 正确返回了 Token。但是,第二个返回 HTTP 代码状态 408,.像这样:
我该如何解决这个问题?谢谢。
【问题讨论】:
-
“合成”请求中还需要
Ocp-Apim-Subscription-Key标头吗? -
@Jon 不,令牌替换了 api 密钥。 OP,你能在 Github 上发布一个可重现的例子吗?您的代码对我来说看起来不错,但我不了解 Unity,所以我无法运行它。
-
@Jon,订阅密钥仅用于获取将在标头(授权)中发送的访问令牌。
-
@MariaInesParnisari,这是一个 .NETCore 示例,来自 GitHub:github.com/Azure-Samples/Cognitive-Speech-TTS/blob/master/… 和另一个 Node.js 示例:github.com/Azure-Samples/Cognitive-Speech-TTS/blob/master/…
标签: c# unity3d webrequest microsoft-cognitive http-error