Skip to content

Instantly share code, notes, and snippets.

@aylarov
Last active May 27, 2020 08:03
Show Gist options
  • Save aylarov/9f7bee706bad5eb83e11e2f7ecbe9370 to your computer and use it in GitHub Desktop.
Save aylarov/9f7bee706bad5eb83e11e2f7ecbe9370 to your computer and use it in GitHub Desktop.
Voximplant Speech Recognition demo. VoxEngine scenario and web client
<!DOCTYPE html>
<html>
<head>
<title>Voximplant Speech Recognition Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
<script type="text/javascript" src="//cdn.voximplant.com/voximplant.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<script type="text/javascript">
var sdk = VoxImplant.getInstance(), call, rec_result = "&nbsp;";
sdk.addEventListener(VoxImplant.Events.SDKReady, onSDKReady);
sdk.addEventListener(VoxImplant.Events.ConnectionEstablished, onConnectionEstablished);
sdk.addEventListener(VoxImplant.Events.ConnectionClosed, onConnectionClosed);
sdk.addEventListener(VoxImplant.Events.ConnectionFailed, onConnectionFailed);
sdk.addEventListener(VoxImplant.Events.MicAccessResult, onMicAccessResult);
sdk.addEventListener(VoxImplant.Events.AuthResult, onAuthResult);
sdk.init({
micRequired: true
});
function onSDKReady(e) {
console.log("Voximplant SDK ver. "+e.version+" initialized");
$('div.label').html("Please allow access to your microphone");
sdk.connect();
}
function onMicAccessResult(e) {
if (e.result) {
$('div.label').html("Establishing connection...");
} else {
$('div.label').html("You need to allow access to use this application");
}
}
function onConnectionEstablished() {
$('div.label').html("Authorizing...");
sdk.login(USERNAME, PASSWORD);
}
function onConnectionClosed() {
$('div.label').html("Network connection has been closed");
}
function onConnectionFailed() {
$('div.label').html("Couldn't connect to Voximplant: check if UDP is allowed");
}
function onAuthResult(e) {
if (e.result) {
$('div.label').html("Idle");
$('div.preloader-wrapper').remove();
$('#container').append("<a onclick='javascript:makeCall()' class='waves-effect green btn-large'><i class='material-icons left'>mic</i>Start</a>");
} else {
$('div.label').html("Authorization error");
}
}
function makeCall() {
$('a.btn-large').remove();
$('div.label').html("Calling...");
call = sdk.call("recognizer");
call.addEventListener(VoxImplant.CallEvents.Connected, onCallConnected);
call.addEventListener(VoxImplant.CallEvents.Failed, onCallFailed);
call.addEventListener(VoxImplant.CallEvents.Disconnected, onCallDisconnected);
call.addEventListener(VoxImplant.CallEvents.MessageReceived, onMessageReceived);
}
function hangupCall() {
call.hangup();
}
function onCallConnected(e) {
$('div.label').html("Call connected");
$('#container').append("<a onclick='javascript:hangupCall()' class='waves-effect red btn-large'><i class='material-icons left'>mic_none</i>Stop</a>");
}
function onCallFailed(e) {
$('div.label').html("Call error: "+e.code+" ("+e.reason+") ");
$('a.btn-large').remove();
$('#container').append("<a onclick='javascript:makeCall()' class='waves-effect green btn-large'><i class='material-icons left'>mic</i>Start</a>");
}
function onCallDisconnected(e) {
rec_result = "&nbsp;"
$('div.label').html("Idle");
$('a.btn-large').remove();
$('#container').append("<a onclick='javascript:makeCall()' class='waves-effect green btn-large'><i class='material-icons left'>mic</i>Start</a>");
removeResultContainer();
}
function onMessageReceived(e) {
try {
var result = JSON.parse(e.text);
if (result.type == "RESULT") {
rec_result = rec_result + " " + result.text;
$('div.card-panel span').html( rec_result );
}
if (result.type == "CAPTURE_STARTED") {
if ( !$('div.row').length ) {
createResultContainer();
}
$('div.card-panel span').html( rec_result + "<div class='loader'></div>");
}
} catch (e) {
console.log(e);
}
}
function createResultContainer() {
$('#container').append("<div class='row'></div>");
$('div.row').append("<div class='col'></div>");
$('div.col').append("<div class='card-panel'></div>");
$('div.card-panel').append("<span class='blue-text text-darken-2'></span>");
}
function removeResultContainer() {
$('div.row').remove();
}
</script>
<style>
body, html {
width: 100%;
height: 100%;
display: flex;
align-content: center;
}
#container {
display: flex;
width: 100%;
height: 100%;
align-self: center;
align-content: center;
justify-content: center;
flex-direction: column;
}
div.preloader-wrapper {
align-self: center;
margin: 10px;
}
div.label {
margin-top: 20px;
align-self: center;
}
a.btn-large {
align-self: center;
}
div.row {
align-self: center;
}
.loader,
.loader:after {
border-radius: 50%;
width: 16px;
height: 16px;
margin-left: 5px;
}
.loader {
display: inline-block;
font-size: 16px;
position: relative;
text-indent: -9999em;
border-top: 3px solid rgba(0, 0, 0, 0.2);
border-right: 3px solid rgba(0, 0, 0, 0.2);
border-bottom: 3px solid rgba(0, 0, 0, 0.2);
border-left: 3px solid #333333;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div id="container">
<div class="preloader-wrapper big active">
<div class="spinner-layer spinner-blue">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-red">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-yellow">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
<div class="spinner-layer spinner-green">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
<div class="label">Initializing...</div>
</div>
</body>
</html>
require(Modules.ASR);
require(Modules.Player);
var mycall,
myasr,
player,
ts,
ts2,
vad = false;
VoxEngine.addEventListener(AppEvents.CallAlerting, function (e) {
mycall = e.call;
e.call.addEventListener(CallEvents.Connected, handleCallConnected);
e.call.answer();
});
function handleCallConnected(e) {
mycall.handleMicStatus(true);
mycall.addEventListener(CallEvents.MicStatusChange, handleMicStatus);
mycall.addEventListener(CallEvents.Disconnected, VoxEngine.terminate);
myasr = VoxEngine.createASR({
lang: ASRLanguage.RUSSIAN_RU
});
myasr.addEventListener(ASREvents.CaptureStarted, function (e) {
clearTimeout(ts);
mycall.sendMessage(JSON.stringify({
type: "CAPTURE_STARTED"
}));
});
myasr.addEventListener(ASREvents.Result, function (e) {
ts = setTimeout(recognitionEnded, 5000);
mycall.sendMessage(JSON.stringify({
type: "RESULT",
text: e.text,
confidence: e.confidence
}));
});
myasr.addEventListener(ASREvents.SpeechCaptured, function (e) {
mycall.sendMessage(JSON.stringify({
type: "SPEECH_CAPTURED"
}));
});
setTimeout(function () {
player = VoxEngine.createTTSPlayer("Слушаю вас", Language.RU_RUSSIAN_FEMALE);
player.addMarker(-1000);
player.addEventListener(PlayerEvents.PlaybackMarkerReached, function (e) {
mycall.sendMediaTo(myasr);
});
player.sendMediaTo(mycall);
}, 200);
}
function recognitionEnded() {
myasr.stop();
VoxEngine.terminate();
}
function handleMicStatus(e) {
if (e.active) {
vad = true;
clearTimeout(ts2);
mycall.sendMessage(JSON.stringify({
type: "VAD",
status: true
}));
} else {
ts2 = setTimeout(function () {
if (!vad) {
myasr.stop();
VoxEngine.terminate();
}
}, 6000);
vad = false;
mycall.sendMessage(JSON.stringify({
type: "VAD",
status: false
}));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment