Speech Seaco Paraformer ASR实战教程:实时录音功能调用代码实例
1. 模型与工具简介
1.1 Speech Seaco Paraformer 是什么
Speech Seaco Paraformer 是基于阿里 FunASR 框架构建的中文语音识别模型,由开发者“科哥”完成 WebUI 封装与工程化适配。它不是简单套壳,而是针对中文场景深度优化的开箱即用方案——支持热词定制、高精度识别、低延迟响应,且完全本地运行,不依赖云端 API。
它底层调用的是 ModelScope 上开源的Linly-Talker/speech_seaco_paraformer_large_asr_nat-zh-cn-16k-common-vocab8404-pytorch模型,该模型在 AISHELL-1、GigaSpeech 中文子集等基准上达到 96%+ 的字准确率(CER),尤其对带口音、语速快、含专业术语的日常中文语音表现稳健。
你不需要懂模型结构,也不用配环境——它已打包为 Docker 镜像或一键脚本,真正实现“下载即用”。
1.2 为什么重点讲「实时录音」功能
其他功能(如单文件识别、批量处理)本质是“离线转写”,而实时录音是唯一能体现 ASR 系统交互感与工程价值的功能:
- 它直连浏览器麦克风,绕过音频文件中转;
- 它在前端完成音频采集、分段、上传、后端识别、流式返回的闭环;
- 它对延迟敏感,考验整个链路的稳定性与资源调度能力;
- 它最贴近真实需求:会议速记、课堂记录、语音输入法、无障碍辅助等场景都依赖这一能力。
本教程不讲理论推导,只聚焦一件事:如何把 WebUI 里的「实时录音」功能,变成你自己的 Python 脚本可调用的能力。你会看到从浏览器按钮点击,到后台 API 请求,再到结果解析的完整链路。
2. 环境准备与服务启动
2.1 快速启动服务(30秒完成)
确保你已部署好 Speech Seaco Paraformer WebUI(通常为 Docker 容器或本地 Python 服务)。若尚未运行,请执行:
/bin/bash /root/run.sh该脚本会自动拉起 Gradio WebUI 服务,默认监听http://localhost:7860。
等待终端输出类似以下日志,即表示服务就绪:
Running on local URL: http://localhost:7860 To create a public link, set `share=True` in `launch()`.验证方式:打开浏览器访问
http://localhost:7860,能看到四个 Tab 标签页(🎤单文件识别、批量处理、🎙实时录音、⚙系统信息),说明服务正常。
2.2 理解 WebUI 的通信机制
Speech Seaco Paraformer 使用 Gradio 构建前端界面,其所有功能均通过HTTP POST 请求调用后端 API 接口。Gradio 默认将每个组件(如按钮、输入框、输出框)映射为一个独立的 API 端点。
我们重点关注「实时录音」Tab 中的两个核心操作:
- 开始录音并获取音频数据→ 前端 JavaScript 控制
<audio>元素 +MediaRecorderAPI; - 上传音频并触发识别→ 点击「 识别录音」时,前端将录音生成的 Blob 数据以
multipart/form-data方式提交至/run/predict。
但注意:WebUI 本身不暴露 RESTful API 文档。我们需要逆向分析其请求行为,才能复现逻辑。
3. 实时录音功能的 API 逆向与调用
3.1 抓包分析:看清浏览器在做什么
打开 Chrome 浏览器,访问http://localhost:7860,切换到「🎙 实时录音」Tab。
按F12打开开发者工具 → 切换到Network(网络)标签页→ 勾选Preserve log(保留日志)。
然后执行一次完整流程:
- 点击麦克风按钮 → 开始录音(此时无网络请求);
- 再次点击麦克风按钮 → 停止录音(仍无请求);
- 点击「 识别录音」→ 此刻 Network 面板会出现一条
POST /run/predict请求。
点击该请求 → 查看Headers和Payload:
- Request URL:
http://localhost:7860/run/predict - Request Method:
POST - Content-Type:
multipart/form-data; boundary=----WebKitFormBoundary... - Form Data包含三个关键字段:
data[0]:null(占位,对应第一个输入组件)data[1]:null(占位,对应第二个输入组件)data[2]: 二进制音频文件(blob.wav,类型audio/wav)
关键发现:
data[2]是真正的音频数据,且文件名固定为blob.wav,格式为标准 WAV(16-bit PCM,16kHz 单声道)。
3.2 构建 Python 调用脚本:脱离浏览器,自主录音识别
我们不再依赖浏览器录音,而是用 Python 自主完成:
- 使用
pyaudio录制麦克风音频; - 保存为符合要求的 WAV 文件(16kHz,单声道,16-bit);
- 构造 multipart/form-data 请求,调用
/run/predict; - 解析返回 JSON,提取识别文本。
安装依赖(仅需一次)
pip install pyaudio requests numpy完整可运行代码(复制即用)
# real_time_asr_cli.py import pyaudio import wave import requests import json import os import numpy as np # === 参数配置 === RECORD_SECONDS = 5 # 录音时长(秒),建议 3~8 秒 OUTPUT_FILENAME = "temp_recording.wav" API_URL = "http://localhost:7860/run/predict" # === 录音函数 === def record_audio(filename, seconds=5): """使用 PyAudio 录制指定时长的 WAV 音频""" CHUNK = 1024 FORMAT = pyaudio.paInt16 # 16-bit CHANNELS = 1 # 单声道 RATE = 16000 # 16kHz p = pyaudio.PyAudio() print(f"🎤 正在录音 {seconds} 秒...(请开始说话)") stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) frames = [] for _ in range(0, int(RATE / CHUNK * seconds)): data = stream.read(CHUNK) frames.append(data) stream.stop_stream() stream.close() p.terminate() # 保存为 WAV wf = wave.open(filename, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close() print(f" 录音完成,已保存为 {filename}") return filename # === 发送识别请求 === def send_to_asr_api(wav_path): """将 WAV 文件发送至 Speech Seaco Paraformer API""" # 构造 multipart/form-data with open(wav_path, "rb") as f: files = { "data": (None, json.dumps([None, None, None])), # 对应三个输入组件 "files": (os.path.basename(wav_path), f, "audio/wav") } try: response = requests.post( API_URL, files=files, timeout=30 ) response.raise_for_status() result = response.json() # 解析返回结构:result["data"][0] 是识别文本 if "data" in result and len(result["data"]) > 0: text = result["data"][0] if isinstance(text, str) and text.strip(): return text.strip() else: return "[识别失败:返回非文本内容]" else: return "[识别失败:API 返回格式异常]" except requests.exceptions.RequestException as e: return f"[请求错误] {str(e)}" except json.JSONDecodeError: return "[解析错误] API 返回非 JSON 内容" except Exception as e: return f"[未知错误] {str(e)}" # === 主流程 === if __name__ == "__main__": # 步骤1:录音 wav_file = record_audio(OUTPUT_FILENAME, RECORD_SECONDS) # 步骤2:调用 ASR print(" 正在发送至语音识别服务...") result_text = send_to_asr_api(wav_file) # 步骤3:输出结果 print("\n" + "="*50) print(" 识别结果:") print(result_text) print("="*50) # 清理临时文件 if os.path.exists(wav_file): os.remove(wav_file) print(f"🗑 临时文件 {wav_file} 已清理")运行效果示例
🎤 正在录音 5 秒...(请开始说话) 录音完成,已保存为 temp_recording.wav 正在发送至语音识别服务... ================================================== 识别结果: 今天天气不错,我们一起去公园散步吧 ================================================== 🗑 临时文件 temp_recording.wav 已清理该脚本完全脱离浏览器,可在服务器后台、自动化任务、嵌入式设备中直接运行。你只需修改
RECORD_SECONDS和API_URL,即可适配不同场景。
4. 进阶技巧:提升实时识别体验
4.1 添加热词支持(Python 脚本版)
WebUI 的热词功能通过data[1]字段传递。我们只需在files中补充data字段:
# 修改 send_to_asr_api 函数中的 files 构造部分: hotwords = "人工智能,语音识别,科哥,Paraformer" # 自定义热词,逗号分隔 files = { "data": (None, json.dumps([None, hotwords, None])), "files": (os.path.basename(wav_path), f, "audio/wav") }效果:当你说“我要用 Paraformer 做语音识别”,模型更倾向将“Paraformer”识别为专有名词,而非“怕拉佛玛”。
4.2 实现连续录音识别(类语音助手)
想让程序持续监听、自动切分、逐段识别?只需加个循环和静音检测:
# 伪代码示意(需引入 webrtcvad 或 simpleaudio 做 VAD) while True: audio_data = record_until_silence(timeout=10) # 录到静音为止 if len(audio_data) > 16000: # 至少1秒有效音频 save_as_wav(audio_data, "chunk.wav") text = send_to_asr_api("chunk.wav") print("🗣", text) if "退出" in text or "停止" in text: break这已具备基础语音助手雏形,无需额外模型,纯靠现有 ASR + 规则判断。
4.3 错误处理与重试策略
生产环境中,网络抖动、服务重启可能导致请求失败。建议加入指数退避重试:
import time from functools import wraps def retry_on_failure(max_retries=3, delay=1): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for i in range(max_retries): try: return func(*args, **kwargs) except Exception as e: if i == max_retries - 1: raise e wait = delay * (2 ** i) print(f" 请求失败,{wait}秒后重试... ({i+1}/{max_retries})") time.sleep(wait) return None return wrapper return decorator @retry_on_failure(max_retries=2, delay=0.5) def send_to_asr_api(wav_path): # 原函数体保持不变 ...5. 常见问题与调试指南
5.1 为什么识别结果为空或报错?
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
返回{"error": "...", "success": false} | 后端模型未加载完成 | 等待run.sh启动日志中出现Model loaded提示后再调用 |
返回{"data": [null]} | data[2]未正确传入音频 | 检查files字典中"files"键是否指向真实 WAV 文件,且 MIME 类型为audio/wav |
| 识别文本乱码或极短 | 音频采样率非 16kHz 或非单声道 | 用sox temp_recording.wav -r 16000 -c 1 fixed.wav转换格式 |
| 请求超时(timeout) | 服务卡顿或显存不足 | 降低RECORD_SECONDS,或升级 GPU 显存 |
5.2 如何验证音频格式是否合规?
用 Python 快速检查:
import wave w = wave.open("temp_recording.wav", "rb") print(f"通道数: {w.getnchannels()}, 采样率: {w.getframerate()}, 位深: {w.getsampwidth()*8}bit") # 应输出:通道数: 1, 采样率: 16000, 位深: 16bit5.3 能否不用 PyAudio?用系统命令录音?
当然可以。Linux 下可用arecord:
import subprocess subprocess.run([ "arecord", "-d", "5", "-r", "16000", "-c", "1", "-f", "S16_LE", "temp.wav" ])Windows 下可用SoundRecorder.exe或ffmpeg,原理一致:只要最终生成标准 WAV,API 就能识别。
6. 总结
6.1 你已掌握的核心能力
- 理解 Speech Seaco Paraformer WebUI 的底层通信逻辑;
- 独立编写 Python 脚本,绕过浏览器,直接调用实时录音识别 API;
- 在脚本中集成热词、错误重试、音频格式校验等工程化能力;
- 具备向连续语音识别、语音助手方向延伸的技术基础。
这不是一个“调用 API”的教程,而是一次从用户到开发者视角的跃迁——你不再只是点击按钮的人,而是能拆解、复用、改造整个语音识别工作流的实践者。
6.2 下一步建议
- 尝试将本脚本封装为 CLI 工具:
asr-cli --record 8 --hotword "AI,大模型"; - 结合
whisper.cpp或funasr原生 Python SDK,对比识别效果与速度; - 将识别结果接入 RAG 系统,实现“语音提问 → 文档检索 → 语音回答”闭环。
语音识别的价值,不在技术本身,而在它如何自然地融入你的工作流。现在,你已经拿到了那把钥匙。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。