<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Avicus Delacroix</title>
    <description>The latest articles on DEV Community by Avicus Delacroix (@followmyutopia).</description>
    <link>https://dev.to/followmyutopia</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F590814%2Ff116bfab-d796-44ff-bcf9-b39a7e2b6406.jpeg</url>
      <title>DEV Community: Avicus Delacroix</title>
      <link>https://dev.to/followmyutopia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/followmyutopia"/>
    <language>en</language>
    <item>
      <title>Let's talk with chatGPT with your voice</title>
      <dc:creator>Avicus Delacroix</dc:creator>
      <pubDate>Fri, 28 Apr 2023 06:31:22 +0000</pubDate>
      <link>https://dev.to/followmyutopia/lets-talk-with-chatgpt-with-your-voice-4ho1</link>
      <guid>https://dev.to/followmyutopia/lets-talk-with-chatgpt-with-your-voice-4ho1</guid>
      <description>&lt;p&gt;Hello! This is Avi from &lt;a href="https://voximplant.com/"&gt;Voximplant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/followmyutopia/how-we-created-an-automl-solution-in-voximplant-2paf"&gt;Last time&lt;/a&gt; I was talking about AutoML solutions and about how we created a virtual assistant called &lt;strong&gt;Avatar&lt;/strong&gt; at Voximplant.&lt;/p&gt;

&lt;p&gt;Since then, I received several messages about artificial intelligence in general and about virtual assistants. I noticed that lately, people became obsessed with &lt;strong&gt;chatGPT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I don't think I need to explain what ChatGPT is. But for those who haven't heard of it: it's a conversational robot based on machine learning like Voximplant Avatar, but it is a different kind of a robot. Avatar is a goal-oriented robot which is made for companies to assist their customers. ChatGPT is a chit-chat robot that learns from users and provides a realistic conversation.&lt;/p&gt;

&lt;p&gt;At Voximplant, we provide not only our virtual assistant, but a lot of communication services, such as calls, conferences, contact centers, interactive menus for hotlines, etc. And, of course, with all that, we have speech synthesis and recognition. So, I decided to &lt;strong&gt;integrate chatGPT into Voximplant&lt;/strong&gt;, give it a voice and teach it to recognize human speech.&lt;/p&gt;

&lt;p&gt;So, I'm going to show you how to build an application that allows talking with chatGPT with your voice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the application
&lt;/h2&gt;

&lt;p&gt;First, you need to register an account and obtain an API key for chatGPT. This can be easily done at &lt;a href="http://platform.openai.com/"&gt;http://platform.openai.com/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After you get your API key, you need to &lt;strong&gt;create an application&lt;/strong&gt; at Voximplant. This is also an easy task. Read the guide on how to create an app in &lt;a href="https://voximplant.com/docs/gettingstarted/basicconcepts/applications"&gt;the Voximplant documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the Voximplant application, you need to create a scenario where all the code will be present; buy a real or a testing phone number and bind it to your application if you want to call chatGPT from your phone and talk with it; and, of course, you will need a routing rule to launch the scenario (leave all the routing rule settings as default).&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the scenario
&lt;/h2&gt;

&lt;p&gt;In the scenario, we need to connect to chatGPT via an API request, use speech synthesis to pronounce what chatGPT says, and use the speech recognition module to convert your words to text and send them back as an utterance.&lt;/p&gt;

&lt;p&gt;Let’s start with requires and the API request.&lt;/p&gt;

&lt;p&gt;All we need to require is the Voximplant's ASR module. Then, we prepare the API url and the API key received in the very first step. For OpenAI, we will also need an array of messages.&lt;/p&gt;

&lt;p&gt;I will make the API request to chatGPT each time the ASR module recognizes the utterance. Let's see what it will look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Modules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ASR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openaiURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.openai.com/v1/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openaiApiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_api_key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;requestCompletion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpRequestAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;openaiURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type: application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization: Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;openaiApiKey&lt;/span&gt;
       &lt;span class="p"&gt;],&lt;/span&gt;
       &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;messages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;
           &lt;span class="c1"&gt;// you can configure the length of the answer&lt;/span&gt;
           &lt;span class="c1"&gt;// by sending the max_tokens parameter, e.g.:&lt;/span&gt;
           &lt;span class="c1"&gt;// "max_tokens": 150&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I commented the &lt;code&gt;"max_tokens"&lt;/code&gt; parameter, which is sent to chatGPT. By default, chatGPT responds with very long messages, which are okay for IM, but can be quite annoying in oral communication. With this parameter, you can adjust the length of incoming messages (utterances) from chatGPT.&lt;/p&gt;

&lt;p&gt;After that, we need to process the inbound call in the scenario. Let's create a couple of necessary variables and integrate our logic into the &lt;code&gt;CallAlerting&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;We need to &lt;strong&gt;create an automatic speech recognition instance&lt;/strong&gt; to process its events. At this step, you can choose the ASR provider. Voximplant provides &lt;a href="https://voximplant.com/docs/references/voxengine/asrprofilelist"&gt;a huge list of them from multiple vendors&lt;/a&gt; for multiple languages. You are free to choose any.&lt;/p&gt;

&lt;p&gt;Also, &lt;strong&gt;you need to choose a voice&lt;/strong&gt; for your robot. The same as for ASR vendors, we have &lt;a href="https://voximplant.com/docs/references/voxengine/voicelist"&gt;a huge list of voices&lt;/a&gt;, and at this part, you may try a lot of voices to find your favorite.&lt;/p&gt;

&lt;p&gt;After that, we need to process the ASR result each time you stop talking to chatGPT. Let's push your utterance to the &lt;code&gt;messages&lt;/code&gt; array and then call the &lt;code&gt;requestCompletion()&lt;/code&gt; function that we created in the previous step to send a request to OpenAI.&lt;/p&gt;

&lt;p&gt;If the API request is successful, we pronounce the chatGPT utterance via the media player and push the robot's utterance to the &lt;code&gt;messages&lt;/code&gt; array. If the request is unsuccessful, we just ask the user to repeat it.&lt;/p&gt;

&lt;p&gt;Let's see how it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoiceList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;en_US_Neural2_C&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CallAlerting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;
   &lt;span class="nx"&gt;asr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createASR&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ASRProfileList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;en_US&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;singleUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ASREvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;requestCompletion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;jsData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="na"&gt;progressivePlayback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
               &lt;span class="p"&gt;})&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; : &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry, something went wrong, can you repeat please?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="na"&gt;progressivePlayback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
               &lt;span class="p"&gt;})&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can notice, I added the &lt;code&gt;Logger.write()&lt;/code&gt; function to add the error message from chatGPT to the application logs for later analysis. You can add more logging to understand, for example, how long the API request completion takes.&lt;/p&gt;

&lt;p&gt;Let’s extend the &lt;code&gt;ASREvents.Result&lt;/code&gt; event processing with logging.&lt;/p&gt;

