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 =)
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.