零基础教程:手把手教你用SenseVoice-Small搭建语音转文字服务
零基础教程:手把手教你用SenseVoice-Small搭建语音转文字服务
1. 引言:为什么你需要一个自己的语音识别服务?
想象一下这个场景:你刚刚结束了一场重要的线上会议,需要把长达一小时的讨论内容整理成文字纪要。手动听写?太耗时了。用第三方在线工具?又担心隐私泄露。这时候,如果你有一个部署在自己服务器上的语音识别服务,一切就变得简单了。
今天,我要带你从零开始,搭建一个属于你自己的、支持多语言的语音转文字服务。我们将使用的核心是SenseVoice-Small模型,一个基于ONNX量化、轻量高效的语音识别引擎。它不仅能识别中文、英文,还支持粤语、日语和韩语,甚至能自动检测超过50种语言。
这个教程的目标很简单:让你在30分钟内,拥有一个可以处理日常音频转录的私有化服务。无论你是开发者、学生,还是对AI技术感兴趣的爱好者,都不需要深厚的机器学习背景,跟着步骤走就能成功。
2. 准备工作:环境与工具
在开始动手之前,我们需要确保你的电脑或服务器环境已经就绪。整个过程就像搭积木,先把需要的“积木块”准备好。
2.1 系统要求
首先,确认你的操作系统。本教程主要基于Linux系统(如 Ubuntu 20.04/22.04)或macOS进行,Windows用户可以通过WSL2获得类似的Linux环境。以下是基本要求:
- 操作系统:Linux (推荐 Ubuntu 20.04+) 或 macOS
- Python版本:Python 3.8 或更高版本
- 内存:至少 2GB 可用内存(模型本身很小,约230MB)
- 磁盘空间:预留约 1GB 空间用于安装依赖和模型
2.2 安装Python与包管理工具
如果你的系统还没有Python,需要先安装它。打开终端,输入以下命令检查:
python3 --version pip3 --version如果显示了版本号(如 Python 3.8.10),说明已经安装。如果没有,请根据你的操作系统搜索“如何安装Python 3.8”进行安装。
接下来,我们创建一个独立的Python虚拟环境。这是一个好习惯,可以避免不同项目的依赖包互相冲突。
# 安装虚拟环境工具(如果尚未安装) sudo apt-get install python3-venv # Ubuntu/Debian # 或者 brew install python@3.8 # macOS # 创建一个名为‘sensevoice-env’的虚拟环境 python3 -m venv sensevoice-env # 激活虚拟环境 # Linux/macOS: source sensevoice-env/bin/activate # 激活后,你的命令行提示符前通常会显示 (sensevoice-env)看到(sensevoice-env)出现在命令行开头,就说明虚拟环境激活成功了。接下来所有的操作都在这个环境里进行。
3. 三步搭建:部署你的语音识别服务
环境准备好了,现在进入核心的搭建环节。整个过程可以概括为三步:安装依赖、启动服务、访问测试。
3.1 第一步:安装必要的软件包
我们需要安装运行SenseVoice-Small服务所需的所有Python库。这些库包括模型推理框架、Web服务框架和音频处理工具。
在激活的虚拟环境中,一次性执行下面的安装命令:
pip install funasr-onnx gradio fastapi uvicorn soundfile jieba简单解释一下这几个包的作用:
funasr-onnx: 这是运行SenseVoice模型的核心推理库。gradio和fastapi: 用来构建Web界面和API服务的框架。uvicorn: 一个轻量级的ASGI服务器,用于运行FastAPI应用。soundfile: 用于读取和处理音频文件。jieba: 中文分词库,帮助提升中文文本的处理效果。
安装过程可能需要一两分钟,等待所有包安装完成即可。
3.2 第二步:编写并启动服务
服务的主程序是一个Python脚本。我们创建一个名为app.py的文件,并将以下内容复制进去。
# app.py from funasr_onnx import SenseVoiceSmall import gradio as gr import os import soundfile as sf import numpy as np from fastapi import FastAPI, File, UploadFile, Form from fastapi.responses import JSONResponse import uvicorn import tempfile # 1. 初始化模型 # 模型会自动从缓存或网络加载,路径是固定的 MODEL_DIR = "/root/ai-models/danieldong/sensevoice-small-onnx-quant" print(f"正在加载模型,路径: {MODEL_DIR}") # 创建模型实例 # batch_size=10 表示可以批量处理10段音频,提升效率 # quantize=True 使用量化后的模型,体积小、速度快 model = SenseVoiceSmall(model_dir=MODEL_DIR, batch_size=10, quantize=True) print("模型加载成功!") # 2. 定义核心识别函数 def transcribe_audio(audio_path, language="auto", use_itn=True): """ 将音频文件转为文字 :param audio_path: 音频文件路径 :param language: 语言代码,如 'zh'(中文), 'en'(英文), 'auto'(自动检测) :param use_itn: 是否启用逆文本正则化(如把“一百”转为“100”) :return: 识别出的文本 """ try: # 调用模型进行识别 # 注意:model接收一个音频路径的列表,所以这里用 [audio_path] results = model([audio_path], language=language, use_itn=use_itn) if results and len(results) > 0: return results[0] # 返回第一段音频的识别结果 else: return "识别失败,未返回结果。" except Exception as e: return f"识别过程中出现错误: {str(e)}" # 3. 创建Gradio Web界面(给普通用户用) def create_gradio_interface(): def gradio_transcribe(audio_file, selected_language): # Gradio上传的是临时文件路径,直接使用 if audio_file is None: return "请先上传一个音频文件。" text_result = transcribe_audio(audio_file, language=selected_language) return text_result # 定义界面 language_choices = ["auto", "zh", "en", "yue", "ja", "ko"] iface = gr.Interface( fn=gradio_transcribe, inputs=[ gr.Audio(label="上传或录制音频", type="filepath"), gr.Dropdown(label="选择语言(或自动检测)", choices=language_choices, value="auto") ], outputs=gr.Textbox(label="识别结果", lines=10), title="SenseVoice-Small 语音识别服务", description="上传音频文件,自动转换为文字。支持中文、英文、粤语、日语、韩语及自动检测。", theme="soft" ) return iface # 4. 创建FastAPI应用(给开发者调用API用) app = FastAPI(title="SenseVoice-Small ASR API") @app.post("/api/transcribe") async def api_transcribe( file: UploadFile = File(...), language: str = Form("auto"), use_itn: bool = Form(True) ): """API接口:上传音频文件并返回识别文本""" # 将上传的文件保存为临时文件 suffix = os.path.splitext(file.filename)[-1] or ".wav" with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp: tmp.write(await file.read()) tmp_path = tmp.name try: text = transcribe_audio(tmp_path, language=language, use_itn=use_itn) return JSONResponse(content={"text": text, "language": language, "success": True}) except Exception as e: return JSONResponse(content={"error": str(e), "success": False}, status_code=500) finally: # 清理临时文件 os.unlink(tmp_path) @app.get("/health") async def health_check(): """健康检查端点""" return {"status": "healthy", "model": "SenseVoice-Small"} # 5. 启动服务 if __name__ == "__main__": # 创建Gradio界面并挂载到FastAPI gradio_app = create_gradio_interface() app = gr.mount_gradio_app(app, gradio_app, path="/") # 启动服务器 print("="*50) print("服务启动成功!") print("Web 界面: http://localhost:7860") print("API 文档: http://localhost:7860/docs") print("健康检查: http://localhost:7860/health") print("="*50) uvicorn.run(app, host="0.0.0.0", port=7860)保存好app.py文件后,在终端运行它:
python3 app.py你会看到终端开始加载模型,并最终显示服务启动成功的消息,包含访问地址。
3.3 第三步:访问与测试你的服务
服务启动后,打开你的浏览器,访问终端提示的地址:http://localhost:7860。
你会看到一个简洁的Web界面:
- 上传音频:点击上传按钮,选择一个你的音频文件(支持mp3, wav, m4a, flac等格式)。
- 选择语言:在下拉框中选择音频的语言,或者保持“auto”让模型自动检测。
- 点击提交:稍等片刻,识别出的文字就会显示在下方的大文本框中。
恭喜你!你的个人语音识别服务已经成功运行了。
除了网页,你还可以用更“程序员”的方式调用它——通过API。打开另一个终端窗口,使用curl命令测试:
# 假设你有一个名为 meeting.wav 的音频文件 curl -X POST "http://localhost:7860/api/transcribe" \ -F "file=@meeting.wav" \ -F "language=auto" \ -F "use_itn=true"命令执行后,你会收到一个JSON格式的响应,其中text字段就是识别出的文字。
4. 核心功能详解与使用技巧
服务跑起来了,我们来深入了解一下它的核心能力和一些让结果更好的小技巧。
4.1 理解多语言与自动检测
SenseVoice-Small的一个强大之处是它的多语言能力。在调用时,你可以通过language参数指定语言:
| 参数值 | 代表语言 | 使用场景建议 |
|---|---|---|
auto | 自动检测 | 不确定语言时使用,模型会自行判断。 |
zh | 中文(普通话) | 会议录音、讲座、播客等。 |
en | 英语 | 英文会议、视频、采访。 |
yue | 粤语 | 粤语对话、节目。 |
ja | 日语 | 日语音频、动漫。 |
ko | 韩语 | 韩语音频、韩剧。 |
小技巧:即使你明确知道是中文,在混合了少量英文词汇(如“这个API很好用”)时,使用auto也可能获得更好的效果,因为模型会动态调整。
4.2 逆文本正则化(ITN):让数字更规范
use_itn=True这个参数非常实用。ITN(Inverse Text Normalization)能将口语化的数字表达转为规范的书面形式。
- 开启ITN:
“今天花了三百五十元”→“今天花了350元” - 关闭ITN:
“今天花了三百五十元”→“今天花了三百五十元”
建议:对于会议纪要、数据报告等需要规范数字的场景,务必开启ITN。对于小说朗读、诗歌等需要保留原文韵味的场景,可以关闭。
4.3 处理长音频与批量文件
我们的服务脚本已经配置了batch_size=10,这意味着它可以高效地处理多个音频文件。如果你有一批音频需要转换,可以写一个简单的Python脚本来批量处理:
# batch_process.py import os from app import transcribe_audio # 假设和app.py在同一目录 audio_folder = "./my_audios" output_file = "./transcriptions.txt" results = [] for filename in os.listdir(audio_folder): if filename.endswith(('.wav', '.mp3', '.m4a')): filepath = os.path.join(audio_folder, filename) print(f"正在处理: {filename}") text = transcribe_audio(filepath, language="zh") results.append(f"【{filename}】\n{text}\n{'-'*40}\n") # 保存所有结果 with open(output_file, 'w', encoding='utf-8') as f: f.writelines(results) print(f"批量处理完成,结果已保存至: {output_file}")对于超长音频(如超过1小时),虽然模型能处理,但内存和出错风险会增加。更稳妥的做法是先用pydub等库将长音频按静音处切割成15-30分钟的小段,再分批送入识别。
5. 常见问题与故障排除
第一次搭建和运行,可能会遇到一些小问题。这里列出几个常见的坑和解决方法。
Q1: 运行python3 app.py时提示“ModuleNotFoundError: No module named ‘funasr_onnx’”。
- 原因:依赖包没有安装成功,或者不在当前的虚拟环境中。
- 解决:确保虚拟环境已激活(命令行前有
(sensevoice-env)),然后重新执行pip install funasr-onnx ...命令。
Q2: 模型加载非常慢,或者卡住不动。
- 原因:首次运行需要从网络下载模型文件(约230MB),如果网络不好会较慢。
- 解决:耐心等待。模型下载后会缓存在
/root/ai-models/目录下,下次启动就很快了。你也可以根据终端提示的路径,手动检查该目录下是否有sensevoice-small-onnx-quant文件夹。
Q3: 上传音频后识别失败,返回错误。
- 检查音频格式:确保是常见的格式(wav, mp3, m4a, flac)。特别老的mp3编码可能有兼容问题,可以尝试用格式工厂等工具转为标准的
wav (PCM 16kHz 单声道)再试。 - 检查音频内容:确认音频不是完全静音或噪音过大,模型需要有效的语音信号。
- 查看终端日志:服务运行终端会打印详细的错误信息,根据提示排查。
Q4: 我想在服务器上部署,让其他人也能访问。
- 修改启动命令:脚本中
uvicorn.run(app, host="0.0.0.0", port=7860)的host="0.0.0.0"已经允许外部访问。 - 安全注意:直接在公网服务器用
0.0.0.0启动服务存在安全风险。生产环境建议:- 使用Nginx反向代理。
- 配置防火墙,只开放必要端口。
- 为API添加认证(如API Key)。FastAPI可以很方便地集成安全中间件。
Q5: 识别结果中有一些专有名词错了怎么办?
- 现状:SenseVoice-Small作为通用模型,对特定领域术语(如医药名、内部产品代号)识别可能不准。
- 后期处理:这是目前所有语音识别的共同挑战。一个实用的方法是:识别完成后,用简单的文本替换规则或关键词表对结果进行二次校正。
6. 总结
跟着这篇教程走下来,你已经完成了几件很有成就感的事:搭建了一个Python环境,安装并配置了语音识别模型,启动了一个同时提供Web界面和API接口的服务,并且学会了如何用它来处理自己的音频文件。
这个基于SenseVoice-Small的服务,核心优势在于“轻量”和“易用”。它不需要昂贵的GPU,在普通的笔记本电脑或云服务器上就能流畅运行,并且开箱即用地支持多种语言。无论是用于个人学习笔记的整理,还是作为某个大型应用中的一个功能模块,它都是一个非常不错的起点。
技术的乐趣在于动手尝试和不断优化。你可以基于这个基础服务,尝试添加更多功能,比如:
- 将识别结果自动保存为Markdown或Word文档。
- 开发一个简单的桌面应用,拖拽音频文件即可识别。
- 与钉钉、飞书等办公软件结合,实现会议录音自动转纪要。
希望这个从零开始的搭建之旅,能帮你打开语音识别应用开发的大门。现在,你的私有化语音转文字服务已经就绪,去处理那段积压已久的会议录音吧!
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