&lt;p&gt;After that, we process the call's &lt;code&gt;Connected&lt;/code&gt; and &lt;code&gt;Disconnected&lt;/code&gt; events. When the call is established, let's pronounce a greeting and send the call's data to the voice recognition module. And when the call is disconnected, let's terminate the scenario.&lt;/p&gt;

&lt;p&gt;After these preparations are done, we can answer the inbound call. The complete event handler will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CallAlerting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;
   &lt;span class="nx"&gt;asr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createASR&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ASRProfileList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;en_US&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;singleUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ASREvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sending data to the OpenAI endpoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ts1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;requestCompletion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
       &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ts2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Request complete in &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ts2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ts1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; ms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;jsData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="na"&gt;progressivePlayback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
               &lt;span class="p"&gt;})&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; : &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry, something went wrong, can you repeat please?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="na"&gt;progressivePlayback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
               &lt;span class="p"&gt;})&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hi, ChatGPT bot is at your service, how may I help you?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultVoice&lt;/span&gt;
           &lt;span class="p"&gt;})&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMarker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;           
           &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackMarkerReached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Disconnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's test our application. Call the phone number you have bound to your application, wait for the greeting, and start talking with your robot. Or use the debug softphone in the control panel to call the scenario.&lt;/p&gt;

&lt;p&gt;You can &lt;strong&gt;find the complete scenario&lt;/strong&gt; with the comments in the corresponding article &lt;a href="https://voximplant.com/docs/guides/integrations/chatgpt"&gt;in the Voximplant documentation&lt;/a&gt;. Feel free to modify the scenario at your wish, process more events, change voices and utterances' length, and much more. It has been tested and is ready to use.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article. Until the next time!&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>ai</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How we created an AutoML solution in Voximplant</title>
      <dc:creator>Avicus Delacroix</dc:creator>
      <pubDate>Tue, 21 Feb 2023 11:53:30 +0000</pubDate>
      <link>https://dev.to/followmyutopia/how-we-created-an-automl-solution-in-voximplant-2paf</link>
      <guid>https://dev.to/followmyutopia/how-we-created-an-automl-solution-in-voximplant-2paf</guid>
      <description>&lt;p&gt;Hello everyone, this is Avi from &lt;a href="https://voximplant.com/" rel="noopener noreferrer"&gt;Voximplant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I’m going to discuss the &lt;strong&gt;history of machine learning&lt;/strong&gt; and natural language processing, tell you about &lt;strong&gt;what AutoML is&lt;/strong&gt;, and explain how &lt;strong&gt;Voximplant&lt;/strong&gt; made this technology available for everyone with its AutoML component.&lt;/p&gt;

&lt;h2&gt;
  
  
  A brief history of NLP technology
&lt;/h2&gt;

&lt;p&gt;Let’s start with a short historical overview of natural language processing: how it evolved and why we at &lt;a href="https://voximplant.com/" rel="noopener noreferrer"&gt;Voximplant&lt;/a&gt; decided that now is the best time to enter the competitive market with our AutoML technology.&lt;/p&gt;

&lt;p&gt;The NLP history can be divided into three phases. We’re going to take an in-depth look at each of these stages below:&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage one
&lt;/h3&gt;

&lt;p&gt;The first phase is applying classic machine learning methods to natural language processing. This approach implied the vectorization method, meaning that we needed to transform text to a representation that ML models could accept as input. &lt;/p&gt;

&lt;p&gt;However, the main disadvantage of such an approach was that the words “good” and “perfect” were as far apart as the words “good” and “tree.” Thus, if you were to paraphrase a sentence with synonyms, you would get a completely different ML vector. In addition, the vectors themselves turned out to be huge, and it was almost impossible to provide them as input to a neural network architecture. However, this was merely the first stage of NLP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage two
&lt;/h3&gt;

&lt;p&gt;The second phase in the development of NLP is word embeddings. This is a technique that allowed each word to have a compact vector representation, and similar words had similar vectors. Each word is represented by a real-valued vector with either tens or hundreds of dimensions. &lt;/p&gt;

&lt;p&gt;Such representations made it easier to process by neural engines, and NLP solutions became noticeably smarter. The algorithms started to understand the basic language structures and semantics based on huge unlabeled inputs, and later we could train the results for a specific task. &lt;/p&gt;

&lt;p&gt;The processing became much faster because the basic language knowledge was already hardwired into the model, and the data for each task decreased significantly. For the NLP industry, this created a new kind of job: research centers trained fundamental models on huge arrays of data, and other companies used them as templates to train for more specific tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage three
&lt;/h3&gt;

&lt;p&gt;The third phase is connected to the creation of the transformer architecture. This architecture didn’t have recurrent network problems and had a much higher level of parallelism, which meant that a much higher level of data could be processed simultaneously, making the whole model much bigger. &lt;/p&gt;

&lt;p&gt;In 2018, Google released &lt;a href="https://arxiv.org/abs/1810.04805" rel="noopener noreferrer"&gt;BERT&lt;/a&gt;, a transformer that de facto became the template for solving complex NLP tasks. With some modifications, this model becomes dominant in NLP. Moreover, nowadays, the standard process of solving an NLP problem is to take a pre-trained &lt;strong&gt;BERT&lt;/strong&gt; and educate it for more specific tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AutoML?
&lt;/h2&gt;

&lt;p&gt;Despite the decent number of ML solutions by large companies such as &lt;strong&gt;Nvidia&lt;/strong&gt;, &lt;strong&gt;Amazon&lt;/strong&gt;, and &lt;strong&gt;Google&lt;/strong&gt;, many retail companies still can’t use them. Why is that? Even if we don’t consider the problems of working with data, one needs a team of highly qualified specialists to support these solutions — this can be quite expensive.&lt;/p&gt;

&lt;p&gt;For many companies that don’t have strong technical expertise teams, it’s difficult to discern whether the efforts are worth it and whether having an ML team will pay off in the long run. Additionally, pilot projects are quite expensive and take time to deploy. For all these reasons, many companies feel discouraged from using this technology.&lt;/p&gt;

&lt;p&gt;This is where AutoML comes to the rescue. AutoML is an attempt to automate the work of an ML team. In the ideal state, it allows people without machine learning education to create ML-based solutions and put them into production. A company uploads its data into the system, and at the output, it receives a ready-to-use scalable service integrated into the company’s infrastructure at some level. The company needs only to work with data and analytics, leaving all the engineering work under the hood. Sounds interesting, right?&lt;/p&gt;

&lt;p&gt;Of course, there are already quite a few players on the market, such as Google Cloud, AWS, and h2o.ai. Their solutions solve some problems in the NLP sphere, but the entry threshold for such solutions is relatively high, and they aim at software engineers instead of technical specialists. This looks like a part of a constructor but not a complete box solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Voximplant decided to create an AutoML engine
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Voximplant&lt;/strong&gt; is a cloud platform for creating different communication services, such as chats and chatbots, calls and conference services, contact centers, and IVRs. We also have telephony and a lot of vendors for voice recognition and synthesis. However, one thing that was missing from our toolkit was a state-of-the-art NLU engine.  &lt;/p&gt;

