Skip to content

ASR modules #2811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build/modules.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ applications/mod_voicemail
#asr_tts/mod_flite
#asr_tts/mod_pocketsphinx
#asr_tts/mod_tts_commandline
#asr_tts/mod_google_asr
#asr_tts/mod_openai_asr
codecs/mod_amr
#codecs/mod_amrwb
codecs/mod_b64
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,8 @@ AC_CONFIG_FILES([Makefile
src/mod/asr_tts/mod_flite/Makefile
src/mod/asr_tts/mod_pocketsphinx/Makefile
src/mod/asr_tts/mod_tts_commandline/Makefile
src/mod/asr_tts/mod_google_asr/Makefile
src/mod/asr_tts/mod_openai_asr/Makefile
src/mod/codecs/mod_amr/Makefile
src/mod/codecs/mod_amrwb/Makefile
src/mod/codecs/mod_b64/Makefile
Expand Down
12 changes: 12 additions & 0 deletions src/mod/asr_tts/mod_google_asr/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

include $(top_srcdir)/build/modmake.rulesam

MODNAME=mod_google_asr
mod_LTLIBRARIES = mod_google_asr.la
mod_google_asr_la_SOURCES = mod_google_asr.c utils.c curl.c
mod_google_asr_la_CFLAGS = $(AM_CFLAGS) -I. -Wno-pointer-arith
mod_google_asr_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_google_asr_la_LDFLAGS = -avoid-version -module -no-undefined -shared

$(am_mod_google_asr_la_OBJECTS): mod_google_asr.h

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<configuration name="google_asr.conf" description="">
<settings>
<!-- api settings -->
<param name="api-url" value="https://speech.googleapis.com/v1/speech:recognize?key=${api-key}" />
<param name="api-key" value="---YOUR-API-KEY---" />

<!-- curl settings -->
<param name="connect-timeout" value="5" />
<param name="request-timeout" value="25" />
<!-- <param name="proxy" value="http://proxy:port" /> -->
<!-- <param name="proxy-credentials" value="" /> -->
<!-- <param name="user-agent" value="Mozilla/1.0" /> -->

<!-- capture settings -->
<param name="speech-max-sec" value="45" />
<param name="speech-silence-sec" value="3" />
<param name="retries-on-error" value="3" />

<param name="vad-debug" value="false" />
<param name="vad-silence-ms" value="400" />
<param name="vad-voice-ms" value="200" />
<param name="vad-threshold" value="100" />

<!-- service settings -->
<param name="encoding" value="l16" />
<param name="default-language" value="en" />
<param name="max-alternatives" value="1" />
<param name="speech-model" value="phone_call" />
<param name="use-enhanced-model" value="false" />
<param name="enable-word-time-offsets" value="false" />
<param name="enable-word-confidence" value="false" />
<param name="enable-profanity-filter" value="false" />
<param name="enable-automatic-punctuation" value="false" />
<param name="enable-spoken-punctuation" value="false" />
<param name="enable-spoken-emojis" value="false" />
<param name="microphone-distance" value="nearfield" />
<param name="recording-device-type" value="phone_line" />
<param name="interaction-type" value="unspecified" />

</settings>
</configuration>

11 changes: 11 additions & 0 deletions src/mod/asr_tts/mod_google_asr/conf/dialplan/dialplan.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

<extension name="asr">
<condition field="destination_number" expression="^(3222)$">
<action application="answer"/>
<action application="play_and_detect_speech" data="conference/8000/conf-welcome.wav detect:google {lang=en}"/>
<action application="sleep" data="1000"/>
<action application="log" data="INFO SPEECH_RESULT=${detect_speech_result}"/>
<action application="sleep" data="1000"/>
<action application="hangup"/>
</condition>
</extension>
129 changes: 129 additions & 0 deletions src/mod/asr_tts/mod_google_asr/curl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Module Contributor(s):
* Konstantin Alexandrin <akscfx@gmail.com>
*
*
*/
#include "mod_google_asr.h"

static size_t curl_io_write_callback(char *buffer, size_t size, size_t nitems, void *user_data) {
asr_ctx_t *asr_ctx = (asr_ctx_t *)user_data;
size_t len = (size * nitems);

if(len > 0 && asr_ctx->curl_recv_buffer_ref) {
switch_buffer_write(asr_ctx->curl_recv_buffer_ref, buffer, len);
}

return len;
}

static size_t curl_io_read_callback(char *buffer, size_t size, size_t nitems, void *user_data) {
asr_ctx_t *asr_ctx = (asr_ctx_t *)user_data;
size_t nmax = (size * nitems);
size_t ncur = (asr_ctx->curl_send_buffer_len > nmax) ? nmax : asr_ctx->curl_send_buffer_len;

if(ncur > 0) {
memmove(buffer, asr_ctx->curl_send_buffer_ref, ncur);
asr_ctx->curl_send_buffer_ref += ncur;
asr_ctx->curl_send_buffer_len -= ncur;
}

return ncur;
}

switch_status_t curl_perform(asr_ctx_t *asr_ctx, globals_t *globals) {
switch_status_t status = SWITCH_STATUS_SUCCESS;
CURL *curl_handle = NULL;
switch_curl_slist_t *headers = NULL;
char *epurl = NULL;
switch_CURLcode curl_ret = 0;
long http_resp = 0;

if(asr_ctx->api_key) {
epurl = switch_string_replace(globals->api_url, "${api-key}", asr_ctx->api_key);
} else {
epurl = strdup(globals->api_url);
}

curl_handle = switch_curl_easy_init();
headers = switch_curl_slist_append(headers, "Content-Type: application/json; charset=utf-8");

switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
switch_curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, curl_io_read_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_READDATA, (void *)asr_ctx);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, curl_io_write_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)asr_ctx);

if(globals->connect_timeout > 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, globals->connect_timeout);
}
if(globals->request_timeout > 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals->request_timeout);
}
if(globals->user_agent) {
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, globals->user_agent);
}
if(strncasecmp(epurl, "https", 5) == 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
if(globals->proxy) {
if(globals->proxy_credentials != NULL) {
switch_curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
switch_curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, globals->proxy_credentials);
}
if(strncasecmp(globals->proxy, "https", 5) == 0) {
switch_curl_easy_setopt(curl_handle, CURLOPT_PROXY_SSL_VERIFYPEER, 0);
}
switch_curl_easy_setopt(curl_handle, CURLOPT_PROXY, globals->proxy);
}

switch_curl_easy_setopt(curl_handle, CURLOPT_URL, epurl);

curl_ret = switch_curl_easy_perform(curl_handle);
if(!curl_ret) {
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_resp);
if(!http_resp) { switch_curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CONNECTCODE, &http_resp); }
} else {
http_resp = curl_ret;
}

if(http_resp != 200) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "http-error=[%ld] (%s)\n", http_resp, globals->api_url);
status = SWITCH_STATUS_FALSE;
}

if(asr_ctx->curl_recv_buffer_ref) {
if(switch_buffer_inuse(asr_ctx->curl_recv_buffer_ref) > 0) {
switch_buffer_write(asr_ctx->curl_recv_buffer_ref, "\0", 1);
}
}

if(curl_handle) {
switch_curl_easy_cleanup(curl_handle);
}

if(headers) {
switch_curl_slist_free_all(headers);
}

switch_safe_free(epurl);
return status;
}
Loading