Android Chrome 中的 Web Speech API 问题

Bes*_*rks 5 javascript android google-chrome webspeech-api webkitspeechrecognition

我正在尝试使用Web Speech APISpeechRecognition接口。它在桌面版 Chrome 上运行良好,但我无法在 Android 版本上检测到任何音频。在我自己的代码无法正常工作后,我在两个不同的 Android 设备(一个运行 LineageOS Nougat,一个运行 LineageOS Pie,都使用 Chrome 79)上测试了这个演示以及另一个演示,但两个演示都没有在任一设备上运行。

我不确定这里出了什么问题……其他人可以在 Android 上使用这些演示吗?我正在通过 https 提供我的测试页面,我可以使用navigator.mediaDevices.getUserMedia在这些设备上录制来自 microhpone 的音频,因此它似乎不是硬件、权限或安全问题。

我看到的具体症状如下:

这是一些基于MDN 示例的测试代码。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title> Web Speech API Test </title>
    <style>
      * { box-sizing: border-box; }

      html {
        height: 100%;
        width: 100%;
      }

      body {
        height: 100%;
        width: 100%;
        padding: 0;
        margin: 0;
        display: grid;
        grid-template-columns: 1fr;
        grid-template-rows: 1fr 10fr 1fr;
        font-family: sans-serif;
      }

      h1 {
        margin: 0;
        padding: 0.5rem;
        background-color: dodgerblue;
        text-align: center;
      }

      #output {
        margin: 0;
        padding: 0.5em;
        border: 0;
        background-color: transparent;
      }

      #start {
        display: block;
        background-color: dodgerblue;
        border: 0;
        color: navy;
        font-weight: bold;
        font-size: 1.2em;
      }
    </style>
  </head>
  <body>
    <h1> Web Speech API Test </h1>
    <textarea id="output"></textarea>
    <button id="start"> START </button>
    <script>
      let SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
      let SpeechGrammarList = window.SpeechGrammarList || window.webkitSpeechGrammarList;
      let SpeechRecognitionEvent = window.SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent;

      let grammar = '#JSGF V1.0; grammar colors; public <color> = aqua | azure | beige | bisque | black | blue | brown | chocolate | coral | crimson | cyan | fuchsia | ghostwhite | gold | goldenrod | gray | green | indigo | ivory | khaki | lavender | lime | linen | magenta | maroon | moccasin | navy | olive | orange | orchid | peru | pink | plum | purple | red | salmon | sienna | silver | snow | tan | teal | thistle | tomato | turquoise | violet | white | yellow ;';

      let recognition = new SpeechRecognition();
      let speechRecognitionList = new SpeechGrammarList();
      speechRecognitionList.addFromString(grammar, 1);

      recognition.grammars = speechRecognitionList;
      recognition.continuous = false;
      recognition.lang = 'en-US';
      recognition.interimResults = false;
      recognition.maxAlternatives = 1;

      let startButton = document.getElementById('start');
      let output = document.getElementById('output');
      output.value += 'Initializing...';

      let listening = false;

      startButton.addEventListener('click', event => {
        if (listening == false) {
          recognition.start();
          startButton.innerHTML = 'STOP';
          listening = true;
        } else {
      //    recognition.stop();
          recognition.abort();
        }
      });

      console.dir(recognition);
      output.value += 'ready.';

      recognition.onstart = event => {
        output.value += '\nRecognition started';
      };

      recognition.onaudiostart = event => {
        output.value += '\nAudio started';
      };

      recognition.onsoundstart = event => {
        output.value += '\nSound started';
      };

      recognition.onspeechstart = event => {
        output.value += '\nSpeech started';
      };

      recognition.onspeechend = event => {
        output.value += '\nSpeech ended';
        recognition.stop();
      };

      recognition.onsoundend = event => {
        output.value += '\nSound ended';
      };

      recognition.onaudioend = event => {
        output.value += '\nAudio ended';
      };

      recognition.onend = event => {
        output.value += '\nRecognition stopped';
        startButton.innerHTML = 'START';
        listening = false;
      };

      recognition.onresult = event => {
        let color = event.results[0][0].transcript;
        let confidence = event.results[0][0].confidence;
        document.body.style.backgroundColor = color;
        output.value += '\nResult recieved: ' + color;
        output.value += '\nConfidence: ' + confidence;
      };

      recognition.onnomatch = event => {
        output.value += '\nColor not recognised';
      };

      recognition.onerror = event => {
        output.value += '\nERROR: ' + event.error;
      };
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

关于问题可能是什么的任何想法将不胜感激。

更新 2021-01-08:

我修改了示例代码,以便将日志消息输出到一个textarea元素而不是控制台,以消除远程调试的需要。我还在我的域上发布了一个实时版本。然后我在 LineageOS Oreo 上使用 Chrome Canary 89 对其进行了测试,发现它仍然无法在那里工作。但是,我随后发现这个示例在运行其官方版本的 Android Pie 和 Chrome 87 的 Razer 手机上确实可以完美运行!因此,我的 WebSpeech 实现似乎很好,并且 LineageOS 可能存在其他一些存在多个版本的问题。

这个问题已经收到了相当多的意见,所以我想其他人一定有类似的问题。对于这些人,我建议您在几种不同的设备上尝试实时测试,然后在此处报告您的发现。也许我们可以缩小导致它在某些设备上而不是其他设备上失败的条件。可能这与 LineageOS 完全没有关系,而完全是另一个问题。