&lt;p&gt;Here's how we went about it. First, we added a 3rd-party solution into our system, but in practice, this solution did not have enough flexibility for real-world scenarios, and this solution could not use the full power of our platform. That’s why we decided to create our own solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we created an AutoML solution in Voximplant
&lt;/h2&gt;

&lt;p&gt;There are two types of conversational bots: chit-chat bots and goal-oriented ones. Chit-chat is designed only for chats, like Replica. These are only useful in answering the client with the phrase that makes the most sense. Goal-oriented bots are designed to find out what kind of action a user wants to perform and perform it. Examples of goal-oriented bots are Siri or Alexa and some smart IVRs in contact centers. Since we are releasing a B2B product, we’re more interested in goal-oriented bots.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv5xt8awad71ln5rwkv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv5xt8awad71ln5rwkv4.png" alt="Bots types" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, what components did we need to create such a robot? Let’s take a look at the typical flow. A user pronounces some phrase, and then it is processed by a voice recognition module, which converts voice into text. From this text, first of all, we want to extract user intent, which means the phrase's normalized meaning. &lt;/p&gt;

&lt;p&gt;During the creation of our bot, we came up with a list of possible intents so our bot could match the user’s phrase with one of these intents. Also, we want to extract all the available data from the user’s speech. For example, if a user wants to book a table at a restaurant, we need to extract the exact timing for the reservation. All these tasks are to convert the natural language into a machine-readable one.&lt;/p&gt;

&lt;p&gt;All the extracted information needs to be passed into the dialog state manager — a component that decides how to respond to the normalized request. There are many approaches to this task, both based on ML and scripting, but in general, we view this component as some kind of script written for each case. After that, the only thing left to do is synthesize speech to answer the user.&lt;/p&gt;

&lt;p&gt;Hence, we need the following components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Intent classifier, which learns on user input&lt;/li&gt;
&lt;li&gt;Component for extracting and normalizing user data&lt;/li&gt;
&lt;li&gt;Dialog state manager to make decisions&lt;/li&gt;
&lt;li&gt;API for managing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The intent classifier needs to have a front end that accepts user data and stores it in the back end. After that, we need to start training the user model, store the resulting artifact somewhere and send it to the inference server that processes user requests in real-time. &lt;/p&gt;

&lt;p&gt;While it doesn’t look too complicated, the system has several limitations: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service should be responsive and not have any delays during a phone call&lt;/li&gt;
&lt;li&gt;The service quality should be comparable with SoTA&lt;/li&gt;
&lt;li&gt;The service should be resilient to the influx of users&lt;/li&gt;
&lt;li&gt;The service should have a competitive price&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What was also important, we needed to launch the project with a small team of 4 people at the beginning, and we had six months to get the MVP. Also, we wanted to start receiving feedback from the market as soon as possible to understand whether our product really solves customers’ problems or not. &lt;/p&gt;

&lt;p&gt;Therefore, we decided to launch our AutoML service in several smaller iterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iteration 1
&lt;/h3&gt;

&lt;p&gt;In the first iteration, we didn’t focus on scaling problems. We wanted to make a quick prototype and receive feedback from the market. We decided to construct a base project, which we could enhance with different technologies in the future, and started with the intent classifier. By making only the intent classifier, we could cover a very large number of tasks, such as automatic comment classification, NPS surveys, and smart IVR.&lt;/p&gt;

&lt;p&gt;Next, we automated the training process for &lt;a href="https://huggingface.co/roberta-large" rel="noopener noreferrer"&gt;RoBerta Large&lt;/a&gt; for a project team that can assemble solutions because this approach gives the highest quality. Inference service prices were intentionally avoided, not to get into too much detail on the one hand and to frighten customers with poor quality on the other.&lt;/p&gt;

&lt;p&gt;We took &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt; to make a simple control panel for data management, made a backend via &lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt;, which trains the tasks, and used &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;MLflow ModelRegistly&lt;/a&gt; to store the results. We also used it for storing metrics for debugging. For the inference server, we deployed several hardware nodes with GPU and &lt;a href="https://developer.nvidia.com/nvidia-triton-inference-server" rel="noopener noreferrer"&gt;Nvidia Triton&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;Our telemetry needs were met by MLflow out of the box, as well as the UI tools for its analysis. We trained each user's model on both the cross-validation dataset as well as the full dataset for final model training. As a result, we were able to identify situations in which our hyperparameter fitting heuristics failed and adjust the formula manually to avoid problems.&lt;/p&gt;

&lt;p&gt;More than that, MLflow helped us solve the problem of delivering models to the inference server. The ModelRegistry service it provides makes it possible to track metrics and store model artifacts in a versioned way.&lt;/p&gt;

&lt;p&gt;The Nvidia Triton inference service pulled the models into memory. The only task left for us was writing a small Python solution that examined the model registry for new models and sending them to Triton.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7we1l58vd3zuoaox8mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7we1l58vd3zuoaox8mu.png" alt="First iteration flow" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, in just a few months, we got a ready-to-use product that could be deployed fast and solve customers' cases without any intervention from ML engineers.&lt;/p&gt;

&lt;p&gt;But although our solution had decent quality and low latency, it was completely non-scalable. The main problem was that each client model always required at least 2 GB of video memory, even if the client made a “hello world”. If we get a large number of new clients, our solution will not withstand the load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iteration 2
&lt;/h3&gt;

&lt;p&gt;The goal of the 2nd iteration was to make our solution scalable. To achieve it, we needed a way to share the GPU resources with our clients in an efficient way.&lt;/p&gt;

&lt;p&gt;What are possible solutions? We can conduct an autoscaling of GPU nodes, but it has drawbacks — not only is it expensive, but it also has high latency during high loads, and the hardware utilization is very low. &lt;/p&gt;

&lt;p&gt;Besides autoscaling, we can add smart rotation logic for GPU nodes, load them on demand, and unload them when not in use. When working with voice, however, you should keep in mind that Nvidia Triton loads models within seconds, not milliseconds. This will lead to a large delay and not a natural conversation. This also doesn’t solve the cost problem. Another variant is switching to the previous generation models and moving from GPU to CPU, but the quality we got did not satisfy us. So, we decided to dig deeper.&lt;/p&gt;

&lt;p&gt;The thing we want to keep in mind is that we do not allocate the GPU memory for each client exclusively. A better idea would be if some parts of the ML model were the same for everyone. This variant simplifies scaling a lot because, in this case, we scale GPU resources, not for client applications (most of them are hello worlds). &lt;/p&gt;

&lt;p&gt;One curious fact we learned from our small team's experience with ML is that the upper layers of transformers change a lot with fine-tuning, while the lower layers hardly change. This seems reasonable because the lower layers are in charge of basic language rules and semantics, and the upper layers are in charge of high-level representations and cases. &lt;/p&gt;

