Я пытаюсь использовать интерфейс 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, но это уже другая проблема.