Pull to refresh

Asterisk + UniMRCP + VoiceNavigator. Синтез и распознавание речи в Asterisk. Часть 4

Reading time 7 min
Views 7.8K
VoiceNavigator Asterisk UniMRCP

Часть 1
Часть 2
Часть 3

В четвертой части, как и было обещано, рассмотрим ограничения и недостатки Asterisk как голосовой платформы и особенности его взаимодействия с VoiceNavigator.
Голосовая платформа – это программно-аппаратный комплекс с функциями синтеза и распознавания речи, позволяющий создавать решения, направленные на оптимизацию работы контакт-центра, усовершенствование работы с клиентами и построение систем голосового самообслуживания.

Asterisk голосовой платформой в чистом виде не является, т.к. работа с серверами синтеза и распознавания не является его основной задачей и реализуется посредством UniMRCP. Поэтому часть недостатков и ограничений связана именно с реализацией работы в UniMRCP.

Среди больших и известных голосовых платформ, использующихся в колл-центрах для построения СГС, стоит отметить Avaya Voice Portal, Genesys Voice Platform, Siemens OpenScape CCVP, Cisco Unified CCX, Voxeo, Voxpilot.
Информации в Рунете очень не много, как и специалистов по данным продуктам с соответствующим уровнем компетенции. Используются в больших колл-центрах, стоимость соответствующая, и доступна она только для больших компаний.
Если будет интерес к какой-то из платформ, готов написать о них отдельно.

Два основных недостатка, существующие в Asterisk+UniMRCP — это отсутствие поддержки VoiceXML и неработающий barge-in для синтеза речи.


Отсутствие поддержки VoiceXML

Стандартом индустрии для создания голосовых приложений является использование языка VoiceXML, поддержка которого в UniMRCP и Asterisk отсутствует.

VoiceXML (Voice Extensible Markup Language) – язык, разработанный для создания сценариев звуковых диалогов, который может синтезировать речь, переводить голос в цифровую форму, распознавать DTMF, SGRS-грамматики.
Язык VXML во многом напоминает HTML. VoiceXML страница может содержать текст, который должен
быть озвучен синтезированным голосом, заранее записанные звуковые файлы, а также формы,
позволяющие воспринимать и распознавать речевую информацию. В зависимости от произнесенной
пользователем команды или ввода DTMF, может происходить переход на другие VoiceXML-страницы.


VXML — это то, что используется во всех голосовых платформах и значительно облегчает создание приложений.
Вот пример приложения, которое просит назвать число от нуля до десяти и повторяет названное число. Попробуйте сделать аналогичное в Asterisk и сравнить)
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml" xml:lang="ru-RU">
       <form id="digits">
           <property name="bargein" value="false"/>
             <field name="digitfield">
                <prompt bargein="false">Пожалуйста, назовите число от нуля до десяти.</prompt>
                <noinput>Вы не назвали никакого числа. Пожалуйста, назовите число от нуля до десяти.</noinput>
                <nomatch>Извините, не удалось распознать сказанное число, повторите, пожалуйста.</nomatch>
                <grammar type="application/srgs+xml" version="1.0" mode="voice" root="boolean" xml:lang="ru-RU">
                   <rule id="boolean" scope="public">
                      <one-of>
                         <item>ноль</item>
                         <item>один</item>
                         <item>два</item>
                         <item>три</item>
                         <item>четыре</item>
                         <item>пять</item>
                         <item>шесть</item>
                         <item>семь</item>
                         <item>восемь</item>
                         <item>девять</item>
                         <item>десять</item>
                         <item><ruleref special="GARBAGE"/></item>
                      </one-of>
                   </rule>
                </grammar>
                <filled>
                   <prompt>Вы назвали число <value expr="digitfield"/>.</prompt>
                   <goto next="#digits"/>
                </filled>
             </field>
       </form>
</vxml>

Для Asterisk есть проект VXI* от i6net. Это VoiceXML Browser — интерпретатор VoiceXML для Астериска на базе OpenVXI.
Мои попытки заставить его работать успехом не увенчались. Для распознавания используется UniMRCP, для синтеза какой-то собственный HTTP-TTS коннектор, который разрабатывается под каждый конкретный движок.
К тому же продукт платный.
Если у кого-то есть опыт работы с VXI* или OpenVXI, буду очень рад вашим комментариям.

Отсутствие barge-in для синтеза

В предыдуших статьях я рассказывал про barge-in и параметр f функции MRCPRecog. В качестве этого параметра можно передать звуковой файл, который будет проигрываться как приветствие. Если при этом также установлен параметр b=1, то озвучивание файла прервется при начале речи и запустится сессия распознавания.
Поддержка barge-in обязательная фича, необходимая при построении голосовых приложений. Например, в случае длинного сообщения или когда абонент звонит не первый раз и знает сообщения системы, не нужно заставлять его прослушивать сообщение до конца. Да и вообще, любим мы перебивать других, тем более робота))

Функция MRCPSynth не поддерживает barge-in. Т.е. динамически созданное сообщение, например, ответ системы на предыдущий выбор абонента, прервать нельзя.
Синтез можно прервать DTMF-ом, но в данном случае это не решение.

Как мне видится, при выбранной в UniMRCP реализации, когда синтез и распознавание запускаются разными сессиями, наличие barge-in для синтеза до конца не решит проблему. Даже, если прервать синтез голосом на последующий запуск сессии распознавания, которая идет после синтеза, понадобится время. И в это время не попадут первые доли секунды сказанной абонентом фразы, что может ухудшить качество распознавания. В VoiceXML такой проблемы нет, там barge-in работает и для предзаписанных фраз и для синтеза. Сессия распознавания запускается одновременно с сессией синтеза, точнее даже раньше нее, и голосовая платформа уже готова получать и передавать MRCP-cерверу голосовые данные (см. пример выше).

В приведенном ранее приложении, достаточно поменять bargein=«false» на bargein=«true», чтобы синтезированную речь можно было прерывать.

Способ немного обойти этот недостаток и обмануть barge-in

Основной способ обойти данный недостаток — минимизировать количество синтеза и там где используются статические фразы, стараться применять предзаписанные файлы, особенно в конце фразы.
Т.к. люди часто начинают говорить, не дослушав фразу до конца, то фразу необходимо строить так, чтобы последняя часть была предзаписана и ее можно было прервать. Даже если это будет одно слово.
Например, если мы уточняем сказанную человеком фразу (значение в кавычках — распознанная на предыдущем этапе фраза).
— Вы сказали «отдел продаж»? (синтез)
— Это правильно? (записанная фраза)


— Вы выбрали «операции со счетом» (синтез).
— Подтверждаете?(записанная фраза)


Пример приложения, сообщающего о стоимости проезда и пункта А в пункт Б.
;Используем предзаписанный файл. Спрашиваем: Произнесите город отправления.
exten => app,n(level1),MRCPRecog(${GRAMMARS_PATH}/towns.xml,ct=0.1&b=1&f=${SND_PATH}/level1)
exten => app,n,SET(RECOG_HYP_NUM=0)
exten => app,n,SET(RECOG_UTR0=ошибка)

exten => app,n,AGI(${AGI_PATH}/NLSML.agi,${QUOTE(${RECOG_RESULT})})

;Если город не распознан, идем в приоритет error_start, иначе идем в check_start
exten => app,n,GotoIf($["${RECOG_UTR0}" = "ошибка"]?error_start:check_start)

;Запускаем AGI-скрипт, где проверяем город, что-то считаем и т.д
exten => app,n(check_start),AGI(${AGI_PATH}/check_start.agi)

;В первой части фразы используется синтез с результатом распознавания 
exten => app,n,MRCPSynth(<?xml version=\"1.0\"?><speak version=\" 1.0\" xml:lang=\"ru-ru\" xmlns=\"http://www.w3.org/2001/10/synthesis\"><voice name=\"Мария8000\"><p>Вы выбрали ${Start_Town}.</p></voice></speak>)

;Во второй части - предзаписанный файл: Назовите пункт назначения
exten => app,n(level2),MRCPRecog(${GRAMMARS_PATH}/towns.xml,ct=0.1&b=1&f=${SND_PATH}/level2)
exten => app,n,SET(RECOG_HYP_NUM=0)
exten => app,n,SET(RECOG_UTR0=ошибка)

exten => app,n,AGI(${AGI_PATH}/NLSML.agi,${QUOTE(${RECOG_RESULT})})

;Если город не распознан, идем в приоритет error_finish, иначе идем в check_finish
exten => app,n,GotoIf($["${RECOG_UTR0}" = "ошибка"]?error_start:check_finish)

;Запускаем AGI-скрипт, где проверяем город, считаем стоимость проезда
exten => app,n(check_finish),AGI(${AGI_PATH}/check_finish.agi)

;Сообщаем результаты расчетов 
exten => app,n,MRCPSynth(<?xml version=\"1.0\"?><speak version=\" 1.0\" xml:lang=\"ru-ru\" xmlns=\"http://www.w3.org/2001/10/synthesis\"><voice name=\"Мария8000\"><p>Стоимость проезда из города ${Start_Town} в город ${Finish_Town} составляет ${Price}.</p></voice></speak>)

Ограничение длины переменной в 256 символов

В Asterisk имеется ограничение на длину переменной — 256 символов. Если переменная больше указанного размера, то лишняя часть просто отбрасывается.
Пока я столкнулся с этим ограничением в двух случаях.

1) Необходимо передать на синтез VoiceNavigator строку более 256 символов.
В голосовых меню все фразы должны быть короткими и емкими, но иногда приходится, например, озвучивать справочную информацию, которая может превышать данное ограничение. В этом случае приходится разбивать текст на части не более 256 символов и озвучивать частями.

Наверное, можно найти и перекомпилировать Asterisk с большим значением этого параметра.
Я пока смог найти в исходниках только как изменить размер для переменных, передаваемых в call-файлах, но не во всем Астериске. Если есть умельцы, опять же, буду рад услышать ваш опыт.

2) Необходимо обрабатывать N-Best более 2-х.
N-Best — это количество возвращаемых результатов распознавания. По умолчанию N-Best=1. Можно увеличить его и тогда VocieNavigator будет возвращать несколько результатов распознавания с наибольшими Confidence Level (достоверностью распознавания).
Например, можно брать два наиболее достоверных результата распознавания и если разница в Confidence Level между ними очень низкая, то просить абонента уточнить что именно он сказал:
— Простите, вы сказали коммерческий отдел или отдел исследования космоса?

Если N-Best>2 и MRCP-сервер возвращает более двух ответов, то NLSML-ответ получается больше 256 символов, конец его обрезается, в итоге парсер не может разобрать NLSML, т.к. он становится не валидным.

Этот кейс встречается совсем редко, обычно N-Best=2 достаточно, но помнить об этой проблеме стоит.

Не работает распознавание DTMF

На сегодня VoiceNavigator не умеет понимать DTMF-сигналы от UniMRCP и, соответственно, работать с DTMF-грамматиками. Разработчики обещают решить проблему в ближайшее время.

DTMF распознается непосредственно самим Астериском (это его стандартная возможность), но при этом невозможно предложить пользователю сказать фразу ИЛИ ввести добавочный номер, т.е. распознавать в одной ветке меню и DTMF и голос сейчас нельзя.
Это является серьезным ограничением и должно быть учтено при построении голосового меню.
В связке VoiceNavigator с другими платформами данная проблема отсутствует.

Вот основные проблемы и ограничения, с которыми приходилось сталкиваться при работе в связке Asterisk+UniMRCP+VoiceNavigator.

Готов ответить на ваши вопросы.

PS: У ЦРТ есть тестовый VoiceNavigator, который смотрит в интернет. Если описанные в статьях технологии заинтересовали, пишите в личку, дам контакты и инструкции, куда и что написать, чтобы вам открыли доступ для тестирования.
Tags:
Hubs:
+6
Comments 3
Comments Comments 3

Articles

Information

Website
speechpro.ru
Registered
Founded
1990
Employees
201–500 employees
Location
Россия