&lt;p&gt;In fact, you can suspend the lower layers while fine-tuning a model for a particular case without losing quality. And the embeddings and subword layer can take about half of the whole model, and if we suspend the first N layers, then up to 90% of the entire model can be left unchanged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xp7qsui4035idxls64g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xp7qsui4035idxls64g.png" alt="What changes" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This solves our problem: 95% of our model will be suspended and only used to add new features and custom models, and we will be fine-tuning the last few layers of users' data.&lt;/p&gt;

&lt;p&gt;In this case, we solve the scaling problem as follows: we have a pool of GPU machines, which we scale when the number of requests to the system increases, which is quite easy, and at the same time, we infer the user part of the system on CPUs with model rotation in RAM. We can quickly deploy a user model on the CPU in less than half a second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmnnjujluqljiswlmf88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmnnjujluqljiswlmf88.png" alt="The final variant" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final variant looks like this: when a user request arrives, it gets to a GPU machine with a backbone, which vectorizes it using the transformer, and then from the 22nd layer of RoBerta, the embeddings array transfers to a CPU machine, where the user’s model is either already cached in RAM, or if not, it is lifted from the local disk cache in another 50-100 milliseconds. Hence we are dealing with a stateless system. We don’t need to think about which pods have which user models — we can send a request to any pod, and it will work correctly. Even though sending the request to the pod when the model is already cached in RAM is better, this problem can be easily solved at the infrastructure level without changing the application logic.&lt;/p&gt;

&lt;p&gt;Thus, we solved the main problem: scaling without sacrificing quality. Thanks to this, we didn’t have to worry about peak loads on the system, and in addition, we got a very clear billing model, calculated by the price of a request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iteration 3
&lt;/h3&gt;

&lt;p&gt;The final touches we needed to feel that our system was complete were hyperparameter selection and multi-language support for our product. That’s what we turn our attention to in the 3rd iteration.&lt;/p&gt;

&lt;p&gt;Taking into account that our system is primarily designed for people who are not ML engineers and don’t have a proper education in this field, we left only one hyperparameter available: the number of training loops. This problem could be solved in two ways. The first one is to perform a two-step training. However, the main issue with this solution is that it makes the training more complicated, and second, we can’t control the dataset size. It was difficult to predict how such a system would behave in a few-shot mode, but most likely, it won’t be good. Therefore, we decided to continue researching the dependence of dataset parameters and the optimal number of training loops.&lt;/p&gt;

&lt;p&gt;Here is where the &lt;strong&gt;Massive&lt;/strong&gt; dataset by &lt;a href="https://research.facebook.com/" rel="noopener noreferrer"&gt;Meta Research&lt;/a&gt; came to aid. With this multilingual classification dataset, we were able to cut thousands of datasets of different sizes and data distribution and began to research the optimal number of training loops and dataset parameters. Specifically, the number of examples in a dataset, the number of classes, and the average and variance of the example’s distribution by class. To our surprise, we found that on different slices of this multi-dimensional distribution, we saw one two-dimensional space, and the dependence was mapped with fairly good quality. Moreover, we got almost the same inverse dependence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxnhlg7n461vekblxhlx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxnhlg7n461vekblxhlx.png" alt="Finding formula" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, we only needed to use the usual regression to get the general formula form from the obtained data(of course, not forgetting the minimum and the maximum number of epochs to get rid of any artifacts).&lt;/p&gt;

&lt;p&gt;And the last problem for us to solve was related to multi-language support. Due to &lt;strong&gt;Voximplant&lt;/strong&gt;’s working geography, we needed support in Russian, English, Spanish, and Portuguese. We wanted to know if it would be a nice idea to use a multilingual model as a backbone for all languages or if each language needs its own model. Luckily for us, the guys at Meta had already researched this problem and proved the excellent work of the multilingual &lt;a href="https://huggingface.co/xlm-roberta-large" rel="noopener noreferrer"&gt;XLM-Roberta&lt;/a&gt;. So we left a separate Russian backbone because it was already noticeably better than the XLM-Roberta’s. After all, we already had a huge amount of raw data; for other languages, we took XLM-Roberta as a backbone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;p&gt;In the end, after circa nine months of hard work, we made a full-fledged tool for creating flexible communication scenarios based on SoTA NLU and serverless JavaScript, deeply integrated with &lt;strong&gt;Voximplant&lt;/strong&gt; features such as chats and telephony.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Voximplant Avatar: An AI chat and voice robot for you</title>
      <dc:creator>Avicus Delacroix</dc:creator>
      <pubDate>Mon, 28 Mar 2022 16:49:21 +0000</pubDate>
      <link>https://dev.to/followmyutopia/voximplant-avatar-an-ai-chat-and-voice-robot-for-you-5ci6</link>
      <guid>https://dev.to/followmyutopia/voximplant-avatar-an-ai-chat-and-voice-robot-for-you-5ci6</guid>
      <description>&lt;p&gt;We encounter voice or chat robots every day. Some of them call to notify us about goods shipments, some of them irritate us with ads. Many such robots greet us on websites asking if we need any help.&lt;/p&gt;

&lt;p&gt;The most significant disadvantage of such robots is that they can say or perceive only previously scripted information. This is the main reason why such robots irritate us, because it's impossible to have an open dialogue with them. So we usually prefer to speak to a human instead.&lt;/p&gt;

&lt;p&gt;Here is where &lt;strong&gt;Artificial Intelligence&lt;/strong&gt; (AI) comes in handy. AI took great steps forward over the last few years and is still evolving. There are plenty of AI companions which can freely talk like real human beings. Such companions learn during communication, understand many phrases, and even try to answer the same question differently.&lt;/p&gt;

&lt;p&gt;So, what if we combine such an AI companion and a voice/text robot? Doing this, we can create an assistant which can maintain a smooth conversation with customers. Teach this assistant everything that it may need, add a realistic speech synthesis engine — that’s what you get with &lt;a href="https://voximplant.com/"&gt;Voximplant Avatar&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How avatar works
&lt;/h2&gt;

&lt;p&gt;Avatar is a Voximplant service that uses AI and NLP (native language processing) for voice and text communication with customers. You can teach your avatar all necessary information, such as your cafe's working hours and delivery options, so it can answer customers' questions. You can also integrate it with your CRM so your avatar can help your customers book tables.&lt;/p&gt;

&lt;p&gt;Additionally, you can supply your avatar with realistic speech synthesis and recognition engines, making it a realistic interlocutor. Modern speech engines sound great and AI and NLP make conversations more natural. Add telephony or chat features, and you receive a perfect assistant for your hotline, contact center, or website.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create an avatar
&lt;/h2&gt;

