开发工具/音视频/基于 WebSocket 实现音频通话/集成语音识别 SDK
集成语音识别 SDK
更新于: 2026-06-25 19:29:14
语音识别 SDK(简称 WsTranscription SDK)是基于双向流式语音识别 WebSocket OpenAPI 封装的软件开发工具包。它为开发者提供了一套高效且完整的语音交互解决方案,可快速集成至各类应用程序,实现高质量的语音识别功能。扣子提供 Demo 和示例项目源码,助力开发者迅速掌握并应用。更多接口详情请参考双向流式语音识别。
扣子提供语音识别 Demo 和 TypeScript 格式的语音识别示例源码 ,帮助你快速体验语音识别的功能,并根据示例源码快速实现语音识别。
Demo 的主要功能包括:
| 配置 | 说明 |
|---|---|
| Base WS URL | 保持默认值 wss://ws.coze.cn。 |
|
个人访问令牌 |
扣子 API & SDK 通过访问令牌进行 API & SDK 请求的鉴权。 个人访问令牌的获取方式可参考添加个人访问令牌。 说明 应为令牌授予 |
以下是基于 React 和 Antd 框架开发的语音识别示例代码,包含用户界面、状态管理和错误处理等功能,帮助你快速了解语音识别的实现流程。
使用前需配置个人访问令牌(ACCESS_TOKEN),并安装@coze/api、antd、react 等依赖,建议开发时开启调试模式。
该示例代码中包含如下功能:
import React, { useEffect, useRef, useState } from 'react';
import {
Button,
Layout,
Space,
Typography,
message,
Row,
Col,
Card,
} from 'antd';
import {
WsToolsUtils,
WsTranscriptionClient,
AIDenoiserProcessorMode,
AIDenoiserProcessorLevel,
} from '@coze/api/ws-tools';
import {
type CommonErrorEvent,
type TranscriptionsMessageUpdateEvent,
WebsocketsEventType,
} from '@coze/api';
import {
AudioOutlined,
PauseOutlined,
PlayCircleOutlined,
} from '@ant-design/icons';
const { Title, Paragraph, Text } = Typography;
// 个人访问令牌
const ACCESS_TOKEN = 'pat_Qm47PKJR5dvMOP53v6DyzwCbTtvEZHQc2TVINEveg9v1T3iSYlTdScJ8***';
const TranscriptionDemo: React.FC = () => {
const clientRef = useRef<WsTranscriptionClient>();
const [isRecording, setIsRecording] = useState(false);
const [isPaused, setIsPaused] = useState(false);
const [transcriptionText, setTranscriptionText] = useState('');
const [disabled, setDisabled] = useState(false);
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
const [hasToken, setHasToken] = useState<boolean>(false);
const [status, setStatus] = useState<string>('未开始');
const [denoiserSupported, setDenoiserSupported] = useState<boolean>(false);
// 检查权限和令牌
useEffect(() => {
const checkRequirements = async () => {
// 检查麦克风权限
const permission = await WsToolsUtils.checkDevicePermission();
setHasPermission(permission.audio);
// 检查是否配置了PAT令牌
const hasConfiguredToken = !!ACCESS_TOKEN;
setHasToken(hasConfiguredToken);
// 检查是否支持AI降噪
const isDenoiserSupported = WsToolsUtils.checkDenoiserSupport();
setDenoiserSupported(isDenoiserSupported);
};
checkRequirements();
}, []);
// 初始化客户端
const initClient = async () => {
if (!hasPermission) {
throw new Error('麦克风权限未授予');
}
const client = new WsTranscriptionClient({
token: ACCESS_TOKEN,
allowPersonalAccessTokenInBrowser: true,
debug: true,
// AI降噪配置 - 仅当浏览器支持并且选择使用时开启
aiDenoisingConfig: denoiserSupported
? {
mode: AIDenoiserProcessorMode.NSNG, // AI降噪模式
level: AIDenoiserProcessorLevel.SOFT, // 舒缓降噪
assetsPath:
'https://lf3-static.bytednsdoc.com/obj/eden-cn/613eh7lpqvhpeuloz/websocket',
}
: undefined,
// 音频捕获配置
audioCaptureConfig: {
echoCancellation: true,
noiseSuppression: !denoiserSupported, // 如果支持AI降噪,则禁用浏览器内置降噪
autoGainControl: true,
},
});
// 如果使用AI降噪但浏览器不支持,则提示用户
if (!denoiserSupported) {
message.info('当前浏览器不支持AI降噪,将使用浏览器内置降噪');
}
// 监听转录结果更新
client.on(
WebsocketsEventType.TRANSCRIPTIONS_MESSAGE_UPDATE,
(event: unknown) => {
setTranscriptionText(
(event as TranscriptionsMessageUpdateEvent).data.content,
);
},
);
// 监听错误事件
client.on(WebsocketsEventType.ERROR, (error: unknown) => {
console.error(error);
message.error((error as CommonErrorEvent).data.msg);
});
// 监听所有事件(用于调试)
client.on(WebsocketsEventType.ALL, (event: unknown) => {
console.log('收到事件', event);
});
clientRef.current = client;
};
// 开始/停止录音
const handleStartAndStop = async () => {
try {
setDisabled(true); // 操作过程中禁用按钮,防止重复点击
if (!clientRef.current) {
await initClient();
}
if (!isRecording) {
// 开始语音识别
await clientRef.current?.start();
setTranscriptionText('');
setIsRecording(true);
setStatus('录音中');
} else {
// 停止语音识别
await clientRef.current?.stop();
setIsRecording(false);
setIsPaused(false);
setStatus('已停止');
}
} catch (error) {
message.error(`操作失败:${error}`);
console.error(error);
setIsRecording(false);
setStatus('发生错误');
} finally {
setDisabled(false);
}
};
// 暂停/恢复录音
const handlePauseAndResume = () => {
try {
if (clientRef.current?.getStatus() === 'paused') {
clientRef.current?.resume();
setIsPaused(false);
setStatus('录音中');
} else {
clientRef.current?.pause();
setIsPaused(true);
setStatus('已暂停');
}
} catch (error) {
message.error(`暂停/恢复失败: ${error}`);
}
};
return (
<Layout style={{ height: '100%' }}>
<Layout.Content style={{ background: '#fff', padding: '20px' }}>
<Title level={2}>语音识别 (ASR) 演示</Title>
{/* 前置条件检查 */}
<Card title="前置条件检查" style={{ marginBottom: '20px' }}>
<Row gutter={[0, 16]}>
<Col span={24}>
<Space>
<Text strong>麦克风权限:</Text>
{hasPermission === null ? (
<Text type="warning">正在检查...</Text>
) : hasPermission ? (
<Text type="success">已授权</Text>
) : (
<Text type="danger">未授权 - 请允许浏览器使用麦克风</Text>
)}
</Space>
</Col>
<Col span={24}>
<Space>
<Text strong>个人访问令牌 (PAT):</Text>
{hasToken ? (
<Text type="success">已配置</Text>
) : (
<Text type="danger">未配置 - 请在右上角 Settings 中设置</Text>
)}
</Space>
</Col>
<Col span={24}>
<Space>
<Text strong>AI降噪支持:</Text>
{denoiserSupported ? (
<Text type="success">支持</Text>
) : (
<Text type="warning">不支持 - 将使用浏览器内置降噪</Text>
)}
</Space>
</Col>
</Row>
</Card>
{/* 录音控制 */}
<Card title="录音控制" style={{ marginBottom: '20px' }}>
<Row justify="start" style={{ marginBottom: '16px' }}>
<Col>
<Text>
当前状态: <Text strong>{status}</Text>
</Text>
</Col>
</Row>
<Row gutter={16}>
<Col>
<Button
type="primary"
icon={<AudioOutlined />}
disabled={disabled || !hasPermission || !hasToken}
onClick={handleStartAndStop}
danger={isRecording}
size="large"
>
{isRecording ? '停止录音' : '开始录音'}
</Button>
</Col>
{isRecording && (
<Col>
<Button
icon={isPaused ? <PlayCircleOutlined /> : <PauseOutlined />}
onClick={handlePauseAndResume}
size="large"
>
{isPaused ? '恢复录音' : '暂停录音'}
</Button>
</Col>
)}
</Row>
</Card>
{/* 识别结果 */}
<Card title="识别结果" bodyStyle={{ minHeight: '120px' }}>
<Paragraph>
{transcriptionText || <Text type="secondary">等待识别结果...</Text>}
</Paragraph>
</Card>
{/* 使用说明 */}
<Card title="使用说明" style={{ marginTop: '20px' }}>
<Paragraph>
<ol>
<li>确保授予浏览器麦克风访问权限</li>
<li>在代码中配置个人访问令牌 (ACCESS_TOKEN)</li>
<li>点击"开始录音"按钮开始语音识别</li>
<li>说话时,实时识别结果将显示在"识别结果"区域</li>
<li>可以使用"暂停录音"按钮暂时停止录音(保持上下文)</li>
<li>完成后点击"停止录音"按钮结束会话</li>
</ol>
</Paragraph>
</Card>
</Layout.Content>
</Layout>
);
};
export default TranscriptionDemo;
你可以通过 WsTranscriptionClient 类来实现实时语音识别功能,支持开始、暂停、恢复和停止等基本操作。
运行以下命令安装 WsTranscription SDK 及其依赖项。
npm install @coze/api
在项目中导入 WsTranscription SDK 提供的模块,包括工具类、客户端类以及事件类型等。
import {
WsToolsUtils,
WsTranscriptionClient,
AIDenoiserProcessorMode,
AIDenoiserProcessorLevel,
} from '@coze/api/ws-tools';
import {
CommonErrorEvent,
TranscriptionsMessageUpdateEvent,
WebsocketsEventType,
} from '@coze/api';
在使用语音识别功能前,先检查并获取麦克风访问权限。调用WsToolsUtils.checkDevicePermission() 方法,检查浏览器是否已授予麦克风权限。
在 HTTPS 或 localhost 中执行该方法。首次调用时,浏览器会向用户显示权限请求对话框,如果用户拒绝麦克风权限,在应用中提供明确指引,告知用户如何在浏览器设置中启用权限。在 iOS Safari 浏览器中,必须由用户交互操作(如点击按钮)触发权限请求。
import { WsToolsUtils } from "@coze/api/ws-tools";
const checkPermission = async () => {
const permission = await WsToolsUtils.checkDevicePermission();
if (!permission.audio) {
throw new Error("麦克风权限未授予");
}
};
调用 new WsTranscriptionClient 方法创建 WsTranscriptionClient 实例,配置 token 等参数以连接到服务。
import {
AIDenoiserProcessorLevel,
AIDenoiserProcessorMode,
WsTranscriptionClient,
} from '@coze/api/ws-tools';
const initClient = async () => {
// 确保麦克风权限已授予
checkPermission();
// 创建新的转录客户端
const client = new WsTranscriptionClient({
token: 'pat_Qm47PKJR5dvMOP53v6DyzwCbTtvEZHQc2TVINEveg9v1T3iSYlTdScJ8***', // 替换为您的个人访问令牌
allowPersonalAccessTokenInBrowser: true,
// 可选:AI降噪配置
aiDenoisingConfig: {
mode: AIDenoiserProcessorMode.NSNG, // 'NSNG'(AI降噪)或'STATIONARY_NS'(稳态噪声抑制)
level: AIDenoiserProcessorLevel.SOFT, // 'SOFT'(推荐)或'AGGRESSIVE'(激进)
},
// 可选:调试模式
debug: true,
});
return client;
};
参数说明:
说明
扣子 SDK 封装了多种鉴权方式,能够有效简化鉴权流程,你可以参考鉴权示例代码实现不同方式的 OAuth 认证,以获取和管理访问扣子 API 所需的令牌
在初始化后注册事件监听器,以便处理语音识别过程中的各种事件。详细的事件说明请参见双向流式语音识别事件。
import {
TranscriptionsMessageUpdateEvent,
WebsocketsEventType,
} from '@coze/api';
import { WsTranscriptionClient } from '@coze/api/ws-tools';
const setupListeners = (client: WsTranscriptionClient) => {
// 监听识别结果
client.on(
WebsocketsEventType.TRANSCRIPTIONS_MESSAGE_UPDATE,
(event: unknown) => {
const transcriptionText = (event as TranscriptionsMessageUpdateEvent).data
.content;
console.log('识别结果:', transcriptionText);
// 更新您的UI
},
);
// 监听错误
client.on(WebsocketsEventType.ERROR, (error: unknown) => {
console.error('错误:', error);
// 适当处理错误
});
// 可选:监听所有事件进行调试
client.on(WebsocketsEventType.ALL, (event: unknown) => {
console.debug('收到事件:', event);
});
};
你可以管理语音识别的状态,包括开始、暂停、恢复和停止录音。
start 接口开始录音和语音识别,调用后会立即开始采集音频并进行语音识别。说明
start 方法之前完成所有事件监听的注册。stop 接口停止录音和语音识别,调用后会结束当前会话。停止录音后如需重新开始录音,需要重新调用 start 方法。pause 或 resume 接口暂停或恢复录音。暂停期间会保持会话连接状态,但不会产生新的转录结果。import { WsTranscriptionClient } from '@coze/api/ws-tools';
// 开始识别
const startRecording = async (client: WsTranscriptionClient) => {
try {
await client.start();
console.log('开始识别');
// 更新您的UI以显示录音状态
} catch (error) {
console.error('开始识别失败:', error);
}
};
// 停止录音和转录
const stopRecording = (client: WsTranscriptionClient) => {
try {
client.stop();
console.log('停止识别');
// 更新您的UI以显示停止状态
} catch (error) {
console.error('停止识别失败:', error);
}
};
// 暂停录音(保持上下文)
const pauseRecording = (client: WsTranscriptionClient) => {
try {
client.pause();
console.log('暂停识别');
// 更新您的UI以显示暂停状态
} catch (error) {
console.error('暂停识别失败:', error);
}
};
// 恢复已暂停的录音
const resumeRecording = (client: WsTranscriptionClient) => {
try {
client.resume();
console.log('恢复识别');
// 更新您的UI以显示识别状态
} catch (error) {
console.error('恢复识别失败:', error);
}
};
在组件卸载或不再需要语音识别功能时,调用 destory 方法断开连接,清理资源,以避免潜在的内存泄漏或其他资源占用问题。
// 使用完客户端后
client.destroy();
在初始化客户端时,你还可以进行高级配置,以满足不同的开发需求,包括配置音频采集、AI降噪、调试模式等。
interface WsTranscriptionClientOptions {
// 必填项
token: GetToken; // Personal Access Token (PAT) 或 OAuth2.0 token,或获取 token 的函数
// 选填项
debug?: boolean; // 是否启用调试模式
headers?: Headers | Record<string, unknown>; // 自定义请求头
allowPersonalAccessTokenInBrowser?: boolean; // 是否允许在浏览器环境中使用个人访问令牌
baseWsURL?: string; // WebSocket 基础 URL,默认为 wss://ws.coze.cn
websocketOptions?: WebsocketOptions; // WebSocket 配置选项
deviceId?: string; // 音频输入设备 ID
// 音频相关配置
audioCaptureConfig?: {
noiseSuppression?: boolean; // 是否启用降噪
echoCancellation?: boolean; // 是否启用回声消除
autoGainControl?: boolean; // 是否启用自动增益控制
};
// AI 降噪配置
aiDenoisingConfig?: {
mode?: AIDenoiserProcessorMode; // AI 降噪模式:NSNG(非平稳噪声抑制) 或 STATIONARY_NS(平稳噪声抑制)
level?: AIDenoiserProcessorLevel; // 降噪级别
assetsPath?: string; // AI 降噪 wasm 文件路径,默认为 '/external'
};
// 自定义音频流
mediaStreamTrack?: MediaStreamTrack;
// 音频录制配置(仅在 debug = true 时生效)
wavRecordConfig?: {
enableSourceRecord: boolean; // 是否启用源音频录制
enableDenoiseRecord: boolean; // 是否启用降噪后音频录制
};
}
你可以通过 WsToolsUtils.getAudioDevices 方法获取系统的音频输入和输出设备列表,返回的设备列表包含每个设备的 deviceId 和 label 信息。
// 获取音频设备列表
const devices = await WsToolsUtils.getAudioDevices()
const audioInputs = devices.audioInputs
const deviceId = audioInputs[0].deviceId
说明
getAudioDevices 之前,确保已获得用户的麦克风权限。配置 AI 降噪的步骤如下:
WsToolsUtils.checkDenoiserSupport() 方法检查。import { AIDenoiserProcessorLevel, AIDenoiserProcessorMode, WsToolsUtils } from "@coze/api/ws-tools";
//检查浏览器是否支持 AI 降噪
const isDenoiserSupported = WsToolsUtils.checkDenoiserSupport();
console.log("支持AI降噪:", isDenoiserSupported);
// 启用/禁用降噪器
client.setDenoiserEnabled(true);
// 更改降噪模式(NSNG或STATIONARY_NS)
client.setDenoiserMode(AIDenoiserProcessorMode.NSNG);
// 更改降噪级别(SOFT或AGGRESSIVE)
client.setDenoiserLevel(AIDenoiserProcessorLevel.SOFT);
通过监听 getStatus中的状态回调,你可以管理语音识别客户端的运行状态。根据不同的状态,你可以执行相应的业务逻辑。建议在状态发生变化时,及时更新用户界面,以提供更直观的交互体验。
const status = client.getStatus(); // 'recording', 'paused'或'ended'
console.log("当前状态:", status);
客户端的运行状态包括: