Проблемы с Web Speech API в Android Chrome

Я пытаюсь использовать интерфейс SpeechRecognition для Web Speech API. Он отлично работает в настольной версии Chrome, но я не могу заставить его обнаруживать звук в версии Android. После того, как мой собственный код не заработал, я протестировал эту демонстрацию а также эту другую демонстрацию на двух разных устройствах Android. устройства (одно работает с LineageOS Nougat, другое с LineageOS Pie, оба с Chrome 79), но ни одна демонстрация не работала ни на одном устройстве.

Я не уверен, что здесь не так ... может ли кто-нибудь еще заставить эти демонстрации работать на Android? Я обслуживаю свою тестовую страницу через https, и я могу записывать звук с microhpone на эти устройства, используя navigator.mediaDevices.getUserMedia, поэтому это не похоже на аппаратное обеспечение, разрешение или проблему безопасности.

Я наблюдаю следующие специфические симптомы:

  • Событие start запускается после первоначального запуска распознавания как ожидается, но последующий audiostart, _ 3_, _ 4_ и _ 5_ события, за которыми должны следовать, никогда не происходят.

  • Попытка вызвать SpeechRecognition.stop, похоже, не имеет никакого эффекта - событие end не запускается. Вызов SpeechRecognition.start после попытки остановки вызывает ошибку Неперехваченное исключение DOMException: не удалось выполнить start для SpeechRecognition: распознавание уже началось.

  • Вызов SpeechRecognition.abort вызывает событие end и разрешает распознавание будет перезапущено.

Вот тестовый код, основанный на примере из 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>

Любые идеи относительно того, в чем может быть проблема, будут оценены.

ОБНОВЛЕНИЕ, 08.01.2021:

Я изменил пример кода, чтобы он выводил сообщения журнала в элемент textarea вместо консоли, чтобы исключить необходимость удаленной отладки. Я также опубликовал в своем домене действующую версию. Затем я протестировал его с помощью Chrome Canary 89 в LineageOS Oreo и обнаружил, что там он по-прежнему не работает. Однако затем я обнаружил, что этот пример ДЕЙСТВИТЕЛЬНО работает на телефоне Razer с официальной версией Android Pie и Chrome 87! Таким образом, может показаться, что моя реализация WebSpeech в порядке, и, возможно, есть еще одна проблема с LineageOS, которая существовала для нескольких версий.

Этот вопрос получил довольно много просмотров, поэтому я полагаю, что у других должны быть похожие проблемы. Этим людям я предлагаю вам попробовать живой тест на нескольких разных устройствах и сообщить о своих результатах здесь. Возможно, мы сможем сузить круг условий, которые вызывают сбой на некоторых устройствах, но не на других. Возможно, это не имеет ничего общего с LineageOS, но это уже другая проблема.


person Besworks    schedule 28.02.2020    source источник
comment
Просто хочу добавить, что я также пробовал приведенный выше тестовый код в Chrome Canary 82 с теми же ошибочными результатами.   -  person Besworks    schedule 29.02.2020


Ответы (2)


API веб-речи на Android использует стороннюю службу, которая обычно реализуется Google (Play Services) и / или производителем (например, Samsung). Скорее всего, эта служба отсутствует или отключена в LineageOS, поскольку обычно она подключается к облачному серверу для транскрипции.

person Flow    schedule 15.07.2021
comment
Это кажется очень вероятным сценарием. Мне интересно, поможет ли установка более крупного пакета из opengapps.org. Я обычно устанавливаю пакет pico на свои устройства, что довольно мало. - person Besworks; 16.07.2021
comment
К сожалению, у меня еще нет опыта в этом, но я был бы заинтересован в результате ^^. Я думаю, что видел людей с LineageOS, у которых это работало. - person Flow; 16.07.2021
comment
Что ж, сейчас я слишком занят работой, чтобы возиться со своим телефоном, но я обязательно опубликую результаты, если / когда я попытаюсь это сделать. Эти комментарии сами по себе могут подтолкнуть кого-нибудь еще, чтобы дать шанс раньше меня. Я обязательно приму ваш ответ, если мы докажем, что это проблема. - person Besworks; 17.07.2021

Вы управляете объектом распознавания с помощью переменной прослушивания, поэтому установите для прослушивания значение false после распознавания.stop ().

recognition.onspeechend = event => {
    console.log('speechend');
    recognition.stop();
    listening = false;
};
person user8260998    schedule 04.01.2021
comment
Это полезная настройка примера кода, но она не решает основную проблему, заключающуюся в том, что распознавание речи не запускается. Я обновил исходный пост, добавив новый пример кода и результаты тестов. - person Besworks; 09.01.2021