Напишите простой IVR в FreeSWITCH
Напишите простой IVR в FreeSWITCH

IVR (Интерактивный голосовой ответ) — это интерактивный голосовой ответ, который мы называем голосовым меню телефона. Он может использовать предварительно записанный голос или TTS для автоматического ответа и обеспечения навигации по меню. Он в основном используется в системах колл-центров. В основном мы представляем функции IVR, предоставляемые FreeSWITCH.

Файл конфигурации по умолчанию системы IVR FreeSWITCH — conf/autoload_configs/ivr.conf.xml.

, который содержит все файлы XML в каталоге conf/ivr_menus/. Затем мы создаем файл конфигурации XML conf/ivr_menus/ivr.xml со следующим содержимым.

Язык кода:javascript
копировать
<include>
    <menus>
        <menu name="welcome"
            greet-long="ivr/welcome.wav"
            greet-short="ivr/welcom_short.wav"
            invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
            exit-sound="voicemail/vm-goodbye.wav"
            timeout="15000"
            max-failures="3"
            max-timeouts="3"
            inter-digit-timeout="2000"
            digit-len="4">
            <entry action="menu-exec-app" digits="0" param="transfer 1000 XML default"/>
            <entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML default"/>
        </menu>
    </menus>
</include>

В приведенной выше конфигурации сначала указываем, что название меню приветствуется, а значения остальных пунктов следующие:

  • Greeting-long: определяет начальный тон приветствия, который представляет собой звук, воспроизводимый в начале, например: «Здравствуйте, добро пожаловать в Yantai Little Cherry Network Technology Co., Ltd., наберите добавочный номер напрямую, наберите 0», это voice По умолчанию файл должен находиться в каталоге /usr/local/freeswitch/sounds.
  • приветствие-короткое: этот элемент определяет короткий звуковой сигнал. Если пользователь не нажимает кнопку в течение длительного времени и время выполнения операции истекло, снова будет воспроизводиться приветственный сигнал, например: «Пожалуйста, наберите добавочный номер напрямую. Пожалуйста, наберите». 0 для запроса каталога».
  • недопустимый звук: этот запрос используется, если пользователь нажимает неправильную клавишу. Если вы установили звуковой файл с помощью команды «make sound-install» во время установки, файл должен существовать по умолчанию.
  • exit-sound: Этот элемент определяет звук при выходе из последнего меню. По умолчанию будет предложено «До свидания».
  • таймаут: укажите таймаут (в миллисекундах), максимальный таймаут ожидания нажатия клавиш пользователем.
  • max-failures: относится к количеству допустимых ошибок нажатия клавиш пользователем. Если нажатия клавиш пользователя не соответствуют всем конфигурациям меню, происходит сбой.
  • max-timeouts: максимальное количество таймаутов.
  • межцифровой таймаут: максимальный интервал (миллисекунды) между двумя нажатиями клавиш. Например, когда пользователь набирает добавочный номер 1001, предположим, что он набирает 10, ждет 5 секунд, а затем нажимает 01. В это время система фактически получает номер 10 (последующий 01 не поступает по таймауту), и указанный недопустимый звук воспроизводится для обозначения ошибок.
  • digit-len: определяет длину пункта меню, то есть максимальное количество цифр для сбора. В этом примере добавочный номер пользователя имеет длину 4 цифры, поэтому мы используем 4. При получении нажатия 4-значной клавиши соответствующее действие будет выполнено немедленно, в противном случае будет выполнено ожидание, пока время нажатия клавиши не истечет.

Видно, что действия ivr в основном настраиваются в элементе записи. В приведенном выше примере кнопка 0 настраивается в первой записи, а приложение FreeSWITCH (передача) выполняется через меню-exec-app и маршрутизируется через него. Снова назначьте вызов правилу маршрутизации, вызываемый номер которого равен 1000. По умолчанию правилом является добавочный номер 1000.

Ключевое правило другой записи в меню — это регулярное выражение, что означает, что соответствующий ключ — это ввод значений 1001 ~ 1019. После успешного сопоставления ключу будет присвоен $1, а затем маршрутизация будет произведена снова. Например, если пользователь вводит ключ 1019, вызов будет назначен правилу маршрутизации, вызываемый номер которого равен 1019, при выполнении перевода. По умолчанию правилом является добавочный номер 1019.

Если входящий пользователь нажмет другие клавиши, появится сообщение об ошибке (звук, указанный в параметре valid-sound), поскольку соответствующий пункт меню не найден, и пользователю будет предложено войти повторно.

После установки вышеуказанного меню необходимо выполнить reloadxml в консоли, чтобы конфигурация вступила в силу.

После завершения настройки можно выполнить на консоли следующий тест (позвоните по номеру 1001 и после ответа войдите в меню ivr):

Язык кода:javascript
копировать
 freeswitch> originate user/1001 &ivr(welcome)

После успешного прохождения теста вы можете настроить диалплан для перевода входящих звонков в меню и добавить расширение в диалплан (обратите внимание, что вам нужно добавить его в правильный контекст диалплана, если вы не уверены, в какой контекст его следует добавить to) , будет безопаснее добавить его как по умолчанию, так и по умолчанию):