&lt;p&gt;Let's create an avatar that can perform everything explained above. For this, you will need &lt;a href="https://manage.voximplant.com/"&gt;a Voximplant account&lt;/a&gt;. Log in to the control panel, find the &lt;a href="https://manage.voximplant.com/avatars"&gt;Avatars&lt;/a&gt; section, and click &lt;strong&gt;Create&lt;/strong&gt;. Give your avatar a name, choose a language and time zone, and create it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uYi8M3el--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbjjfnvgorwkjjdmr5zn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uYi8M3el--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbjjfnvgorwkjjdmr5zn.png" alt="Create an avatar" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this step, you already have a smart avatar that can analyze human speech and understand the speaker's intentions. Now we can teach our avatar all the information it may need.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to teach an avatar
&lt;/h2&gt;

&lt;p&gt;To teach your avatar, open it, go to the &lt;strong&gt;Intents&lt;/strong&gt; section and click &lt;strong&gt;Add&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N-2WAeIz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lypfxmrdaka8usuyqbpi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N-2WAeIz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lypfxmrdaka8usuyqbpi.png" alt="Add an intent" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To understand what a customer wants, an avatar needs to find intents in a customer's speech. But a customer can ask the same question differently, thus why your avatar needs training.&lt;/p&gt;

&lt;p&gt;Open the intent you created and go to the &lt;strong&gt;Training phrases&lt;/strong&gt; section. We need to write several phrases on how a customer can ask the question.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are your opening hours?&lt;/li&gt;
&lt;li&gt;Do you work tomorrow?&lt;/li&gt;
&lt;li&gt;How late are you open until tonight?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then go to the &lt;strong&gt;Answers&lt;/strong&gt; section and write some variants of your answers.&lt;/p&gt;

&lt;p&gt;When you save the intent, you will see a yellow &lt;strong&gt;Training required&lt;/strong&gt; button at the top of the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Imw9mpx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ra6acdv7186kw70zba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Imw9mpx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ra6acdv7186kw70zba.png" alt="Training" width="800" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Train&lt;/strong&gt; and wait, this will take a moment. AI will analyze all possible variants of this question and will be ready to answer in a real case.&lt;/p&gt;

&lt;p&gt;You can add as many intents as you want. Let's teach our avatar intents surrounding delivery options and booking a table.&lt;/p&gt;

&lt;p&gt;Next write a JavaScript &lt;strong&gt;scenario&lt;/strong&gt; on the &lt;strong&gt;Dialogue scenario&lt;/strong&gt; tab. I created a simple scenario where the avatar greets a customer and searches for intents to learn about working hours and delivery options in the customer's speech and answers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;addState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// greet a customer when it connects to the dialogue&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pineapple garden, how can I help you?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// search for intents in a customer's speech&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openHours&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delivery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// answer a customer's intent and keep listening&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if an intent is not clear, ask to rephrase&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry, I didn&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t catch that. I can help you with open hours, deliveries, and reservations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// set the entry point&lt;/span&gt;
&lt;span class="nx"&gt;setStartState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more information on how to write avatar scenarios in the &lt;a href="https://voximplant.com/docs/guides/ai/avatar"&gt;Voximplant documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's test our avatar. Click the &lt;strong&gt;Debug&lt;/strong&gt; button at the top right corner to run the scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iuSiieWA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owjo3i8s4chzxqqvhcla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iuSiieWA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owjo3i8s4chzxqqvhcla.png" alt="Debug" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ask your avatar any questions to see if it processes incoming intents. The avatar should recognize your intent and answer your question correctly. Let's try!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M7ZgmvAb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/870ii7bky3f11tl8872l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M7ZgmvAb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/870ii7bky3f11tl8872l.png" alt="Avatar answers" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voila! Your avatar recognizes intents perfectly and gives correct answers. Now it's time to teach the avatar to do something more serious than just answering the questions, like booking tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  How avatar can book tables
&lt;/h2&gt;

&lt;p&gt;First, teach your avatar a booking intent the same way we did previously. Upon recognizing this intent, the avatar needs to collect all the necessary information for booking, primarily time, date, and the number of people.&lt;/p&gt;

&lt;p&gt;A customer might provide necessary information during their intention to book a table; for example, they could say, "I need to book a table for two", so we already know the number of people. That is why we need to collect the information during intent recognition.&lt;/p&gt;

&lt;p&gt;Let's create a booking object in the scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reservationForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;uncertainUtterancesCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to collect all the necessary information to fill out the form. Check what is missing and ask the customer questions. If the customer could not provide a certain answer, increase the &lt;code&gt;uncertainUtterancesCount&lt;/code&gt; counter, to avoid looping.&lt;/p&gt;

&lt;p&gt;When all the information is collected, we need to summarize it to the customer and ask for confirmation. If the customer confirms, we record the booking object and now can send it to your CRM or backend via an API request.&lt;/p&gt;

&lt;p&gt;I also added several exit points to the scenario to avoid looping. For example, if the avatar did not understand the client three times, or the customer states that the avatar cannot help them, or says goodbye, the scenario will end. Take a look at my final scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reservationForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;uncertainUtterancesCountweirdUtterancesInRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;addState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// if this is the first time in this state, greet the client. if it is not, ask what we can help with&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visitsCounter&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pineapple garden, how can I help you?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Can I help you with somehting else?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// search for intents&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openHours&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delivery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// answer the intent and go to the 'start' state&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// the client may already give you some information&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemTime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemNumber&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sure!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if the client says "no thanks", say goodbye and end the conversation&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ok! Hope I&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;ve helped. See you!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if the client says that there's a question, ask and listen&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sure, so what&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;s your question?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if the client's intent is not clear, ask for missing information, but not more than 3 times&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utteranceCounter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry, I didn&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t catch that. I can help you with open hours, deliveries, and reservations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;m so sorry, but I couldn&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t understand you. Bye!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;addState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if the client cannot answer avatar's questions, or if your avatar does not understand the client, stop asking anything&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCountweirdUtterancesInRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry I couldn&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t understand you&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if the information is given, confirm it&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservationConfirm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if something is wrong, ask about it&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;For how many people and which date would you like a reservation?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;And for how many people do you need a table?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;And for which date?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// check if you have all the necessary information&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemTime&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemTime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;systemNumber&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCountweirdUtterancesInRow&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openHours&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delivery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// if during filling the form any other intent is found, answer it and continue filling the form&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// continue filling the form&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;addState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reservationConfirm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// convert to human-readable date&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;months&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;January&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;February&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;March&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;April&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;May&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;June&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;July&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;August&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;September&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;October&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;November&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;December&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;monthStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;months&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;minute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`So you want to book a table for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; people at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;monthStr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onUtterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Awesome! We will be waiting for you&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slotPeopleCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uncertainUtterancesCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I see, sorry.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utteranceCounter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;m sorry, so do you want to make a reservation?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sorry, I can&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t help you. Hopefully I will be able to assist you next time. Bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;nextState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;addState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;final&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;isFinal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;needRedirectionToOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;reservationForm&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// set the entry point&lt;/span&gt;
&lt;span class="nx"&gt;setStartState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have an avatar that can tell customers about hours of operation, delivery options, and also book a table and integrate with your CRM or backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to integrate telephony and chat
&lt;/h2&gt;

