@amaster.ai/asr-client
v1.1.1
Published
Qwen ASR Realtime WebSocket client with microphone recording
Downloads
4,370
Readme
ASR Realtime WebSocket Client SDK
基于 Web Audio + WebSocket 的 实时语音识别(ASR)客户端 SDK,用于将浏览器麦克风音频实时发送到 ASR 服务(如 Qwen ASR Realtime),并接收实时/最终转写结果。
遵循 Qwen-ASR Realtime API 协议实现,完整支持会话管理、VAD 模式、手动模式等全部功能。
特性
- 🎙 浏览器麦克风实时采集(16kHz / 单声道)
- 🔁 实时音频流式发送(Base64 PCM16)
- 🧠 支持 VAD 模式(自动检测语音开始/结束)和 Manual 模式(手动控制)
- 🌍 支持 25 种语言识别
- ✍️ 支持中间结果与最终转写结果
- 📡 完整的会话生命周期管理(session.update、session.finish)
- 🔌 事件 ID 自动生成,符合协议规范
- 🌐 同时支持 WebSocket 实时识别和 HTTP 按压识别
安装与环境要求
安装
# npm
npm install @amaster.ai/asr-client
# pnpm
pnpm add @amaster.ai/asr-client
# yarn
yarn add @amaster.ai/asr-client浏览器要求
- 支持
getUserMedia - 支持
AudioContext - 支持
WebSocket
推荐使用 Chrome / Edge 最新版本。
快速开始
方式一:WebSocket 实时 ASR(流式识别)
适合需要实时看到识别结果的场景,如语音输入、实时字幕等。
VAD 模式(推荐)
自动检测语音开始和结束:
import { createASRClient } from "@amaster.ai/asr-client";
const client = createASRClient({
// 语言配置
language: "zh", // 支持 zh、yue、en、ja 等 25 种语言
// VAD 配置(自动检测语音)
enableVAD: true,
vadThreshold: 0.0, // 推荐设为 0.0,默认 0.2
vadSilenceDurationMs: 400, // 推荐设为 400ms,默认 800ms
// 回调函数
onReady() {
console.log("ASR 连接成功,会话已配置");
},
onSpeechStart() {
console.log("🎤 检测到说话开始");
},
onSpeechEnd() {
console.log("🛑 检测到说话结束");
},
onTranscript(text, isFinal) {
console.log(isFinal ? "✅ 最终结果:" : "📝 实时结果:", text);
},
onSessionFinished() {
console.log("👋 会话已结束");
},
onError(err) {
console.error("❌ ASR 错误", err);
},
onClose() {
console.log("🔌 连接已关闭");
},
});
// 1. 建立连接(自动发送 session.update)
await client.connect();
// 2. 开始录音
await client.startRecording();
// 3. 停止录音(VAD 模式下可选,会自动检测结束)
await client.stopRecording();
// 4. 关闭连接(自动发送 session.finish)
await client.close();Manual 模式(非 VAD)
手动控制识别时机,适合按住说话、松开识别的场景:
const client = createASRClient({
language: "zh",
enableVAD: false, // 关闭 VAD,使用手动模式
onReady() {
console.log("准备就绪");
},
onTranscript(text, isFinal) {
if (isFinal) {
console.log("识别结果:", text);
}
},
onAudioBufferCommitted() {
console.log("音频已提交,等待识别结果...");
},
});
await client.connect();
await client.startRecording();
// 用户说话中...
await client.stopRecording(); // 触发 input_audio_buffer.commit方式二:HTTP 按压式 ASR(一句话识别)
适合按住说话、松开识别的场景,如语音消息、语音搜索等。
import { useRef, useState } from "react";
import { createASRHttpClient } from "@amaster.ai/asr-client";
function VoiceButton() {
const [recording, setRecording] = useState(false);
const [text, setText] = useState("");
const [error, setError] = useState<string | null>(null);
// 创建 HTTP ASR 客户端
const asrHttpClient = useRef(
createASRHttpClient({
onRecordingStart() {
setRecording(true);
setText("");
setError(null);
},
onRecordingStop() {
setRecording(false);
},
onResult(result) {
setText(result);
},
onError(err) {
setError(err.message);
},
})
).current;
return (
<div>
<button
onMouseDown={() => asrHttpClient.startRecording()}
onMouseUp={() => asrHttpClient.stopRecording()}
onTouchStart={() => asrHttpClient.startRecording()}
onTouchEnd={() => asrHttpClient.stopRecording()}
style={{
padding: "12px 24px",
background: recording ? "#f87171" : "#4ade80",
}}
>
{recording ? "松开识别" : "按住说话"}
</button>
<div>
<strong>识别结果:</strong>
<div>{text || "(暂无)"}</div>
</div>
{error && <div style={{ color: "red" }}>错误:{error}</div>}
</div>
);
}API 说明
createASRClient(config): ASRClient
WebSocket 实时 ASR 客户端。
ASRClientConfig
| 参数 | 类型 | 默认值 | 说明 |
| ------------------------ | ------------------------------------------ | ------- | -------------------------------------------------------- |
| audioFormat | "pcm" \| "opus" | "pcm" | 音频格式 |
| sampleRate | 16000 \| 8000 | 16000 | 采样率。8000 会先升采样到 16000,可能引入微小延迟 |
| language | ASRLanguage | "zh" | 音频源语言,支持 25 种语言(见下方语言列表) |
| enableVAD | boolean | true | 是否启用 VAD 模式。true=自动检测,false=手动控制 |
| vadThreshold | number | 0.2 | VAD 检测阈值,推荐设为 0.0,范围 [-1, 1] |
| vadSilenceDurationMs | number | 800 | VAD 断句检测阈值(ms),推荐设为 400,范围 [200, 6000] |
| getAccessToken | () => string \| null | - | 获取访问令牌(用于 WebSocket 认证) |
| onReady | () => void | - | 会话创建并配置完成(收到 session.updated) |
| onSpeechStart | () => void | - | 检测到语音开始(VAD 模式) |
| onSpeechEnd | () => void | - | 检测到语音结束(VAD 模式) |
| onTranscript | (text: string, isFinal: boolean) => void | - | 转写回调,isFinal 表示是否为最终结果 |
| onAudioBufferCommitted | () => void | - | 音频缓冲区已提交(非 VAD 模式) |
| onSessionFinished | () => void | - | 会话已结束(收到 session.finished) |
| onError | (error: Error) => void | - | 错误回调 |
| onClose | () => void | - | 连接关闭回调 |
支持的语言 (ASRLanguage)
| 代码 | 语言 | 代码 | 语言 |
| ----- | ------------------------------------ | ---- | -------- |
| zh | 中文(普通话、四川话、闽南语、吴语) | it | 意大利语 |
| yue | 粤语 | es | 西班牙语 |
| en | 英文 | hi | 印地语 |
| ja | 日语 | id | 印尼语 |
| de | 德语 | th | 泰语 |
| ko | 韩语 | tr | 土耳其语 |
| ru | 俄语 | uk | 乌克兰语 |
| fr | 法语 | vi | 越南语 |
| pt | 葡萄牙语 | cs | 捷克语 |
| ar | 阿拉伯语 | da | 丹麦语 |
| fil | 菲律宾语 | fi | 芬兰语 |
| is | 冰岛语 | ms | 马来语 |
| no | 挪威语 | pl | 波兰语 |
| sv | 瑞典语 | | |
ASRClient
interface ASRClient {
/** 建立 WebSocket 连接并发送 session.update */
connect(): Promise<void>;
/** 开始录音并流式发送音频 */
startRecording(): Promise<void>;
/**
* 停止录音
* - VAD 模式:停止发送音频
* - 非 VAD 模式:停止发送音频并触发识别(发送 input_audio_buffer.commit)
*/
stopRecording(): Promise<void>;
/**
* 关闭连接
* - 发送 session.finish
* - 等待 session.finished
* - 关闭 WebSocket
*/
close(): Promise<void>;
/** 是否正在录音 */
isRecording(): boolean;
/** 是否已连接到服务器 */
isConnected(): boolean;
}createASRHttpClient(config): ASRHttpClient
HTTP 按压式 ASR 客户端。
ASRHttpClientConfig
| 参数 | 类型 | 说明 |
| ------------------ | ------------------------ | -------------------- |
| getAccessToken | () => string \| null | 获取访问令牌 |
| language | string | 语言,默认 'zh' |
| sampleRate | number | 采样率,默认 16000 |
| onRecordingStart | () => void | 录音开始回调 |
| onRecordingStop | () => void | 录音停止回调 |
| onResult | (text: string) => void | 识别结果回调 |
| onError | (error: Error) => void | 错误回调 |
ASRHttpClient
interface ASRHttpClient {
startRecording(): Promise<void>; // 开始录音
stopRecording(): Promise<string>; // 停止录音并返回识别结果
recordAndRecognize(durationMs: number): Promise<string>; // 录音指定时长
recognizeFile(file: File | Blob): Promise<string>; // 识别音频文件
recognizeUrl(audioUrl: string): Promise<string>; // 识别音频 URL
}配合统一客户端使用
推荐与 @amaster.ai/client 统一客户端一起使用,自动处理认证:
import { createClient } from "@amaster.ai/client";
const client = createClient({
baseURL: "https://api.amaster.ai",
});
// WebSocket ASR
const asrClient = client.asr({
onTranscript(text, isFinal) {
console.log(isFinal ? "[最终]" : "[实时]", text);
},
});
await asrClient.connect();
await asrClient.startRecording();
// HTTP ASR
const asrHttpClient = client.asrHttp({
onResult(text) {
console.log("识别结果:", text);
},
});
await asrHttpClient.startRecording();
// ... 用户说话 ...
const result = await asrHttpClient.stopRecording();VAD 模式 vs Manual 模式
| 特性 | VAD 模式(enableVAD: true) | Manual 模式(enableVAD: false) |
| -------- | -------------------------------------- | ------------------------------- |
| 语音检测 | 服务端自动检测 | 客户端手动控制 |
| 适用场景 | 连续对话、实时字幕 | 按住说话、语音消息 |
| 开始录音 | startRecording() | startRecording() |
| 停止录音 | 自动检测 / stopRecording() | stopRecording() 触发识别 |
| 事件触发 | onSpeechStart / onSpeechEnd | onAudioBufferCommitted |
| 配置参数 | vadThreshold, vadSilenceDurationMs | 无需 VAD 配置 |
VAD 配置建议
// 快速响应场景(如实时字幕)
const client = createASRClient({
enableVAD: true,
vadThreshold: 0.0, // 最灵敏
vadSilenceDurationMs: 400, // 较短停顿即断句
});
// 长句输入场景(如文章朗读)
const client = createASRClient({
enableVAD: true,
vadThreshold: 0.2, // 默认灵敏度
vadSilenceDurationMs: 1200, // 较长停顿才断句
});音频参数说明
WebSocket ASR
- 采样率:16000 Hz(推荐)或 8000 Hz
- 声道:单声道
- 格式:PCM16 → Base64
- 缓冲大小:4096 frames
HTTP ASR
- 采样率:自动检测(通常为 16000 Hz)
- 声道:单声道
- 格式:WAV(内部将 PCM 转为 WAV)
常见问题
Q: WebSocket 和 HTTP ASR 有什么区别?
| 特性 | WebSocket ASR | HTTP ASR | | -------- | ---------------------- | ------------------- | | 实时性 | 实时流式返回 | 说完后一次性返回 | | 适用场景 | 语音输入、实时字幕 | 语音消息、语音搜索 | | 交互方式 | 开始 → 持续识别 → 停止 | 按住说话 → 松开识别 | | 网络开销 | 持续连接 | 每次请求独立 |
Q: 为什么必须是 16kHz?
ASR 服务通常要求 16kHz PCM 输入,否则会影响识别效果或直接报错。
Q: 支持移动端吗?
支持,但需注意:
- iOS Safari 需用户手势触发录音
- 后台会自动暂停音频采集
Q: VAD 模式下为什么要等一段时间才返回最终结果?
VAD 需要检测到静音(silence)才会认为一句话结束,然后返回最终结果。vadSilenceDurationMs 配置了这个静音时长阈值。
Q: 如何切换语言?
const client = createASRClient({
language: "en", // 英文识别
});注意事项
- WebSocket 必须在 HTTPS 页面下使用麦克风
- 页面关闭前建议调用
await client.close()优雅关闭 - 不建议在多个 ASR Client 实例中共享麦克风
- HTTP ASR 会自动将录音转为 WAV 格式上传
- 每个事件都会自动生成唯一的
event_id,符合协议规范
License
MIT