Язык кода:javascript
копировать
<extension name="incoming_call">
    <condition field="destination_number" expression="^777$">
        <action application="answer" data=""/>
        <action application="sleep" data="1000"/>
        <action application="ivr" data="welcome"/>
    </condition>
</extension>

Затем позвоните по номеру 777 для тестирования.

Благодаря приведенной выше конфигурации ivr.xml мы уже знаем, как настроить простой IVR. Далее мы настраиваем IVR со дополнительным меню.

Язык кода:javascript
копировать
<include>
    <menus>
        <menu name="main"
            greet-long="ivr/main_welcome.wav"
            greet-short="ivr/main_welcome_short.wav"
            invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
            exit-sound="voicemail/vm-goodbye.wav"
            timeout ="10000"
            max-failures="3"
            digit-len="4">
            <entry action="menu-exit" digits="*"/>
            <entry action="menu-sub" digits="2" param="sub"/>
            <entry action="menu-exec-app" digits="0" param="transfer 1000 XML default"/>
        </menu>
    </menus>
</include>
Язык кода:javascript
копировать
<include>
    <menus>
        <menu name="sub"
            greet-long="ivr/sub_welcome.wav"
            greet-short="ivr/web_welcome_short.wav"
            invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
            exit-sound="voicemail/vm-goodbye.wav"
            timeout="15000"
            max-failures="3"
            max-timeouts="3"
            inter-digit-timeout="2000"
            digit-len="4">
            <entry action="menu-exit" digits="*"/>
            <entry action="menu-back" digits="6"/>
            <entry action="menu-top" digits="7"/>
            <entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML default"/>
        </menu>
    </menus>
</include>

Два IVR настроены выше,Именаmainsub,Как следует из названия,main - главное меню,подменю, Давайте сначала представим действия в записи:

  • Menu-exit: выход из всего меню IVR.
  • меню-подменю: введите подменю, такое как приведенный выше XML, мы используем подменю в качестве подменю
  • Menu-Back: возврат в предыдущее меню.
  • Menu-top: возврат в главное меню, которое является меню первого уровня.
  • меню-exec-app: выполнить соответствующее приложение, например передачу

После настройки XML вам также необходимо выполнить команду reloadxml в консоли, чтобы конфигурация вступила в силу.

После завершения настройки вы можете выполнить следующий тест на консоли (все равно позвоните по номеру 1001 и войдите в меню ivr после ответа):

Язык кода:javascript
копировать
freeswitch> originate user/1001 &ivr(main)

После входа в главное меню мы можем нажать 2, чтобы войти в подменю. В подменю, если мы можем нажать 6, чтобы вернуться в предыдущее меню, нажмите 7, чтобы вернуться в главное меню. Однако, поскольку у нас есть только один уровень подменю. , здесь клавиши 6 и 7. Эффект тот же. Если читатели заинтересованы, вы можете настроить несколько подменю, чтобы проверить разницу между верхним и задним меню.

Однако мы также видели, что приведенный выше XML IVR чрезвычайно прост. В реальном бизнесе нам может потребоваться взаимодействовать с некоторыми внешними службами, например, выполнять запросы к базе данных, запрашивать веб-сервис и т. д., поэтому нам нужен более гибкий способ. настраиваем приложение IVR, здесь мы представляем IVR, реализованный с использованием Lua:

Модуль mod_lua FreeSWITCH поддерживает язык Lua. Поскольку Lua является встроенным языком и его можно легко встроить в программу, использование Lua приносит нам много удобства. Последний модуль уже поддерживает Lua 5.2. Далее мы используем Lua для реализации описанного выше WelcomeIVR.

Язык кода:javascript
копировать
local tts_engine = "tts_commandline"
local tts_voice = "zh-CN-XiaoxiaoNeural"
session:set_tts_params(tts_engine, tts_voice)
session:setVariable("tts_engine", tts_engine)
session:setVariable("tts_voice", tts_voice)
session:answer()
session:sleep(1000)
local digits = session:playAndGetDigits(1, 4, 3, 15000, "#", «Скажите: Добро пожаловать в использование интеллектуального голосового продукта Xiaoying Cherry, наберите добавочный номер напрямую. Чтобы проверить номер, наберите 0», "скажите: ошибка ввода", "^(0|10[0-1][0-9]$)", "digits", 2000)
if digits ~= "" and digits ~= nil then
    if digits == "0" then
        session:transfer("1000 XML default")
    else
        session:transfer(digits .. " XML default")
    end
else
    session:speak("До свидания")
end

Мы можем сохранить приведенный выше lua в каталог сценариев FreeSWITCH и назвать его Welcome.lua. После завершения настройки мы можем выполнить следующий тест на консоли (все еще вызывая 1001 и войдя в меню ivr после ответа).

Язык кода:javascript
копировать
freeswitch> originate user/1001 &lua(welcome.lua)