&lt;p&gt;The last thing your avatar needs is telephony or chat service to be able to communicate with your customer. To integrate it with telephony, go to the &lt;strong&gt;Integration&lt;/strong&gt; tab of your avatar and copy the integration script. Then create &lt;a href="https://manage.voximplant.com/applications"&gt;an application on the Voximplant platform&lt;/a&gt; and paste the integration code into the &lt;a href="https://voximplant.com/docs/gettingstarted/basicconcepts/scenarios"&gt;application scenario&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Set up the &lt;a href="https://voximplant.com/docs/references/voxengine/voxengine/ttsoptions"&gt;speech synthesis&lt;/a&gt; and &lt;a href="https://voximplant.com/docs/references/voxengine/asrparameters"&gt;recognition&lt;/a&gt; modules by choosing the language and a suitable voice, rent or connect &lt;a href="https://voximplant.com/docs/gettingstarted/basicconcepts/phonenumbers"&gt;a phone number&lt;/a&gt;, set up &lt;a href="https://voximplant.com/docs/gettingstarted/basicconcepts/routing"&gt;a routing rule&lt;/a&gt;, and your avatar is ready to answer your customers' calls!&lt;/p&gt;

&lt;p&gt;You can also connect your avatar to &lt;a href="https://voximplant.com/docs/references/avatarapi"&gt;a text chat&lt;/a&gt;, for example, on your website. Avatars work perfectly with both voice and text channels. You can test how an avatar communicates in a chat via &lt;a href="https://github.com/voximplant/avatars-grpc-nodejs-example"&gt;this simple demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;We created a simple avatar that can communicate with customers, answer their questions, and book tables via API requests. This is a simple case, but you can extend the logic and make your avatar an indispensable assistant for your hotline or contact center.&lt;/p&gt;

&lt;p&gt;Voximplant's speech synthesis and recognition modules allow you to choose a very realistic voice or even integrate 3rd party voices, so your customers won't be able to tell if it is a real person or a robot. And constantly evolving AI and NLP will make your avatar better every day!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://manage.voximplant.com/auth"&gt;Register at the Voximplant platform&lt;/a&gt; and create your own avatar today! Everyone who tests in and leaves a review will get a guaranteed prize.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nlp</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How KFC employs thousands of candidates with good conversion</title>
      <dc:creator>Avicus Delacroix</dc:creator>
      <pubDate>Mon, 31 May 2021 13:27:43 +0000</pubDate>
      <link>https://dev.to/followmyutopia/how-kfc-employs-thousands-of-candidates-with-good-conversion-3on</link>
      <guid>https://dev.to/followmyutopia/how-kfc-employs-thousands-of-candidates-with-good-conversion-3on</guid>
      <description>&lt;p&gt;Hi, this is Avi from Voximplant. Last time I showed you an example of &lt;a href="https://dev.to/followmyutopia/diy-clubhouse-for-ios-android-and-even-unity-1na1"&gt;How to create a DIY cross-platform Clubhouse&lt;/a&gt;, and today I have something more interesting to show to you — a real case of the employment system in KFC restaurants.&lt;/p&gt;

&lt;p&gt;In Russia alone, KFC opens more than 100 restaurants every year (imagine worldwide numbers), and all these restaurants need staff. Working in fast-food restaurants is popular among young people; many seek this kind of work temporarily. And all of them send their CVs to KFC.&lt;/p&gt;

&lt;p&gt;Because of this KFC gets more than 15,000 applications every month and needs to process them. &lt;em&gt;But imagine how many HR employees they would need to call all the applicants?&lt;/em&gt; Factor in that most applicants are underage or that they don’t need the job anymore and  it looks like a waste of time and money spent on HR.&lt;/p&gt;

&lt;p&gt;This is why KFC asked &lt;a href="https://voximplant.com/?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;&lt;strong&gt;Voximplant&lt;/strong&gt;&lt;/a&gt; for help. And the solution was obvious: we created a robot that called all the applicants and asked them a simple question, "Do you want to work for KFC?". If they say yes, the robot asks for some additional information, about their age/documents/desired work hours and more, and passes the information to an HR manager who is ready to employ them.&lt;/p&gt;

&lt;p&gt;The results were astounding. The robot processes the applications 10 times faster than a human, filters 37% of candidates as irrelevant, and HR managers increase their conversion by 11%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today I want to talk to you about how to create such a robot for your own purposes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Actually, it's not as hard as it may seem. Let's create a simple robot like the one KFC uses, right now.&lt;/p&gt;

&lt;p&gt;The task will be simple: call all the candidates from a call list, greet them, ask them if they want to work for us, recognize their answer, and connect to a call-center specialist depending on their answer.&lt;/p&gt;

&lt;p&gt;Let's &lt;a href="https://manage.voximplant.com/auth?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;log into the Voximplant platform&lt;/a&gt;, &lt;a href="https://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/applications?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;create an application&lt;/a&gt;, and &lt;a href="https://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/programmable_voice_and_video/scenarios?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;start with a scenario&lt;/a&gt;. First, we need to &lt;a href="https://voximplant.com/docs/references/voxengine/asrhttps://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/programmable_voice_and_video/scenarios?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;import speech recognition&lt;/a&gt; and &lt;a href="https://voximplant.com/docs/references/voxengine/player?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;speech synthesis modules&lt;/a&gt;, declare necessary constants and start writing our logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Modules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ASR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Modules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;callerid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7xxxxxxxxxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7xxxxxxxxxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callOperator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can pass all the necessary input to the scenario in the &lt;a href="https://voximplant.com/docs/references/voxengine/voxengine/customdata?utm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;VoxEngine.customData&lt;/a&gt; field. For our example, let's use the following JSON format: { "phone" : "7xxxxxxxxxx", "name": "John" }.&lt;/p&gt;

&lt;p&gt;At scenario start, we parse the JSON from &lt;a href=""&gt;customData&lt;/a&gt; and &lt;a href="https://voximplant.com/docs/references/voxengine/voxengine/callpstnutm_source=devto&amp;amp;utm_medium=techarticle&amp;amp;utm_campaign=vox_kfc"&gt;initiate a call&lt;/a&gt; from &lt;code&gt;callerid&lt;/code&gt; to &lt;code&gt;data.phone&lt;/code&gt; and connect the event handlers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Start a call from callerid to data.phone&lt;/span&gt;
 &lt;span class="nx"&gt;callCandidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callPSTN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callerid&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Add event listeners&lt;/span&gt;
 &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_connected_handler&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Disconnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_disconnected_handler&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_failed_handler&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our candidate answers the call, we create a Player to synthesize speech, set some text (use your imagination), and play it to our candidate. We can integrate 3rd-party voices, so let's use one from Yandex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_connected_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// Create a text-to-speech player&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Здравствуйте &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Хотите работать?`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoiceList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Yandex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Neural&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ru_RU_alena&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTTSPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Start playback and connect an event listener after&lt;/span&gt;
 &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;callCandidate&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;PlayerEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlaybackFinished&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;playbackFinishedHandler&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the playback finishes, we need to process the candidate's answer. For our example, let's integrate a voice recognition profile from Tinkoff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;playbackFinishedHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// Create an ASR for speech recognition&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;asrProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ASRProfileList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tinkoff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ru_RU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nx"&gt;asr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createASR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asrProfile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Wait for the human’s response and add an event listener&lt;/span&gt;
 &lt;span class="c1"&gt;// which will trigger after speech recognition&lt;/span&gt;
 &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;asr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;ASREvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asrResultHandler&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the candidate's answer is recorded and transcribed to text. We can process the result as we need. As a simple way, if the candidate's answer has the keyword "no" in it, let's just record it to our data object and hang up (you may want another logic).&lt;/p&gt;

