【问题标题】:Continuous Speech Recognition on browser like "ok google" or "hey siri"浏览器上的连续语音识别,如“ok google”或“hey siri”
【发布时间】:2017-11-14 03:34:21
【问题描述】:

我正在做 POC,我的要求是我想在浏览器上实现 OK googleHey Siri 这样的功能。

我正在使用 Chrome 浏览器的 Web speech api。我注意到我无法继续识别,因为它会在一段时间后自动终止,并且出于安全考虑,我知道它是相关的。我只是在SpeechReognition 终止然后在其end 事件上执行另一个hack 我进一步start SpeechRecogntion 但这不是实现这种解决方案的最佳方法,因为假设我使用的2个实例不同浏览器选项卡上的相同应用程序然后它不起作用或者我可能在我的浏览器中使用另一个使用语音识别的应用程序然后两个应用程序的行为与预期不同。我正在寻找解决此问题的最佳方法。

提前致谢。

【问题讨论】:

    标签: javascript html google-chrome speech-recognition webspeech-api


    【解决方案1】:

    由于您的问题是您无法长时间连续运行 SpeechRecognition,因此一种方法是仅当您在麦克风中获得一些输入时才启动 SpeechRecognition。

    这种方式只有在有输入时才会启动 SR,寻找你的 magic_word。
    如果找到了 magic_word,那么您就可以正常使用 SR 执行其他任务了。

    这可以通过 WebAudioAPI 检测到,它不受 SR 所受的时间限制的约束。您可以通过来自 MediaDevices.getUserMedia 的 LocalMediaStream 提供它。

    更多信息,在下面的脚本,你可以看到this answer

    以下是如何将其附加到 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();
    }
    

    作为 a plunker,因为 StackSnippets 和 jsfiddle 的 iframe 都不允许 gUM 有两个版本...

    【讨论】:

    • Web Speech Api 自动检测到静音。它以错误代码no-speech 中止speech recognition。我的问题是没有检测到沉默,这是我想要继续听的东西,就像 android Ok Google 一样。我们的手机一直在听,当它检测到Ok google 时,它会激活它。我想要相同但在浏览器上使用最佳方法。
    • @ArunRedhu 你当时没有得到答案。你的问题是你不能做长时间连续的语音识别,对吧?此解决方案允许您仅在实际输入声音时启动 SpeechRecognition。这样,您可以收听您的magic_word,如果已经说过,请激活您的其他命令侦听器,否则,只需忽略并等待下一个magic_word。这样一来,只要没有说出 magic_word,您就不会一直使用 WebSpeechAPI。
    • @ArunRedhu 我改写了答案,希望您现在看到这个解决方案试图克服什么以及如何克服。
    猜你喜欢
    • 1970-01-01
    • 2017-08-30
    • 2014-11-05
    • 2023-04-06
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    相关资源
    最近更新 更多