【发布时间】:2020-06-12 04:26:08
【问题描述】:
我正在尝试使用Web Speech API 的SpeechRecognition 接口。它在桌面版 Chrome 上运行良好,但我无法让它检测到 Android 版上的任何音频。在我自己的代码无法运行后,我在两台不同的 Android 设备上测试了 this demo 和 this other demo(一台运行 LineageOS Nougat,一台运行 LineageOS Pie,均使用 Chrome 79),但两个演示都无法在任一设备上运行。
我不确定这里出了什么问题...其他人可以让这些演示在 Android 上运行吗?我正在通过 https 提供我的测试页面,我可以使用 navigator.mediaDevices.getUserMedia 在这些设备上录制来自 microhpone 的音频,所以这似乎不是硬件、权限或安全问题。
我看到的具体症状如下:
-
start事件在按预期开始识别后触发,但随后的audiostart、soundstart、speechstart和result事件应该跟随它永远不会这样做。 -
尝试调用
SpeechRecognition.stop似乎没有任何效果——end 事件不会被触发。在停止尝试后调用SpeechRecognition.start会引发 Uncaught DOMException: Failed to execute 'start' on 'SpeechRecognition': 识别已经开始。 -
调用
SpeechRecognition.abort会触发end事件并允许重新启动识别。
这里有一些基于example from 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>
任何关于问题可能是什么的想法都将不胜感激。
2021-01-08 更新:
我修改了示例代码,使其将日志消息输出到textarea 元素而不是控制台,以消除远程调试的需要。我还在我的域上发布了live version。然后我在 LineageOS Oreo 上使用 Chrome Canary 89 对其进行了测试,发现它仍然无法在那里工作。然而,我随后发现这个示例在运行官方版本的 Android Pie 和 Chrome 87 的 Razer 手机上运行良好!所以看起来我的 WebSpeech 实现很好,并且可能存在多个版本的 LineageOS 的其他问题。
这个问题已经收到了相当多的意见,所以我想其他人一定有类似的问题。对于这些人,我建议您在几种不同的设备上尝试实时测试,并在此处报告您的发现。也许我们可以缩小导致它在某些设备上失败但在其他设备上失败的条件。可能这与 LineageOS 完全没有关系,而完全是另一个问题。
【问题讨论】:
-
只是想补充一点,我也在 Chrome Canary 82 中尝试了上述测试代码,结果相同。
标签: javascript android google-chrome webspeech-api webkitspeechrecognition