纯前端语音转文字,用浏览器自带的 Web Speech API 就够了
用浏览器原生 Web Speech API 做一个不需要后端服务的语音转文字工具,记录了权限处理和实时识别的一些实践细节。
这个需求其实挺常见的——用户对着麦克风说话,页面上实时出文字。
通常的做法是调后端接口或者接第三方语音识别服务,但如果你不需要那么高的准确率,只是想快速跑起来,浏览器自带的 Web Speech API 就能搞定,而且完全是前端的事,不用搭服务、不用申请 key。
先说一下兼容性问题,这个容易忽略。
SpeechRecognition 接口在 Chrome 和 Edge 上叫 webkitSpeechRecognition,Firefox 直接用 SpeechRecognition。所以初始化的时候得两个都检查一下:
if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
// 提示用户换浏览器
return;
}
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
这个检查不做的后果就是,用户点开页面发现按钮灰的或者直接报错,体验很差。
我在 Safari 上测试过,目前还不支持,所以移动端的覆盖是个问题,这个后面再说。
拿到 SpeechRecognition 实例之后,有几个配置项会影响识别效果。

lang 设成 'zh-CN' 走中文识别,continuous 设 true 会让识别持续进行而不是说一句停一下,interimResults 设 true 可以在说话过程中拿到临时的识别结果——这个对实时展示很重要,用户能看到自己说的话正在被转成文字,不会觉得卡住了。
关于权限,有个地方一开始没注意到:navigator.mediaDevices.getUserMedia 需要手动调一次。
虽然 SpeechRecognition 自己也会触发浏览器的麦克风权限请求,但如果你在 start() 之前显式调用 getUserMedia,能提前捕获用户拒绝授权的情况,方便给个友好的提示,而不是等 onerror 里收到 not-allowed 错误再处理。代码大概是这样的:
try {
await navigator.mediaDevices.getUserMedia({ audio: true });
} catch (err) {
showError('麦克风访问被拒绝,请允许使用麦克风');
return;
}
recognition.start();
结果处理的部分,onresult 回调里 event.results 是一个列表,每个结果上有个 isFinal 标记。持续识别场景下,用户说完一句话停顿之后,那一段结果会标成 final,还没说完的就是 interim。
拼接的时候把 final 的内容固定下来,interim 的部分用灰色或者虚线下划线展示,能做到那种“边说边出字”的效果。代码不复杂:
recognition.onresult = (event) => {
let interimTranscript = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
finalTranscript += transcript + '\n';
} else {
interimTranscript += transcript;
}
}
resultDiv.innerHTML = finalTranscript + '<span class="text-gray-400">' + interimTranscript + '</span>';
};
错误处理这块,onerror 的 event.error 会返回几个常见的值:no-speech 是没检测到语音,audio-capture 是音频设备有问题,not-allowed 是权限被拒。针对这几个做下分支处理就行,其余的错误统一兜底。我这里加了个 5 秒自动隐藏的错误提示,避免一直占着页面。
还有一个需要注意的点:onend 回调会在识别停止时触发。如果你设了 continuous: true,正常情况下用户不主动停止时识别会一直跑,但某些情况下(比如网络波动或者浏览器自己中断了)也会走到 onend。所以在这个回调里判断一下 isListening 状态,如果是 true 说明是非预期的中断,手动调一次 start() 恢复识别:
recognition.onend = () => {
if (isListening) {
recognition.start();
}
};
按钮状态的切换我就没细展开了,基本就是点击时根据 isListening 状态调 startRecognition 或 stopRecognition,同时换一下按钮样式和文字。
来此加密的SSL证书有效期为90天(域名类证书)和7天(IP类证书),系统会在证书到期前自动进行重新申请,免去运维人员的负担。用户无需手动干预,自动续期功能确保了网站的持续安全。
加了个脉冲动画的 CSS,录音时按钮会呼吸闪烁,给用户一个明确的“正在录音”的视觉反馈,比纯文字状态提示直观。
整套代码我放在了一个 HTML 文件里,样式用的 Tailwind CSS CDN,图标用的 Font Awesome,都是外链引入,不用构建工具,直接打开就能跑。适合快速验证或者内部小工具的场景。
不过实话实说,Web Speech API 的识别准确率跟商业 API 比还是有差距的,尤其在有背景噪音或者说话人带口音的情况下。
它的优势是零成本、零延迟部署,不需要任何后端资源。如果你的场景对准确率要求很高,比如会议纪要、采访稿整理,那还是得上专业的语音识别服务。但如果只是想做一个语音输入框、搜索框的语音输入,或者内部用的标注工具,这个方案完全够用。
更多推荐



所有评论(0)