I am attempting to use the example script "ExampleTextToSpeech" that comes with the Watson Unity SDK. However, the Watson Text to Speech example throws error when attempting to synthesize. My service IAM Key appears to be correct. I am not specifying the AIM URL or the Service Url. I assume the default values should be correct since I am in the North American Region and this has worked for both the Watson Assistant and Speech to Text. The problem appears to be with the Synthesize call. I've listed the errors below.
Sorry I failed to post the actual code the first time. I assumed I didn't need to since it is the same code from the SDK demos. Please find the code below. I have removed some extraneous code bits such as customizing words from the code. The errors can be found at the end of the code block.
using UnityEngine;
using IBM.Watson.DeveloperCloud.Services.TextToSpeech.v1;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Utilities;
using System.Collections;
using System.Collections.Generic;
using IBM.Watson.DeveloperCloud.Connection;
public class TTS : MonoBehaviour
{
//Iam Apikey: v0qlUa8hojlVW8rKBh48fO0JtQYTO9vfNkGMG6wpptbs
#region PLEASE SET THESE VARIABLES IN THE INSPECTOR
[Space(10)]
[Tooltip("The service URL (optional). This defaults to \"https://stream.watsonplatform.net/text-to-speech/api\"")]
[SerializeField]
private string _serviceUrl;
[Header("CF Authentication")]
[Tooltip("The authentication username.")]
[SerializeField]
private string _username;
[Tooltip("The authentication password.")]
[SerializeField]
private string _password;
[Header("IAM Authentication")]
[Tooltip("The IAM apikey.")]
[SerializeField]
private string _iamApikey;
[Tooltip("The IAM url used to authenticate the apikey (optional). This defaults to \"https://iam.bluemix.net/identity/token\".")]
[SerializeField]
private string _iamUrl;
#endregion
TextToSpeech _service;
string _testString = "<speak version=\"1.0\"><say-as interpret-as=\"letters\">I'm sorry</say-as>. <prosody pitch=\"150Hz\">This is Text to Speech!</prosody><express-as type=\"GoodNews\">I'm sorry. This is Text to Speech!</express-as></speak>";
string _createdCustomizationId;
CustomVoiceUpdate _customVoiceUpdate;
string _customizationName = "unity-example-customization";
string _customizationLanguage = "en-US";
string _customizationDescription = "A text to speech voice customization created within Unity.";
string _testWord = "Watson";
private bool _synthesizeTested = false;
private bool _getVoicesTested = false;
private bool _getVoiceTested = false;
private bool _getPronuciationTested = false;
private bool _getCustomizationsTested = false;
private bool _createCustomizationTested = false;
private bool _deleteCustomizationTested = false;
private bool _getCustomizationTested = false;
private bool _updateCustomizationTested = false;
private bool _getCustomizationWordsTested = false;
private bool _addCustomizationWordsTested = false;
private bool _deleteCustomizationWordTested = false;
private bool _getCustomizationWordTested = false;
void Start()
{
LogSystem.InstallDefaultReactors();
Runnable.Run(CreateService());
}
private IEnumerator CreateService()
{
// Create credential and instantiate service
Credentials credentials = null;
if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
{
// Authenticate using username and password
credentials = new Credentials(_username, _password, _serviceUrl);
}
else if (!string.IsNullOrEmpty(_iamApikey))
{
// Authenticate using iamApikey
TokenOptions tokenOptions = new TokenOptions()
{
IamApiKey = _iamApikey,
IamUrl = _iamUrl
};
credentials = new Credentials(tokenOptions, _serviceUrl);
// Wait for tokendata
while (!credentials.HasIamTokenData())
yield return null;
}
else
{
throw new WatsonException("Please provide either username and password or IAM apikey to authenticate the service.");
}
_service = new TextToSpeech(credentials);
Runnable.Run(Examples());
}
private IEnumerator Examples()
{
// Synthesize
Log.Debug("ExampleTextToSpeech.Examples()", "Attempting synthesize.");
_service.Voice = VoiceType.en_US_Allison;
_service.ToSpeech(HandleToSpeechCallback, OnFail, _testString, true);
while (!_synthesizeTested)
yield return null;
// Get Voices
Log.Debug("ExampleTextToSpeech.Examples()", "Attempting to get voices.");
_service.GetVoices(OnGetVoices, OnFail);
while (!_getVoicesTested)
yield return null;
// Get Voice
Log.Debug("ExampleTextToSpeech.Examples()", "Attempting to get voice {0}.", VoiceType.en_US_Allison);
_service.GetVoice(OnGetVoice, OnFail, VoiceType.en_US_Allison);
while (!_getVoiceTested)
yield return null;
Log.Debug("ExampleTextToSpeech.Examples()", "Text to Speech examples complete.");
}
void HandleToSpeechCallback(AudioClip clip, Dictionary<string, object> customData = null)
{
PlayClip(clip);
}
private void PlayClip(AudioClip clip)
{
if (Application.isPlaying && clip != null)
{
GameObject audioObject = new GameObject("AudioObject");
AudioSource source = audioObject.AddComponent<AudioSource>();
source.spatialBlend = 0.0f;
source.loop = false;
source.clip = clip;
source.Play();
Destroy(audioObject, clip.length);
_synthesizeTested = true;
}
}
private void OnGetVoices(Voices voices, Dictionary<string, object> customData = null)
{
Log.Debug("ExampleTextToSpeech.OnGetVoices()", "Text to Speech - Get voices response: {0}", customData["json"].ToString());
_getVoicesTested = true;
}
private void OnGetVoice(Voice voice, Dictionary<string, object> customData = null)
{
Log.Debug("ExampleTextToSpeech.OnGetVoice()", "Text to Speech - Get voice response: {0}", customData["json"].ToString());
_getVoiceTested = true;
}
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Error("ExampleTextToSpeech.OnFail()", "Error received: {0}", error.ToString());
}
}
[12/11/2018 16:57:45][RESTConnector.ProcessRequestQueue()][ERROR] URL: /v1/synthesize?accept=audio%2fwav&voice=en-US_AllisonVoice&text=%3cspeak+version%3d%221.0%22%3e%3csay-as+interpret-as%3d%22letters%22%3eI%27m+sorry%3c%2fsay-as%3e.+%3cprosody+pitch%3d%22150Hz%22%3eThis+is+Text+to+Speech%21%3c%2fprosody%3e%3cexpress-as+type%3d%22GoodNews%22%3eI%27m+sorry.+This+is+Text+to+Speech%21%3c%2fexpress-as%3e%3c%2fspeak%3e, ErrorCode: 0, Error: Cannot connect to destination host, Response:
UnityEngine.Debug:LogError(Object)
IBM.Watson.DeveloperCloud.Debug.DebugReactor:ProcessLog(LogRecord) (at Assets/Watson/Scripts/Debug/DebugReactor.cs:60)
IBM.Watson.DeveloperCloud.Logging.LogSystem:ProcessLog(LogRecord) (at Assets/Watson/Scripts/Logging/Logger.cs:206)
IBM.Watson.DeveloperCloud.Logging.Log:Error(String, String, Object[]) (at Assets/Watson/Scripts/Logging/Logger.cs:279)
IBM.Watson.DeveloperCloud.Connection.<ProcessRequestQueue>c__Iterator0:MoveNext() (at Assets/Watson/Scripts/Connection/RESTConnector.cs:607)
IBM.Watson.DeveloperCloud.Utilities.Routine:MoveNext() (at Assets/Watson/Scripts/Utilities/Runnable.cs:131)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
[12/11/2018 16:57:45][ExampleTextToSpeech.OnFail()][ERROR] Error received: URL: /v1/synthesize?accept=audio%2fwav&voice=en-US_AllisonVoice&text=%3cspeak+version%3d%221.0%22%3e%3csay-as+interpret-as%3d%22letters%22%3eI%27m+sorry%3c%2fsay-as%3e.+%3cprosody+pitch%3d%22150Hz%22%3eThis+is+Text+to+Speech%21%3c%2fprosody%3e%3cexpress-as+type%3d%22GoodNews%22%3eI%27m+sorry.+This+is+Text+to+Speech%21%3c%2fexpress-as%3e%3c%2fspeak%3e, ErrorCode: 0, Error: Cannot connect to destination host, Response:
UnityEngine.Debug:LogError(Object)
IBM.Watson.DeveloperCloud.Debug.DebugReactor:ProcessLog(LogRecord) (at Assets/Watson/Scripts/Debug/DebugReactor.cs:60)
IBM.Watson.DeveloperCloud.Logging.LogSystem:ProcessLog(LogRecord) (at Assets/Watson/Scripts/Logging/Logger.cs:206)
IBM.Watson.DeveloperCloud.Logging.Log:Error(String, String, Object[]) (at Assets/Watson/Scripts/Logging/Logger.cs:279)
TTS:OnFail(Error, Dictionary`2) (at Assets/Scripts/TTS.cs:158)
IBM.Watson.DeveloperCloud.Services.TextToSpeech.v1.TextToSpeech:ToSpeechResponse(Request, Response) (at Assets/Watson/Scripts/Services/TextToSpeech/v1/TextToSpeech.cs:492)
IBM.Watson.DeveloperCloud.Connection.<ProcessRequestQueue>c__Iterator0:MoveNext() (at Assets/Watson/Scripts/Connection/RESTConnector.cs:647)
IBM.Watson.DeveloperCloud.Utilities.Routine:MoveNext() (at Assets/Watson/Scripts/Utilities/Runnable.cs:131)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)