&lt;p&gt;If the candidate's answer has the word "yes", let's also record this to our data object's field and connect it to an operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;asrResultHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// Disable event listener&lt;/span&gt;
 &lt;span class="nx"&gt;asr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;ASREvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// The answer is written into text field&lt;/span&gt;
 &lt;span class="c1"&gt;// we can proceed the result as we want&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

   &lt;span class="c1"&gt;// Update the data object&lt;/span&gt;
   &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wantsToWork&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Hang up ( Triggers the callCandidate_disconnected_handler )&lt;/span&gt;
   &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hangup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wantsToWork&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Call the operator function&lt;/span&gt;
   &lt;span class="nx"&gt;startOperatorCall&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hangup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;startOperatorCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;callOperator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callPSTN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callerid&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Unite two calls into one&lt;/span&gt;
 &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMediaBetween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callOperator&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Connect event handler&lt;/span&gt;
 &lt;span class="nx"&gt;callOperator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Подключились к оператору&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="nx"&gt;callOperator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Disconnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hangup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="nx"&gt;callOperator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;callCandidate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hangup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that we need to process now is the session's termination. For example, if the call attempt was successful, we send the result object (with candidates' answers) via an HTTP request, and terminate our session. If the call attempt was not successful, just terminate the session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The call was successful&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_disconnected_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://servicename&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="c1"&gt;// Send the data object via a POST http request to specific url&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpRequestAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Terminate session&lt;/span&gt;
 &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// The call was not successful&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;callCandidate_failed_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila. Now we have a primitive robot who accepts a call list, calls every candidate, and asks them if they want to work for us. Then it writes their answer in text form to the database and connects to an HR manager if the candidate wants to work.&lt;/p&gt;

&lt;p&gt;This was a simple example. Next you can extend your robot's logic, create complex dialogs and algorithms, connect your candidates to different departments depending on their answer, or collect any additional information you want. It has no limits, only your imagination!&lt;/p&gt;

&lt;p&gt;I hope this explanation was useful, and I hope you all find a great team and develop a productive business!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>robots</category>
      <category>recruiting</category>
    </item>
    <item>
      <title>DIY Clubhouse: for iOS, Android, and even Unity</title>
      <dc:creator>Avicus Delacroix</dc:creator>
      <pubDate>Tue, 09 Mar 2021 10:00:03 +0000</pubDate>
      <link>https://dev.to/followmyutopia/diy-clubhouse-for-ios-android-and-even-unity-1na1</link>
      <guid>https://dev.to/followmyutopia/diy-clubhouse-for-ios-android-and-even-unity-1na1</guid>
      <description>&lt;p&gt;The pandemic changed us all. Working and studying remotely, &lt;em&gt;we craved live communications&lt;/em&gt; and seeing our friends and colleagues in person. Maybe that's why a new social network, &lt;a href="https://www.joinclubhouse.com"&gt;&lt;strong&gt;Clubhouse&lt;/strong&gt;&lt;/a&gt;, has gathered more than 6 million people in less than a year.&lt;/p&gt;

&lt;p&gt;Clubhouse is an all-new type of social networking. No texting at all, communicate only by voice. All the communication happens in so-called "rooms", which can be &lt;strong&gt;open&lt;/strong&gt; for everyone or &lt;strong&gt;private&lt;/strong&gt;. The room's owner (moderator) decides who can talk, and the listeners can "raise a hand" to indicate that they want to ask a question.&lt;/p&gt;

&lt;p&gt;However, Clubhouse has its limitations. For now, &lt;strong&gt;it's only available for iOS&lt;/strong&gt; users, and to join, you &lt;strong&gt;need to receive an invitation&lt;/strong&gt; from an existing user. But what if you are an Android user?&lt;/p&gt;

&lt;p&gt;You can wait until they release an Android or desktop version, or you can &lt;strong&gt;make your own Clubhouse&lt;/strong&gt;, with &lt;del&gt;blackjack&lt;/del&gt; better security, voice recording, AI, and support for any platform. And &lt;a href="https://voximplant.com"&gt;&lt;strong&gt;Voximplant&lt;/strong&gt;&lt;/a&gt; will help you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this article&lt;/em&gt;, you’ll see how to create a Clubhouse-like audio room with Voximplant's Web SDK, so clients can use a common browser as a client.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that Voximplant supports multiple SDKs, from Web, iOS, and Android to React Native, Flutter, and even Unity. Imagine, you can embed an audio (or video) chat into your game design&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Set up VoxEngine
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VoxEngine&lt;/strong&gt; is a cloud platform to enable serverless communications. Let's create a room. &lt;a href="https://manage.voximplant.com/auth"&gt;Log into your account&lt;/a&gt; (or &lt;a href="https://manage.voximplant.com/auth/sign_up"&gt;create one&lt;/a&gt;) and &lt;a href="https://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/applications"&gt;create a new application&lt;/a&gt;. Then &lt;a href="https://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/users"&gt;create a user&lt;/a&gt; for authorization and &lt;a href="https://voximplant.com/docs/introduction/introduction_to_voximplant/basic_concepts/programmable_voice_and_video/scenarios"&gt;a new scenario&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First &lt;a href="https://voximplant.com/docs/references/voxengine/conference"&gt;import the conference module&lt;/a&gt;. Then implement user disconnecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Modules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Conference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onEndpointDisconnected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;members&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
       &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;terminate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then implement permissions check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implement &lt;a href="https://voximplant.com/docs/references/voxengine/voxengine/createconference"&gt;room creation&lt;/a&gt; and &lt;a href="https://voximplant.com/docs/references/voxengine/conference#add"&gt;adding a new user&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;logURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// for debug reason&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;conference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;logURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logURL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nx"&gt;conference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createConference&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;hd_audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;VoxEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CallAlerting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;checkPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CallEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Disconnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onEndpointDisconnected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
           &lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
           &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FORWARD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BOTH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scheme&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
           &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
           &lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;getCall&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getCall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hangup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Reason&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DENIED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part is done. Now let's create a client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the client
&lt;/h2&gt;

