Sergey
Sergey

Reputation: 1089

How to integrate Google Text-To-Speech in Twilio (or URL with '&' in XML tag)

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 &amp;
It not helped for me. I this case I got another exception: returned the HTTP status code 404. Look like Twilio don't decode &amp; 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

Answers (3)

Charlie Weems
Charlie Weems

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:

  • Arabic
  • Czech
  • Filipino
  • Greek
  • Hungarian
  • Indonesian
  • Slovak
  • Ukrainian
  • Vietnamese

This support article provides the list of languages that Twilio Text-to-Speech supports.

Upvotes: 1

Sergey
Sergey

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

Tomalak
Tomalak

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&amp;q=Hello%20World&amp;tl=en-us</Play>
</Response>

If Twilio cannot process this then you should file a bug against them.

Upvotes: 0

Related Questions