在知识付费直播中,常常会遇到听众在直播结束后忘记内容的情况。为了解决这一问题,通常的做法是提供讲义或文档,帮助听众沉淀和复习。然而,有时直播依赖临场发挥,无法提前准备详细的讲义。而在实践中发现,一边讲解一边手动整理输入编辑出文档也是不现实的。
为了找到一个实时生成文档的解决方案,我尝试了多种方案,但都不尽人意。AI离线语音识别虽然准确度高,但占用资源多,不适合长时间的实时直播。而在线的付费方案虽然便捷,但功能并不符合我的预期,价格昂贵且不好用。最终,我发现了一个轻量级且有效的能够高度自定义的解决方案——浏览器内置的 Web Speech API。
随着人工智能技术的迅猛发展,语音识别技术已经逐渐走入我们的日常生活。从语音助手到语音输入法,语音转文字(Speech-to-Text)技术为用户提供了更加便捷的交互方式。本文将介绍浏览器内置的Web Speech API,特别是其语音识别功能,并通过一个实践案例展示如何在网页中实现语音转文字功能。
Web Speech API 是一个由W3C制定的Web标准,旨在为Web应用提供语音识别和语音合成功能。该API主要包括两个部分:
本篇文章将重点介绍语音识别部分,即如何使用浏览器的SpeechRecognition API实现语音转文字功能。
Web Speech API 的语音识别功能在现代浏览器中的支持情况如下:
因此,为了确保应用的广泛兼容性,建议主要针对支持该API的浏览器进行开发和测试。
onstart
、onerror
、onend
和 onresult
等,用于处理语音识别过程中的不同状态和结果。
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>浏览器内置语音转文字示例title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
text-align: center;
}
#transcript {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
min-height: 100px;
width: 80%;
margin-left: auto;
margin-right: auto;
text-align: left;
white-space: pre-wrap;
background-color: #f9f9f9;
overflow-y: auto;
}
button {
padding: 10px 20px;
font-size: 16px;
margin: 5px;
cursor: pointer;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
style>
head>
<body>
<h1>浏览器内置语音转文字示例h1>
<button id="startBtn">开始录音button>
<button id="stopBtn" disabled>停止录音button>
<div id="transcript">
{
"paragraphs": []
}
div>
<script>
(function () {
// 获取页面中的按钮和显示区域
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const transcriptDiv = document.getElementById('transcript');
// 状态变量
let isRecognizing = false; // 是否正在识别
let recognition = null; // 语音识别实例
let speechContent = {
paragraphs: []
}; // 存储识别内容
let currentParagraph = { sentences: [] }; // 当前段落
// 初始化 Web Speech API
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition || null;
// 检查浏览器是否支持语音识别
if (!window.SpeechRecognition) {
alert("您的浏览器不支持语音识别。请使用最新版本的 Chrome 或 Edge。");
startBtn.disabled = true; // 禁用开始按钮
return;
}
// 创建语音识别实例
recognition = new window.SpeechRecognition();
recognition.lang = 'zh-CN'; // 设置语言为中文
recognition.interimResults = true; // 启用中间结果
recognition.continuous = true; // 启用连续识别
// 语音识别开始时的回调
recognition.onstart = () => {
console.log('语音识别已启动。');
isRecognizing = true;
startBtn.disabled = true; // 禁用开始按钮
stopBtn.disabled = false; // 启用停止按钮
};
// 语音识别出错时的回调
recognition.onerror = (event) => {
console.error('语音识别错误:', event.error);
alert(`语音识别错误: ${event.error}`);
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
// 语音识别结束时的回调
recognition.onend = () => {
console.log('语音识别已结束。');
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
// 语音识别结果时的回调
recognition.onresult = (event) => {
// 遍历所有识别结果
for (let i = event.resultIndex; i < event.results.length; i++) {
const result = event.results[i];
const transcript = result[0].transcript.trim(); // 获取识别的文本
const isFinal = result.isFinal; // 是否为最终结果
if (isFinal) {
// 如果是最终结果,将句子添加到当前段落
currentParagraph.sentences.push({ finalTranscript: transcript });
speechContent.paragraphs.push(currentParagraph); // 将段落添加到speechContent
currentParagraph = { sentences: [] }; // 重置当前段落
} else {
// 如果是临时结果,更新当前段落的最后一个句子
if (currentParagraph.sentences.length === 0) {
// 如果当前段落没有句子,添加一个临时句子
currentParagraph.sentences.push({ interimTranscript: transcript });
} else {
// 更新最后一个句子的临时文本
currentParagraph.sentences[currentParagraph.sentences.length - 1].interimTranscript = transcript;
}
}
}
updateTranscript(); // 更新显示区域
};
// 开始录音按钮的点击事件
startBtn.addEventListener('click', () => {
if (recognition && !isRecognizing) {
recognition.start(); // 启动语音识别
console.log('开始录音...');
}
});
// 停止录音按钮的点击事件
stopBtn.addEventListener('click', () => {
if (recognition && isRecognizing) {
recognition.stop(); // 停止语音识别
console.log('停止录音。');
}
});
// 更新显示区域的函数
function updateTranscript() {
// 将speechContent对象格式化为JSON字符串,并显示在页面上
transcriptDiv.textContent = JSON.stringify(speechContent, null, 2);
}
// 初始显示
updateTranscript();
})();
script>
body>
html>
下面将详细解析上述代码的各个部分,帮助您更好地理解其工作原理。
<body>
<h1>浏览器内置语音转文字示例h1>
<button id="startBtn">开始录音button>
<button id="stopBtn" disabled>停止录音button>
<div id="transcript">
{
"paragraphs": []
}
div>
...
body>
startBtn
):用户点击后开始语音识别。stopBtn
):用户点击后停止语音识别。初始状态下被禁用,只有在语音识别启动后才启用。transcript
):用于实时显示语音识别的结果,初始内容为一个空的JSON对象。body {
font-family: Arial, sans-serif;
margin: 40px;
text-align: center;
}
#transcript {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
min-height: 100px;
width: 80%;
margin-left: auto;
margin-right: auto;
text-align: left;
white-space: pre-wrap;
background-color: #f9f9f9;
overflow-y: auto;
}
button {
padding: 10px 20px;
font-size: 16px;
margin: 5px;
cursor: pointer;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
(function () {
// 获取页面中的按钮和显示区域
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const transcriptDiv = document.getElementById('transcript');
// 状态变量
let isRecognizing = false; // 是否正在识别
let recognition = null; // 语音识别实例
let speechContent = {
paragraphs: []
}; // 存储识别内容
let currentParagraph = { sentences: [] }; // 当前段落
// 初始化 Web Speech API
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition || null;
// 检查浏览器是否支持语音识别
if (!window.SpeechRecognition) {
alert("您的浏览器不支持语音识别。请使用最新版本的 Chrome 或 Edge。");
startBtn.disabled = true; // 禁用开始按钮
return;
}
// 创建语音识别实例
recognition = new window.SpeechRecognition();
recognition.lang = 'zh-CN'; // 设置语言为中文
recognition.interimResults = true; // 启用中间结果
recognition.continuous = true; // 启用连续识别
// 语音识别开始时的回调
recognition.onstart = () => {
console.log('语音识别已启动。');
isRecognizing = true;
startBtn.disabled = true; // 禁用开始按钮
stopBtn.disabled = false; // 启用停止按钮
};
// 语音识别出错时的回调
recognition.onerror = (event) => {
console.error('语音识别错误:', event.error);
alert(`语音识别错误: ${event.error}`);
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
// 语音识别结束时的回调
recognition.onend = () => {
console.log('语音识别已结束。');
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
// 语音识别结果时的回调
recognition.onresult = (event) => {
// 遍历所有识别结果
for (let i = event.resultIndex; i < event.results.length; i++) {
const result = event.results[i];
const transcript = result[0].transcript.trim(); // 获取识别的文本
const isFinal = result.isFinal; // 是否为最终结果
if (isFinal) {
// 如果是最终结果,将句子添加到当前段落
currentParagraph.sentences.push({ finalTranscript: transcript });
speechContent.paragraphs.push(currentParagraph); // 将段落添加到speechContent
currentParagraph = { sentences: [] }; // 重置当前段落
} else {
// 如果是临时结果,更新当前段落的最后一个句子
if (currentParagraph.sentences.length === 0) {
// 如果当前段落没有句子,添加一个临时句子
currentParagraph.sentences.push({ interimTranscript: transcript });
} else {
// 更新最后一个句子的临时文本
currentParagraph.sentences[currentParagraph.sentences.length - 1].interimTranscript = transcript;
}
}
}
updateTranscript(); // 更新显示区域
};
// 开始录音按钮的点击事件
startBtn.addEventListener('click', () => {
if (recognition && !isRecognizing) {
recognition.start(); // 启动语音识别
console.log('开始录音...');
}
});
// 停止录音按钮的点击事件
stopBtn.addEventListener('click', () => {
if (recognition && isRecognizing) {
recognition.stop(); // 停止语音识别
console.log('停止录音。');
}
});
// 更新显示区域的函数
function updateTranscript() {
// 将speechContent对象格式化为JSON字符串,并显示在页面上
transcriptDiv.textContent = JSON.stringify(speechContent, null, 2);
}
// 初始显示
updateTranscript();
})();
(function () {
// ...代码内容...
})();
使用立即执行函数(IIFE)包裹所有JavaScript代码,避免全局命名空间污染。
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const transcriptDiv = document.getElementById('transcript');
通过 document.getElementById
获取页面中的开始和停止按钮,以及显示识别结果的 div
。
let isRecognizing = false; // 是否正在识别
let recognition = null; // 语音识别实例
let speechContent = {
paragraphs: []
}; // 存储识别内容
let currentParagraph = { sentences: [] }; // 当前段落
SpeechRecognition
实例。window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition || null;
兼容不同浏览器的前缀,确保在支持的浏览器中正确初始化 SpeechRecognition
。
if (!window.SpeechRecognition) {
alert("您的浏览器不支持语音识别。请使用最新版本的 Chrome 或 Edge。");
startBtn.disabled = true; // 禁用开始按钮
return;
}
如果浏览器不支持语音识别,提示用户并禁用开始录音按钮。
recognition = new window.SpeechRecognition();
recognition.lang = 'zh-CN'; // 设置语言为中文
recognition.interimResults = true; // 启用中间结果
recognition.continuous = true; // 启用连续识别
recognition.onstart = () => {
console.log('语音识别已启动。');
isRecognizing = true;
startBtn.disabled = true; // 禁用开始按钮
stopBtn.disabled = false; // 启用停止按钮
};
当语音识别启动时,更新状态变量,禁用开始按钮,启用停止按钮,并在控制台打印日志。
recognition.onerror = (event) => {
console.error('语音识别错误:', event.error);
alert(`语音识别错误: ${event.error}`);
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
当语音识别过程中发生错误时,显示错误信息,更新状态变量,并调整按钮状态。
recognition.onend = () => {
console.log('语音识别已结束。');
isRecognizing = false;
startBtn.disabled = false; // 启用开始按钮
stopBtn.disabled = true; // 禁用停止按钮
};
当语音识别结束时,更新状态变量,启用开始按钮,禁用停止按钮,并在控制台打印日志。
recognition.onresult = (event) => {
// 遍历所有识别结果
for (let i = event.resultIndex; i < event.results.length; i++) {
const result = event.results[i];
const transcript = result[0].transcript.trim(); // 获取识别的文本
const isFinal = result.isFinal; // 是否为最终结果
if (isFinal) {
// 如果是最终结果,将句子添加到当前段落
currentParagraph.sentences.push({ finalTranscript: transcript });
speechContent.paragraphs.push(currentParagraph); // 将段落添加到speechContent
currentParagraph = { sentences: [] }; // 重置当前段落
} else {
// 如果是临时结果,更新当前段落的最后一个句子
if (currentParagraph.sentences.length === 0) {
// 如果当前段落没有句子,添加一个临时句子
currentParagraph.sentences.push({ interimTranscript: transcript });
} else {
// 更新最后一个句子的临时文本
currentParagraph.sentences[currentParagraph.sentences.length - 1].interimTranscript = transcript;
}
}
}
updateTranscript(); // 更新显示区域
};
对于每一个识别结果:
result[0].transcript
获取识别到的文本,并使用 trim()
去除首尾空白字符。isFinal = true
):speechContent.paragraphs
。currentParagraph
以开始新的段落。isFinal = false
):最后,调用 updateTranscript()
函数更新显示区域。
// 开始录音按钮的点击事件
startBtn.addEventListener('click', () => {
if (recognition && !isRecognizing) {
recognition.start(); // 启动语音识别
console.log('开始录音...');
}
});
// 停止录音按钮的点击事件
stopBtn.addEventListener('click', () => {
if (recognition && isRecognizing) {
recognition.stop(); // 停止语音识别
console.log('停止录音。');
}
});
// 更新显示区域的函数
function updateTranscript() {
// 将speechContent对象格式化为JSON字符串,并显示在页面上
transcriptDiv.textContent = JSON.stringify(speechContent, null, 2);
}
// 初始显示
updateTranscript();
speechContent
对象格式化为带有缩进的JSON字符串,并显示在 transcript
区域。updateTranscript()
显示初始的空JSON对象。通过上述代码,我们实现了一个简单的语音转文字应用,其主要功能包括:
当用户点击“开始录音”按钮后,浏览器会请求麦克风权限,并开始监听用户的语音输入。用户说话时,语音识别结果会实时显示在页面上的 transcript
区域。当用户点击“停止录音”按钮,语音识别将停止,按钮状态也会相应更新。
以下是一个示例的识别结果显示:
{
"paragraphs": [
{
"sentences": [
{
"finalTranscript": "你好,我正在测试语音识别功能。"
}
]
},
{
"sentences": [
{
"finalTranscript": "这是一个多段落的测试。"
}
]
}
]
}
lang
属性,确保识别结果的准确性。本示例中设置为中文(zh-CN
)。通过本文的介绍和实践案例,我们了解了如何使用浏览器内置的Web Speech API实现语音转文字功能。该技术不仅能够提升用户体验,还为开发更加智能化的Web应用提供了可能。未来,随着Web Speech API的不断完善和浏览器支持的扩大,语音交互将成为Web应用的重要组成部分。
Challenges in the Verification of Reinforcement Learning Algorithms