-1

So I am using webkitSpeechRecognition and it works great, but the problem is I want to use it in multiple places at the same time and when I add it into another section on my page it doesn't work correctly.

Here is it working on its own:

var final_transcript = '';
var recognizing = false;
var ignore_onend;
var start_timestamp;

//get languages
// https://gist.githubusercontent.com/onigetoc/d5dc63320c4d08633eb7b7daf6c1ddeb/raw/e9c3da4a40db8edf4992db9219526617da811c4c/lang.json
$.get("//raw.githubusercontent.com/the-creature/language-json/master/data.json", function(data) {
  var cList = $('#language');
  var data = $.parseJSON(data);

  $.each(data, function(i) {
    var option = $('<option/>')
      .attr('value', data[i].code)
      .html(data[i].name)
      .appendTo(cList);
  });

  var userLang = navigator.language || navigator.userLanguage;
  $("#language").val(userLang);

});

// Speech Recognition
if (!('webkitSpeechRecognition' in window)) {
  message.innerHTML = 'Web Speech API is not supported by this browser. Upgrade to <a href="//www.google.com/chrome">Chrome</a> version 25 or later.';
} else {
  var recognition = new webkitSpeechRecognition();
  recognition.continuous = true;
  recognition.interimResults = true;

  recognition.onstart = function() {
    recognizing = true;
    message.innerHTML = 'Speak now.';
    talk_button.innerHTML = 'Listen';
  };

  recognition.onresult = function(event) {
    var interim_transcript = '';
    for (var i = event.resultIndex; i < event.results.length; ++i) {
      if (event.results[i].isFinal) {
        final_transcript += event.results[i][0].transcript;
        vc_search(final_transcript);
      } else {
        interim_transcript += event.results[i][0].transcript;
      }
    }
    final_span.innerHTML = final_transcript;
    interim_span.innerHTML = interim_transcript;
  };

  recognition.onend = function() {

    recognizing = false;
    if (ignore_onend) {
      return;
    }
    speechMyText(final_transcript);
    if (!final_transcript) {
      message.innerHTML = 'Click "Talk" and begin speaking.';
      talk_button.innerHTML = 'Talk';
      return;
    }
  };

  recognition.onerror = function(event) {
    if (event.error == 'no-speech') {
      message.innerHTML = 'No speech was detected.';
      ignore_onend = true;
    }
    if (event.error == 'audio-capture') {
      message.innerHTML = 'No microphone was found. Ensure that a microphone is installed.';
      ignore_onend = true;
    }
    if (event.error == 'not-allowed') {
      if (event.timeStamp - start_timestamp < 100) {
        message.innerHTML = 'Permission to use microphone is blocked. To change, go to chrome://settings/contentExceptions#media-stream';
      } else {
        message.innerHTML = 'Permission to use microphone was denied.';
      }
      ignore_onend = true;
    }
  };

}

function talkWithApp(event) {
  if (recognizing) {
    recognition.stop();
    message.innerHTML = 'Click "Talk" and begin speaking.';
    talk_button.innerHTML = 'Talk';
    return;
  }
  final_transcript = '';
  recognition.lang = language.value;
  recognition.start();
  ignore_onend = false;
  final_span.innerHTML = '';
  interim_span.innerHTML = '';
  message.innerHTML = 'Click the "Allow" button above to enable your microphone.';
  start_timestamp = event.timeStamp;
}

// Speech Synthesis
function speechMyText(textToSpeech) {
  var u = new SpeechSynthesisUtterance();
  u.text = textToSpeech;
  u.lang = language.value;
  u.rate = 1.0;
  u.onend = function(event) {}
  speechSynthesis.speak(u);
}
.message {
    color:#999;
    padding: 1em 0;
}
.todo, .response {
    min-height:50px;
    background-color: #fff;
    margin-bottom: 0.5em;
    padding: 1px;
    color:#555;
    -webkit-box-shadow: 0 0px 3px #BDBDBD;
    box-shadow: 0 0px 3px #BDBDBD;
    transition: all 0.3s ease-in-out;
}
<div class="container">
  <div id="message" class="message">Click "Talk" and begin speaking.</div>
  <div class="todo"> <span id="final_span" class="final"></span>
    <span id="interim_span" class="interim"></span>
  </div>
  <div class="controls">
    <button id="talk_button" type="button" class="btn btn-default" onclick="talkWithApp(event)">Talk</button>
    
    <select id="language" class="select">
      <option selected="selected">Select Your Language</option>
    </select>
  </div>
</div>

And here is it running multiple times within the same page:

var final_transcript = '';
var recognizing = false;
var ignore_onend;
var start_timestamp;

//get languages
// https://gist.githubusercontent.com/onigetoc/d5dc63320c4d08633eb7b7daf6c1ddeb/raw/e9c3da4a40db8edf4992db9219526617da811c4c/lang.json
$.get("//raw.githubusercontent.com/the-creature/language-json/master/data.json", function(data) {
  var cList = $('#language');
  var data = $.parseJSON(data);

  $.each(data, function(i) {
    var option = $('<option/>')
      .attr('value', data[i].code)
      .html(data[i].name)
      .appendTo(cList);
  });

  var userLang = navigator.language || navigator.userLanguage;
  $("#language").val(userLang);

});

// Speech Recognition
if (!('webkitSpeechRecognition' in window)) {
  message.innerHTML = 'Web Speech API is not supported by this browser. Upgrade to <a href="//www.google.com/chrome">Chrome</a> version 25 or later.';
} else {
  var recognition = new webkitSpeechRecognition();
  recognition.continuous = true;
  recognition.interimResults = true;

  recognition.onstart = function() {
    recognizing = true;
    message.innerHTML = 'Speak now.';
    talk_button.innerHTML = 'Listen';
  };

  recognition.onresult = function(event) {
    var interim_transcript = '';
    for (var i = event.resultIndex; i < event.results.length; ++i) {
      if (event.results[i].isFinal) {
        final_transcript += event.results[i][0].transcript;
        vc_search(final_transcript);
      } else {
        interim_transcript += event.results[i][0].transcript;
      }
    }
    final_span.innerHTML = final_transcript;
    interim_span.innerHTML = interim_transcript;
  };

  recognition.onend = function() {

    recognizing = false;
    if (ignore_onend) {
      return;
    }
    speechMyText(final_transcript);
    if (!final_transcript) {
      message.innerHTML = 'Click "Talk" and begin speaking.';
      talk_button.innerHTML = 'Talk';
      return;
    }
  };

  recognition.onerror = function(event) {
    if (event.error == 'no-speech') {
      message.innerHTML = 'No speech was detected.';
      ignore_onend = true;
    }
    if (event.error == 'audio-capture') {
      message.innerHTML = 'No microphone was found. Ensure that a microphone is installed.';
      ignore_onend = true;
    }
    if (event.error == 'not-allowed') {
      if (event.timeStamp - start_timestamp < 100) {
        message.innerHTML = 'Permission to use microphone is blocked. To change, go to chrome://settings/contentExceptions#media-stream';
      } else {
        message.innerHTML = 'Permission to use microphone was denied.';
      }
      ignore_onend = true;
    }
  };

}

function talkWithApp(event) {
  if (recognizing) {
    recognition.stop();
    message.innerHTML = 'Click "Talk" and begin speaking.';
    talk_button.innerHTML = 'Talk';
    return;
  }
  final_transcript = '';
  recognition.lang = language.value;
  recognition.start();
  ignore_onend = false;
  final_span.innerHTML = '';
  interim_span.innerHTML = '';
  message.innerHTML = 'Click the "Allow" button above to enable your microphone.';
  start_timestamp = event.timeStamp;
}

// Speech Synthesis
function speechMyText(textToSpeech) {
  var u = new SpeechSynthesisUtterance();
  u.text = textToSpeech;
  u.lang = language.value;
  u.rate = 1.0;
  u.onend = function(event) {}
  speechSynthesis.speak(u);
}
.message {
    color:#999;
    padding: 1em 0;
}
.todo, .response {
    min-height:50px;
    background-color: #fff;
    margin-bottom: 0.5em;
    padding: 1px;
    color:#555;
    -webkit-box-shadow: 0 0px 3px #BDBDBD;
    box-shadow: 0 0px 3px #BDBDBD;
    transition: all 0.3s ease-in-out;
}
<div class="container">
  <div id="message" class="message">Click "Talk" and begin speaking.</div>
  <div class="todo"> <span id="final_span" class="final"></span>
    <span id="interim_span" class="interim"></span>
  </div>
  <div class="controls">
    <button id="talk_button" type="button" class="btn btn-default" onclick="talkWithApp(event)">Talk</button>
    
    <select id="language" class="select">
      <option selected="selected">Select Your Language</option>
    </select>
  </div>
</div>

<div class="container">
  <div id="message" class="message">Click "Talk" and begin speaking.</div>
  <div class="todo"> <span id="final_span" class="final"></span>
    <span id="interim_span" class="interim"></span>
  </div>
  <div class="controls">
    <button id="talk_button" type="button" class="btn btn-default" onclick="talkWithApp(event)">Talk</button>
    
    <select id="language" class="select">
      <option selected="selected">Select Your Language</option>
    </select>
  </div>
</div>

As you can see it doesn't work correctly on both when running multiple times. How can I make it so it only uses the section that was clicked? but still works in multiple places on a page.

Here are the two different ways:

https://jsfiddle.net/k5cm8ypg/

https://jsfiddle.net/ygpbfLso/1/

Jerdine Sabio
  • 5,688
  • 2
  • 11
  • 23
brandbei37
  • 501
  • 3
  • 13
  • 1
    You should accept the answer as the correct answer if it helped you. I noticed that in all your questions you didn't choose a correct answer. – Jerdine Sabio Mar 22 '20 at 03:26

1 Answers1

1

It seems that in your HTML your using ID multiple times; IDs should be unique to a certain page or frame.

Then in your script, both recognition object and your event can't properly get and assign values because an ID they're trying to access has been declared more than once.

What I did was;

  1. Remove all the IDs to use classes

  2. Add a global var activeButton

  3. Bind talk event to the whole document and triggers when .talk_button is clicked.

  4. When .talk_button is clicked, the context is set around that button. This is done with activeButton = $(this);. You will notice I used a combination of .parent(),.find() to find the elements within the context or container of that button.

Run the demo on jsfiddle. It was fun to work with, didn't know there's a speech api readily available on the browser.

https://jsfiddle.net/1pvqx2am/2/

Jerdine Sabio
  • 5,688
  • 2
  • 11
  • 23