После ответа на звонок мы услышим приветственное сообщение, например: «Добро пожаловать в интеллектуальный голосовой продукт Xiaoying Cherry. Пожалуйста, наберите добавочный номер напрямую. Чтобы проверить номер, наберите 0. Как видите, мы не использовали записанный». на этот раз голосовой файл для приветственного сообщения. Вместо этого используется TTS. Вышеупомянутый TTS использует Edge-tts.

Мы можем добиться того же эффекта, что и IVR XML, нажав 0# и, соответственно, нажав 1001~1019, чтобы перейти к соответствующему маршруту расширения. Следует отметить, что мы упомянули выше о нажатии 0#. Конечно, мы также можем просто нажать 0, но нам нужно подождать тайм-аут в 2 секунды. Нажатие # означает, что нажатие клавиши завершено. Нам не нужно ждать таймаута и программа продолжит работу.

Далее мы представляем playAndGetDigits.

Язык кода:javascript
копировать
digits = session:playAndGetDigits (
          min_digits, max_digits, max_attempts, timeout, terminators,
          prompt_audio_files, input_error_audio_files,
          digit_regex, variable_name, digit_timeout,
          transfer_on_failure)
  • min_digits: минимальная длина ключа
  • max_digits: максимальная длина ключа
  • max_attempts: количество раз, когда ключи не совпадают или ключи не получены.
  • timeout: время ожидания нажатия клавиши, единица измерения — миллисекунды.
  • терминаторы: ключевые терминаторы
  • Prompt_audio_files: файл, который будет воспроизводиться изначально, это может быть записанный аудиофайл, TTS и т. д. Если во время воспроизведения будет получено нажатие клавиши, воспроизведение будет прервано. Если кнопка не получена, воспроизведение будет повторяться до достижения max_attempts.
  • input_error_audio_files: аудиофайлы, воспроизводимые при получении нажатия клавиши, не соответствующего digit_regex. Если вы не используете эту функцию, вы можете установить пустую строку или воспроизвести тихий поток, например Silence_stream://1000.
  • digit_regex: регулярное выражение для проверки полученных нажатий клавиш.
  • имя_переменной: необязательный параметр, используемый для хранения переменной канала кнопки.
  • digit_timeout: Необязательный параметр, параметр времени ожидания между нажатиями клавиш.
  • Transfer_on_failure: Необязательный параметр, действие, которое необходимо выполнить после сбоя ключа. Синтаксис: имя расширения [идентификатор плана набора [контекст]], например 1000 XML по умолчанию.

Следует отметить, что использование playAndGetDigits в Lua имеет ту же функцию, что и использование play_and_get_digits в XML Dialplan, за исключением того, что параметры немного отличаются. В первом случае параметр digit_regex предшествует имени переменной, а во втором — наоборот. Читателям следует быть осторожными, чтобы не сделать наоборот.

В приведенном выше примере некоторые читатели могут спросить, можем ли мы просто нажать 0 в приведенном выше Lua, не дожидаясь двухсекундного таймаута. Ответ — да? Давайте просто оптимизируем приведенный выше скрипт Lua.

Язык кода:javascript
копировать
local tts_engine = "tts_commandline"
local tts_voice = "zh-CN-XiaoxiaoNeural"
session:set_tts_params(tts_engine, tts_voice)
session:setVariable("tts_engine", tts_engine)
session:setVariable("tts_voice", tts_voice)
session:answer()
session:sleep(1000)
local first_digit = session:playAndGetDigits(1, 1, 3, 15000, "#", «Скажите: Добро пожаловать в использование интеллектуального голосового продукта Xiaoying Cherry, наберите добавочный номер напрямую. Чтобы проверить номер, наберите 0», "сказать: Ошибка ввода, пожалуйста, введите еще раз", "[0-1]", "first_digit", 2000)
if first_digit ~= "" and first_digit ~= nil then
    if first_digit == "0" then
        session:transfer("1000 XML default")
    else
        local remain_digits = session:playAndGetDigits(3, 3, 3, 2000, "#", "silence_stream://1000", "сказать: Ошибка ввода, пожалуйста, введите еще раз", "^(0[0-1][0-9]$)", "remain_digits", 2000)
        session:transfer(first_digit .. remain_digits .. " XML default")
    end
else
    session:speak("До свидания")
end
Язык кода:javascript
копировать
Вышеупомянутый оптимизированный скрипт,мы можем видеть,Соберите ключи в два шага,Сначала соберите первую пуговицу,Следовательно, min_digits и min_digits можно установить равными 1.,Это позволяет избежать нажатия знака решетки и ожидания истечения времени ожидания клавиши. После сбора первого ключа,Остальные пуговицы вы можете собрать в соответствии с реальными условиями.

Выше мы реализовали очень простой и распространенный сценарий IVR и изучили простой процесс. Читатели могут объединить реальную ситуацию и написать более мощный сценарий IVR. Давайте сейчас напишем его.

Ссылка на литературу:

  • https://freeswitch.org/confluence/display/FREESWITCH/Lua+API+Reference
  • https://freeswitch.org/confluence/display/FREESWITCH/mod_dptools%3A+play_and_get_digits
boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода