Last active
March 24, 2017 06:30
-
-
Save aylarov/0a699701815c05f6557a2d4d486800dc to your computer and use it in GitHub Desktop.
VoxEngine scenario for Babelfish app - Gatekeeper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require(Modules.ASR); | |
require(Modules.Recorder); | |
/** | |
* Conference Gatekeeper | |
* Handle inbound calls and route them to the conference | |
*/ | |
var call, | |
conferenceId, | |
conf, | |
API_KEY = "YOUR_GOOGLE_TRANSLATE_API_KEY", | |
translateFrom, | |
translateTo, | |
asrLanguage, | |
ttsLanguage, | |
ttsEnabled = false, | |
voice = null, | |
asr, vad, ts, ts2; | |
var decodeHtmlEntity = function (str) { | |
return str.replace(/&#(\d+);/g, function (match, dec) { | |
return String.fromCharCode(dec); | |
}); | |
}; | |
/** | |
* Inbound call handler | |
*/ | |
VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) { | |
// Get conference id from headers | |
conferenceId = e.headers['X-Conference-Id']; | |
Logger.write('User ' + e.callerid + ' is joining conference ' + conferenceId); | |
call = e.call; | |
/** | |
* Add event listeners | |
*/ | |
call.addEventListener(CallEvents.Connected, sdkCallConnected); | |
call.addEventListener(CallEvents.Disconnected, function (e) { | |
VoxEngine.terminate(); | |
}); | |
call.addEventListener(CallEvents.Failed, function (e) { | |
VoxEngine.terminate(); | |
}); | |
call.addEventListener(CallEvents.MessageReceived, function (e) { | |
// Process text message arrived from client | |
Logger.write("Message Received: " + e.text); | |
try { | |
var msg = JSON.parse(e.text); | |
} catch (err) { | |
Logger.write(err); | |
} | |
if (msg.type == "ICE_FAILED") { | |
// P2P call ICE problems | |
conf.sendMessage(e.text); | |
} else if (msg.type == "ENABLE_TTS") { | |
// Text-to-speech enabled | |
ttsEnabled = true; | |
voice = msg.voice; | |
Logger.write("TTS voice: " + voice); | |
} else if (msg.type == "DISABLE_TTS") { | |
// Text-to-speech disabled | |
ttsEnabled = false; | |
} else if (msg.type == "ASR_START") { | |
/** | |
* Start recognition and translation | |
*/ | |
translateFrom = msg.fromLanguage; | |
translateTo = msg.toLanguage; | |
e.call.handleMicStatus(true); | |
e.call.addEventListener(CallEvents.MicStatusChange, handleMicStatus); | |
switch (translateFrom) { | |
case "en": | |
asrLanguage = ASRLanguage.ENGLISH_US; | |
break; | |
case "ru": | |
asrLanguage = ASRLanguage.RUSSIAN_RU; | |
break; | |
case "de": | |
asrLanguage = ASRLanguage.GERMAN_DE; | |
break; | |
case "fr": | |
asrLanguage = ASRLanguage.FRENCH_FR; | |
break; | |
case "es": | |
asrLanguage = ASRLanguage.SPANISH_ES; | |
break; | |
} | |
/** | |
* Create ASR instance | |
*/ | |
asr = VoxEngine.createASR({ | |
lang: asrLanguage, | |
singleUtterance: true, | |
interimResults: true | |
}); | |
/** | |
* Notify client about SpeechCaptured event | |
*/ | |
asr.addEventListener(ASREvents.SpeechCaptured, function (asrevent) { | |
e.call.sendMessage(JSON.stringify({ | |
type: "SPEECH_CAPTURED" | |
})); | |
}); | |
/** | |
* Notify client about CaptureStarted event | |
*/ | |
asr.addEventListener(ASREvents.CaptureStarted, function (asrevent) { | |
clearTimeout(ts); | |
e.call.sendMessage(JSON.stringify({ | |
type: "CAPTURE_STARTED" | |
})); | |
}); | |
/** | |
* Process interim recognition result | |
*/ | |
asr.addEventListener(ASREvents.InterimResult, function (asrevent) { | |
e.call.sendMessage(JSON.stringify({ | |
type: "RESULT", | |
text: asrevent.text, | |
confidence: asrevent.confidence, | |
stability: asrevent.stability, | |
result_type: "INTERIM_RESULT" | |
})); | |
}); | |
/** | |
* Process final recognition result | |
*/ | |
asr.addEventListener(ASREvents.Result, function (asrevent) { | |
// Send result to conference that will re-send it to other participant | |
conf.sendMessage(JSON.stringify({ | |
type: "RESULT", | |
text: asrevent.text, | |
confidence: asrevent.confidence, | |
result_type: "RECOGNITION" | |
})); | |
// Send result to client | |
e.call.sendMessage(JSON.stringify({ | |
type: "RESULT", | |
text: asrevent.text, | |
confidence: asrevent.confidence, | |
result_type: "LOCAL_RECOGNITION" | |
})); | |
/** | |
* Translate result using Google Translate API | |
*/ | |
Logger.write("Making HTTP request for translation " + translateFrom + " => " + translateTo); | |
Net.httpRequest("https://www.googleapis.com/language/translate/v2?key=" + | |
API_KEY + | |
"&source=" + translateFrom + | |
"&target=" + translateTo + | |
"&q=" + encodeURIComponent(asrevent.text), | |
function (result) { | |
handleTranslationResult(result, asrevent.confidence, e.call); | |
}); | |
}); | |
/** | |
* Start streaming call audio to ASR instance | |
*/ | |
e.call.sendMediaTo(asr); | |
} else if (msg.type == "ASR_STOP") { | |
/** | |
* Stop ASR | |
*/ | |
e.call.handleMicStatus(false); | |
e.call.removeEventListener(CallEvents.MicStatusChange); | |
e.call.stopMediaTo(asr); | |
asr.stop(); | |
} | |
}); | |
// Answer the call | |
call.answer(); | |
}); | |
/** | |
* Process the translation result received from Google Translate API | |
*/ | |
function handleTranslationResult(e, confidence, c) { | |
Logger.write("handleTranslationResult code: " + e.code); | |
if (e.code == 200) { | |
try { | |
var result = JSON.parse(e.text); | |
Logger.write("Translation result: " + result.data.translations[0].translatedText); | |
// Send the translation result to client | |
call.sendMessage(JSON.stringify({ | |
type: "RESULT", | |
text: decodeHtmlEntity(result.data.translations[0].translatedText), | |
confidence: confidence, | |
result_type: "LOCAL_TRANSLATION" | |
})); | |
// Send the translation result to the conference for other participant | |
conf.sendMessage(JSON.stringify({ | |
type: "RESULT", | |
text: decodeHtmlEntity(result.data.translations[0].translatedText), | |
confidence: confidence, | |
result_type: "TRANSLATION", | |
tts: ttsEnabled, | |
language: translateTo, | |
voice: voice | |
})); | |
} catch (err) { | |
Logger.write(JSON.stringify(err)); | |
} | |
} | |
} | |
/** | |
* Handle microphone status | |
*/ | |
function handleMicStatus(e) { | |
if (e.active) { | |
vad = true; | |
e.call.sendMessage(JSON.stringify({ | |
type: "VAD", | |
status: true | |
})); | |
} else { | |
vad = false; | |
e.call.sendMessage(JSON.stringify({ | |
type: "VAD", | |
status: false | |
})); | |
} | |
} | |
/** | |
* Connected handler | |
*/ | |
function sdkCallConnected(e) { | |
Logger.write('Joining conference'); | |
// Call standalone conference with specified conference id | |
conf = VoxEngine.callConference('conf_' + conferenceId, call.callerid(), call.displayName(), { | |
"X-ClientType": "web" | |
}); | |
Logger.write('CallerID: ' + call.callerid() + ' DisplayName: ' + call.displayName()); | |
// Add event listeners | |
conf.addEventListener(CallEvents.Connected, function (e) { | |
Logger.write("Conference Connected"); | |
// Send media between client call and conference | |
VoxEngine.sendMediaBetween(conf, call); | |
// Notify client that conference call connected | |
call.sendMessage(JSON.stringify({ | |
type: "CONF", | |
result: "connected" | |
})); | |
}); | |
conf.addEventListener(CallEvents.Disconnected, VoxEngine.terminate); | |
conf.addEventListener(CallEvents.Failed, function (e) { | |
/** | |
* Conference scenario rejects calls if 2 participants are already connected | |
*/ | |
if (e.headers["X-Reason"] == "ROOM_IS_FULL") { | |
call.say("The room is full", Language.US_ENGLISH_FEMALE); | |
call.addEventListener(CallEvents.PlaybackFinished, function (event) { | |
call.hangup({ | |
"X-Reason": e.headers["X-Reason"] | |
}); | |
}); | |
} | |
}); | |
/** | |
* Process messages coming from the conference | |
*/ | |
conf.addEventListener(CallEvents.MessageReceived, function (e) { | |
var result = JSON.parse(e.text); | |
if (result["result_type"] == "TRANSLATION") { | |
if (result["tts"] == true) { | |
switch (result["language"]) { | |
case "en": | |
if (result["voice"] == 0) ttsLanguage = Language.US_ENGLISH_MALE; | |
else ttsLanguage = Language.US_ENGLISH_FEMALE; | |
break; | |
case "ru": | |
if (result["voice"] == 0) ttsLanguage = Language.RU_RUSSIAN_MALE; | |
else ttsLanguage = Language.RU_RUSSIAN_FEMALE; | |
break; | |
case "de": | |
if (result["voice"] == 0) ttsLanguage = Language.EUR_GERMAN_MALE; | |
else ttsLanguage = Language.EUR_GERMAN_FEMALE; | |
break; | |
case "fr": | |
if (result["voice"] == 0) ttsLanguage = Language.EUR_FRENCH_MALE; | |
else ttsLanguage = Language.EUR_FRENCH_FEMALE; | |
break; | |
case "es": | |
if (result["voice"] == 0) ttsLanguage = Language.EUR_SPANISH_MALE; | |
else ttsLanguage = Language.EUR_SPANISH_FEMALE; | |
break; | |
} | |
call.say(result.text, ttsLanguage); | |
} | |
} | |
call.sendMessage(e.text); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment