Как интегрировать Google Text-To-Speech в Twilio (или URL с "&" в теге XML)

Я хочу использовать сервис Google Text-To-Speech в Twilio.

Я сгенерировал URL с несколькими параметрами, разделенными амперсандами (&).
Например: http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us

Проблема: когда я пытаюсь поместить этот URL в тег TwiML, у меня возникает исключение, которое написано ниже:

Ошибка в строке 1 документа: ссылка на сущность "q" должна заканчиваться символом ";" разделитель. Убедитесь, что тело ответа является действительным документом XML.

Это TwiML:

<Response>
    <Play>http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us</Play>
</Response>

Решения, которые я уже пробовал:

1) Заменить & с &amp;
Это не помогло для меня. В этом случае я получил еще одно исключение: вернул код состояния HTTP 404. Похоже, Twilio не декодировать &amp; вернуться к &,

2) Сохраните вывод Google в файл на сервере и поместите прямую ссылку на этот файл (без знака &) в тег. Должно работать, но похоже на грязный взлом =)

2 ответа

Решение

Хорошо, я решил эту проблему третьим способом:

Я сделал "прокси" сервлет для сокрытия всех параметров, необходимых для Google TTS Engine, внутри этого сервлета. Это проще продемонстрировать в коде:

Я поместил URL-адрес моего прокси-сервлета (вместо URL-адреса в Google TTS Engine) в TwiML. Для этого сервлета требуется только один параметр: сообщение, которое будет воспроизводиться. В этом случае я избегаю символа амперсанда в TwiML.

...
String url = Constants.APPLICATION_URL + "/tts/" +"?" + Constants.ParamName.GREETINGS + "=" + greetings;
Play play = new Play(url);
...

Это сервлет прокси (он сопоставлен с /tts/ path). сделать запрос в Google TTS Engine и отправить ответ от него:

...
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);
    }
}
...

Конечно, это выглядит как грязный хак, но я думаю, что это лучше, чем сохранить временный файл на сервере.

Разместите это здесь, если это будет полезно другим. Я написал пример приложения с открытым исходным кодом, в котором хранятся записи из Google Cloud Text-To-Speech API в Google Cloud Storage. Ответ - это URL-адрес записи, который можно передать<Play> Глагол TwiML.

Это приложение может быть полезно, если вы хотите использовать TTS на языках, которые поддерживаются Google, но не Twilio. По состоянию на декабрь 2019 года к этим языкам относятся:

  • арабский
  • Чешский
  • Филиппинский
  • Греческий
  • Венгерский
  • индонезийский
  • словацкий
  • украинец
  • вьетнамский

В этой статье поддержки представлен список языков, которые поддерживает функция преобразования текста в речь Twilio.

<Response>
    <Play>http://translate.google.com/translate_tts?ie=UTF-8&q=Hello%20World&tl=en-us</Play>
</Response>

синтаксически неверный XML. Это все в порядке

<Response>
    <Play>http://translate.google.com/translate_tts?ie=UTF-8&amp;q=Hello%20World&amp;tl=en-us</Play>
</Response>

Если Twilio не может обработать это, вы должны сообщить об ошибке.

Другие вопросы по тегам