Reputation: 1089
I want to use Google Text-To-Speech service in Twilio.
I have generated URL with several parameters, separated with ampersands(&).
For Example: http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us
The problem is: when I try to put this URL in TwiML tag, I have exception that written below:
Error on line 1 of document : The reference to entity "q" must end with the ';' delimiter. Please ensure that the response body is a valid XML document.
This is TwiML:
<Response>
<Play>http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us</Play>
</Response>
Solutions, that I already tried:
1) Replace &
with &
It not helped for me. I this case I got another exception: returned the HTTP status code 404. Look like Twilio don't decode &
back to &
.
2) Save Google output to file on server and put direct link to this file (without any &) to tag. It should work, but it look like dirty hack =)
Upvotes: 1
Views: 1547
Reputation: 1750
Posting this here in case it's useful to others. I've written an open source example app that stores recordings from the Google Cloud Text-To-Speech API to Google Cloud Storage. The response is the URL of the recording, which can be passed to the <Play>
TwiML verb.
This app may be helpful if you're looking to use TTS in the languages that are supported by Google but not Twilio. As of December 2019 these languages include:
This support article provides the list of languages that Twilio Text-to-Speech supports.
Upvotes: 1
Reputation: 1089
Ok, I solved this problem on third way:
I made "proxy" servlet for hiding all of parameters, that needed for google TTS Engine, inside this servlet. It's more easy to demonstrate in code:
I put URL to my proxy servlet (instead URL to Google TTS Engine) to TwiML. For this servlet required only one parameter: message that will play. In this case I avoid ampersand symbol in TwiML.
...
String url = Constants.APPLICATION_URL + "/tts/" +"?" + Constants.ParamName.GREETINGS + "=" + greetings;
Play play = new Play(url);
...
This is proxy servlet (it mapped to /tts/ path). make request to Google TTS Engine and send back response from it:
...
this.greetings = request.getParameter(Constants.ParamName.GREETINGS);
InputStream input = null;
HttpURLConnection con = null;
OutputStream output = null;
try {
URL obj = new URL("http://translate.google.com/translate_tts?ie=UTF-8&q=" + URLEncoder.encode(greetings, "UTF-8") + "&tl=en-us"));
con = (HttpURLConnection) obj.openConnection();
con.setConnectTimeout(5000);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Content-Type", "audio/mpeg");
input = con.getInputStream();
response.setContentType("audio/mpeg");
output = response.getOutputStream();
byte[] buffer = new byte[10240];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
...
Of course, this is look like a dirty hack, but I think it is better, than save temporary file on server.
Upvotes: 2
Reputation: 338228
<Response>
<Play>http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us</Play>
</Response>
is syntactically invalid XML. This is all-right:
<Response>
<Play>http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us</Play>
</Response>
If Twilio cannot process this then you should file a bug against them.
Upvotes: 0