助手
扣子 AI 帮助与支持
你好,我是 扣子 文档问答助手 🎉 你在阅读当前文档的过程中,无论对文档概念的解释,还是文档内容方面的疑问,都可以随时向我提问,我会全力为你解答
推荐问题
如何快速了解这个空间的核心内容?
有哪些近期更新的重点文档?
我应该从哪些文档开始阅读?
文档反馈
低代码项目
快速开始
智能体
工作流
应用
资源
发布
模型
多人协作
推广与变现

集成语音识别 SDK

更新于: 2026-06-25 19:29:14

语音识别 SDK(简称 WsTranscription SDK)是基于双向流式语音识别 WebSocket OpenAPI 封装的软件开发工具包。它为开发者提供了一套高效且完整的语音交互解决方案,可快速集成至各类应用程序,实现高质量的语音识别功能。扣子提供 Demo 和示例项目源码,助力开发者迅速掌握并应用。更多接口详情请参考双向流式语音识别

体验 Demo

扣子提供语音识别 Demo 和 TypeScript 格式的语音识别示例源码 ,帮助你快速体验语音识别的功能,并根据示例源码快速实现语音识别。

Demo 功能简介

Demo 的主要功能包括:

  • 实时语音转录
  • AI 智能降噪
  • 选择音频输入设备
  • 录音控制,包括开始录音、暂停和恢复录音、停止录音
  • 错误处理

Image

使用 Demo

  1. 配置参数。
    单击右上角的 Settings,配置个人访问令牌,具体如下表所示。
    配置 说明
    Base WS URL 保持默认值 wss://ws.coze.cn

    个人访问令牌

    扣子 API & SDK 通过访问令牌进行 API & SDK 请求的鉴权。

    个人访问令牌的获取方式可参考添加个人访问令牌

    说明

    应为令牌授予 createTranscription 的权限。

  2. 单击开始录音,在识别结果中会将浏览器采集的音频进行语音识别并转为文字。

完整示例代码

以下是基于 React 和 Antd 框架开发的语音识别示例代码,包含用户界面、状态管理和错误处理等功能,帮助你快速了解语音识别的实现流程。

使用前需配置个人访问令牌(ACCESS_TOKEN),并安装@coze/apiantdreact 等依赖,建议开发时开启调试模式。

该示例代码中包含如下功能:

  • 基础功能:实时语音转录、录音控制(开始/暂停/恢复/停止)、状态显示和错误处理、AI降噪检测。
  • 界面组件:前置条件检查面板、录音控制面板、实时转录结果显示、使用说明。
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;
};

参数说明:

  • token:访问密钥,用于身份认证与鉴权。体验或调试场景可以生成短期的个人访问令牌(PAT),以快速完成 WsChat SDK 的整体流程。个人访问令牌的获取方法请参见添加个人访问令牌。在线上环境中,应使用服务访问令牌(SAT)或 OAuth 鉴权方案,详细说明请参见鉴权方式概述

    说明

    扣子 SDK 封装了多种鉴权方式,能够有效简化鉴权流程,你可以参考鉴权示例代码实现不同方式的 OAuth 认证,以获取和管理访问扣子 API 所需的令牌

  • allowPersonalAccessTokenInBrowser:在浏览器环境中使用个人访问令牌时,必须设置为 true。
  • debug:启用调试日志,便于开发和测试阶段的问题排查。

步骤五:注册事件监听

在初始化后注册事件监听器,以便处理语音识别过程中的各种事件。详细的事件说明请参见双向流式语音识别事件

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 方法。
  • 暂停和恢复录音:调用 pauseresume 接口暂停或恢复录音。暂停期间会保持会话连接状态,但不会产生新的转录结果。
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 降噪

配置 AI 降噪的步骤如下:

  1. 检查浏览器是否支持 AI 降噪。
    某些浏览器或设备可能不支持全部降噪功能,当不确定设备支持情况时,可以使用 WsToolsUtils.checkDenoiserSupport() 方法检查。
  2. 开启或关闭降噪,设置降噪的等级和模式。
    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);

客户端的运行状态包括:

  • recording:录音中
  • paused:已暂停
  • ended:已结束