Непрерывное распознавание речи в браузере, например, «окей, гугл» или «эй, сири».

Я делаю POC, и мое требование состоит в том, что я хочу реализовать такую ​​​​функцию, как OK google или Hey Siri в браузере.

Я использую браузер Chrome Web speech api. То, что я заметил, я не могу продолжать распознавать, поскольку оно автоматически прекращается через определенный период времени, и я знаю, что это актуально из-за соображений безопасности. Я просто делаю еще один взлом, например, когда SpeechReognition завершается, а затем в его событии end я продолжаю start SpeechRecogntion, но это не лучший способ реализовать такое решение, потому что предположим, если я использую 2 экземпляра одного и того же приложения на другой вкладке браузера, тогда Это не работает, или, возможно, я использую другое приложение в своем браузере, которое использует распознавание речи, тогда оба приложения ведут себя не так, как ожидалось. Я ищу лучший подход для решения этой проблемы.

Заранее спасибо.


person Arun Redhu    schedule 14.11.2017    source источник


Ответы (1)


Поскольку ваша проблема заключается в том, что вы не можете запускать SpeechRecognition непрерывно в течение длительных периодов времени, одним из способов было бы запускать SpeechRecognition только тогда, когда вы получаете какой-либо ввод в микрофон.

Таким образом, только когда будет какой-то ввод, вы запустите SR, ища ваше magic_word.
Если magic_word будет найдено, то вы сможете использовать SR как обычно для других ваших задач.

Это может быть обнаружено с помощью WebAudioAPI, который не привязан к этому временному ограничению, от которого страдает SR. Вы можете передать его через LocalMediaStream из MediaDevices.getUserMedia.

Для получения дополнительной информации о сценарии ниже вы можете увидеть этот ответ.

Вот как вы можете прикрепить его к SpeechRecognition:

const magic_word = ##YOUR_MAGIC_WORD##;

// initialize our SpeechRecognition object
let recognition = new webkitSpeechRecognition();
recognition.lang = 'en-US';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.continuous = true;

// detect the magic word
recognition.onresult = e => {
    // extract all the transcripts
    var transcripts  = [].concat.apply([], [...e.results]
      .map(res => [...res]
        .map(alt => alt.transcript)
      )
    );
  if(transcripts.some(t => t.indexOf(magic_word) > -1)){
    //do something awesome, like starting your own command listeners
  }
  else{
    // didn't understood...
  }
}
// called when we detect silence
function stopSpeech(){
    recognition.stop();
}
// called when we detect sound
function startSpeech(){
    try{ // calling it twice will throw...
      recognition.start();
  }
  catch(e){}
}
// request a LocalMediaStream
navigator.mediaDevices.getUserMedia({audio:true})
// add our listeners
.then(stream => detectSilence(stream, stopSpeech, startSpeech))
.catch(e => log(e.message));


function detectSilence(
  stream,
  onSoundEnd = _=>{},
  onSoundStart = _=>{},
  silence_delay = 500,
  min_decibels = -80
  ) {
  const ctx = new AudioContext();
  const analyser = ctx.createAnalyser();
  const streamNode = ctx.createMediaStreamSource(stream);
  streamNode.connect(analyser);
  analyser.minDecibels = min_decibels;

  const data = new Uint8Array(analyser.frequencyBinCount); // will hold our data
  let silence_start = performance.now();
  let triggered = false; // trigger only once per silence event

  function loop(time) {
    requestAnimationFrame(loop); // we'll loop every 60th of a second to check
    analyser.getByteFrequencyData(data); // get current data
    if (data.some(v => v)) { // if there is data above the given db limit
      if(triggered){
        triggered = false;
        onSoundStart();
        }
      silence_start = time; // set it to now
    }
    if (!triggered && time - silence_start > silence_delay) {
      onSoundEnd();
      triggered = true;
    }
  }
  loop();
}

Как планкер, поскольку ни StackSnippets, ни iframes jsfiddle не будут разрешить гум в двух вариантах...

person Kaiido    schedule 14.11.2017
comment
Тишина автоматически определяется Web Speech Api. Он прерывает speech recognition с кодом ошибки no-speech. Мой вопрос не в обнаружении тишины, это то, что я хочу продолжать слушать, как андроид Ok Google. Наш мобильный всегда слушает, и когда он обнаруживает Ok google, он активирует его. Я хочу то же самое, но с лучшим подходом в браузере. - person Arun Redhu; 15.11.2017
comment
@ArunRedhu, тогда ты не получил ответа. Ваша проблема в том, что вы не можете выполнять длительные непрерывные SpeechRecognitions, верно? Это решение позволяет запускать SpeechRecognition только тогда, когда действительно есть входные звуки. Таким образом, вы можете прослушивать свое magic_word, если оно было сказано, активировать другие слушатели команд, в противном случае просто игнорировать и ждать следующего magic_word. Таким образом, вы не будете постоянно использовать WebSpeechAPI, пока не будет произнесено magic_word. - person Kaiido; 15.11.2017
comment
@ArunRedhu Я переформулировал ответ, надеясь, что теперь вы видите, что это решение пытается преодолеть и как. - person Kaiido; 15.11.2017