&lt;p&gt;As I decided to make an example with &lt;strong&gt;Web SDK&lt;/strong&gt;, my client will be an HTML-page. I'll hide the control buttons until the SDK initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
       &lt;span class="nc"&gt;.hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;The demo&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"btns"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Avi&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"viewer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Join as listener&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"speaker"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Join as speaker&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"leave"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Leave&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"audio"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Current speakers &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"countSpeakers"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"endpoints"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"*****"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An interesting part. Let's &lt;a href="https://voximplant.com/docs/references/websdk/voximplant/client#init"&gt;initialize our SDK&lt;/a&gt; in the  tag and show the control buttons if the initialization is successful.&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="o"&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;script&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;&amp;amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class="c1"&amp;gt;// sdk init&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getInstance&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;user&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;user*****&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;init&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="k"&amp;gt;async&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;await&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;init&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;({&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;showDebugInfo&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;true&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;serverIp&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;url*****&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;await&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;connect&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;await&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;login&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;user&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;@app**.acc**.voximplant.com`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;pass*****&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="nx"&amp;gt;init&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;().&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;then&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;btns&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;classList&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;remove&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;hidden&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Create some necessary constants. I will get the user name from an HTML-tag with id=”myname”. Then let&amp;amp;#39;s define when each button is displayed:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;currentRole&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;countSpeakers&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="mi"&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;confNumber&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;Test room&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;speakerBtn&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;speaker&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;viewerBtn&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;viewer&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;leaveBtn&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;leave&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
&amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;myname&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;myName&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;setRole&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;role&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentRole&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;role&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;role&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;===&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;speaker&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;speakerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;true&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;leaveBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;viewerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;role&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;===&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;viewer&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;speakerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;leaveBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;viewerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;true&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;role&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;===&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;start&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;speakerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;viewerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;leaveBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;disabled&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="kc"&amp;gt;true&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Handle &amp;lt;a href="https://voximplant.com/docs/references/websdk/voximplant/call#hangup"&amp;gt;leaving the conversation&amp;lt;/a&amp;gt;:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;endCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;&amp;amp;amp;&amp;amp;amp;&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;state&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;!==&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;ENDED&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;endpoints&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;''&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;hangup&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;setRole&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;start&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Then &amp;lt;a href="https://voximplant.com/docs/references/websdk/voximplant/endpointevents#remotemediaadded"&amp;gt;adding&amp;lt;/a&amp;gt; and &amp;lt;a href="https://voximplant.com/docs/references/websdk/voximplant/endpointevents#remotemediaremoved"&amp;gt;removing a user&amp;lt;/a&amp;gt; to/from a conversation:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;onEndpointAdded&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;Endpoint added&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;nameTable&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;endpoints&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;p&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;createElement&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;p&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;p&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;p&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="s2"&amp;gt;`Name: &amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;displayName&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;, id: &amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;nameTable&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;append&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;p&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;countSpeakers&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;countSpeakers&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;+&amp;lt;/span&amp;gt; &amp;lt;span class="mi"&amp;gt;1&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;EndpointEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;RemoteMediaAdded&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;RemoteMediaAdded&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;mediaRenderer&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;nodeCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;audio&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;mediaRenderer&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;render&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;nodeCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;})&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;EndpointEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;RemoteMediaRemoved&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`Endpoint &amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt; media removed &amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;mediaRenderer&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;})&amp;lt;/span&amp;gt;
   &amp;lt;span class="c1"&amp;gt;// ENDPOINT REMOVED&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;EndpointEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;Removed&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;ev&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`Endpoint &amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;${&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt; removed`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="kd"&amp;gt;let&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;removeP&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;endpoint&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;id&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;nameTable&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;removeChild&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;removeP&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;})&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Handle the Leave button and some necessary events:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="kd"&amp;gt;const&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;setCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;leaveBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;onclick&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;endCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;CallEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;EndpointAdded&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;onEndpointAdded&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;CallEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;MessageReceived&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;MessageReceived&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;text&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
   &amp;lt;span class="c1"&amp;gt;//handle connection&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;CallEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;Connected&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`Call connected successfully`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
   &amp;lt;span class="c1"&amp;gt;//other call event listeners&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;CallEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;Disconnected&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`Call disconnected`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;endCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;addEventListener&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;VoxImplant&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;CallEvents&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;Failed&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;e&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;console&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;warn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="s2"&amp;gt;`Call failed`&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;endCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And handle the role buttons (Speaker or Listener):&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight javascript"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nx"&amp;gt;speakerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;onclick&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="k"&amp;gt;async&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;endpoints&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;''&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;endpoints&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;''&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="k"&amp;gt;await&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;hangup&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;setTimeout&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;setRole&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;speaker&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;callConference&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;({&amp;lt;/span&amp;gt;
           &amp;lt;span class="na"&amp;gt;number&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;confNumber&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;,&amp;lt;/span&amp;gt;
           &amp;lt;span class="na"&amp;gt;extraHeaders&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;X-Name&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;myName&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
       &amp;lt;span class="p"&amp;gt;});&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;setCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;},&amp;lt;/span&amp;gt; &amp;lt;span class="mi"&amp;gt;300&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="nx"&amp;gt;viewerBtn&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;onclick&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="k"&amp;gt;async&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
   &amp;lt;span class="k"&amp;gt;if&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nb"&amp;gt;document&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;getElementById&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;endpoints&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;innerText&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="dl"&amp;gt;''&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
       &amp;lt;span class="k"&amp;gt;await&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;hangup&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
   &amp;lt;span class="nx"&amp;gt;setTimeout&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(()&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;setRole&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="s1"&amp;gt;viewer&amp;lt;/span&amp;gt;&amp;lt;span class="dl"&amp;gt;'&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;currentCall&amp;lt;/span&amp;gt; &amp;lt;span class="o"&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class="nx"&amp;gt;sdk&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;joinAsViewer&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class="nx"&amp;gt;confNumber&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;);&amp;lt;/span&amp;gt;
       &amp;lt;span class="nx"&amp;gt;setCall&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;();&amp;lt;/span&amp;gt;
   &amp;lt;span class="p"&amp;gt;},&amp;lt;/span&amp;gt; &amp;lt;span class="mi"&amp;gt;300&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="o"&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span class="sr"&amp;gt;/script&amp;lt;/span&amp;gt;&amp;lt;span class="err"&amp;gt;&amp;amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span class="sr"&amp;gt;/html&amp;lt;/span&amp;gt;&amp;lt;span class="err"&amp;gt;&amp;amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Done&amp;lt;/strong&amp;gt;. Now we have a working room with two roles (Speaker and Listener) simple button controls and a list of active speakers. All we need to do to make it a complete app is to make a decent interface and add some user/room management with databases and search.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And do not forget that the functionality of the Voximplant engine goes far beyond this: you can schedule a voice room to record if you&amp;amp;#39;re unable to join due to a scheduling conflict, you can add messages if you need, you can even create interactive voice menus with speech synthesis and recognition, which can be lots of fun.&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
      <category>ios</category>
      <category>android</category>
      <category>unity3d</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
