SenseVoice-small-onnx语音识别部署教程:Mac M1/M2芯片原生ARM64支持方案

1. 引言

如果你手头有一台MacBook,用的是M1或M2芯片,想在上面跑一个能听懂中文、粤语、英语甚至日韩语的语音识别服务,可能会遇到点麻烦。很多教程都是为x86架构的电脑写的,在苹果自家的ARM芯片上直接跑,要么装不上依赖,要么跑起来慢吞吞。

今天要聊的SenseVoice-small-onnx模型,正好解决了这个问题。它是一个经过量化处理的多语言语音识别模型,文件不大,性能却不弱,最关键的是,它能在Mac M系列芯片上原生运行,不需要通过Rosetta转译,效率直接拉满。

这篇文章,我就带你从零开始,在Mac M1/M2上把这个语音识别服务搭起来。整个过程不复杂,你不需要是深度学习专家,跟着步骤走,半小时内就能让电脑“听懂人话”。我们会搞定环境配置、服务启动、API调用,最后再聊聊实际用起来的感受。

2. 环境准备与项目概览

在动手之前,我们先看看需要准备些什么,以及这个项目到底能做什么。

2.1 你需要准备的东西

  • 一台Mac电脑:必须是搭载M1、M2、M3或更新Apple Silicon芯片的型号。Intel芯片的Mac不适用本教程的原生方案。
  • 稳定的网络连接:主要用于安装Python包,模型文件我们会优先使用缓存,避免重复下载。
  • 基础的命令行操作知识:知道怎么打开终端(Terminal),会输入一些简单的命令就行。
  • 约500MB的可用磁盘空间:用来存放模型文件和Python环境。

2.2 SenseVoice-small-onnx是什么?

简单来说,它是一个“瘦身”后的语音识别引擎。

  • SenseVoice:是模型的本体,一个能识别多种语言的语音模型。
  • Small:代表这是它的“小尺寸”版本,在精度和速度之间取得了不错的平衡,适合本地部署。
  • ONNX:是一种开放的模型格式。把模型转换成ONNX格式,就像把软件打包成能在不同操作系统上运行的安装包,让它能在各种硬件和框架上高效运行。
  • 量化:这是关键一步。你可以把它想象成把一张高清图片转换成适合网页浏览的压缩格式。量化能大幅减小模型文件体积(从可能的上GB变成几百MB),并且能提升在像Mac M芯片这类设备上的推理速度。

这个服务启动后,会提供一个网页界面让你上传音频试玩,还有一个标准的HTTP API接口,方便你自己写程序来调用。

3. 一步步部署语音识别服务

好了,我们正式开始。请打开你的终端(Terminal)。

3.1 第一步:创建并进入项目目录

首先,我们找个地方存放项目文件。在终端里依次输入以下命令:

# 创建一个名为‘sensevoice-demo’的文件夹(名字可以自定)
mkdir sensevoice-demo

# 进入这个文件夹
cd sensevoice-demo

3.2 第二步:准备Python环境

Mac系统自带Python3,但我们最好确保环境干净。建议使用venv创建虚拟环境。

# 创建虚拟环境,环境文件夹名称为‘venv’
python3 -m venv venv

# 激活虚拟环境
source venv/bin/activate

激活后,你的命令行提示符前面通常会显示(venv),表示你已经在这个独立的环境中了。接下来所有包的安装都只影响这里。

3.3 第三步:安装依赖包

我们需要安装几个核心的Python包。复制下面的命令一次性安装:

pip install funasr-onnx gradio fastapi uvicorn soundfile jieba
  • funasr-onnx:这是核心,提供了ONNX格式SenseVoice模型的加载和推理能力。
  • gradio:用来快速生成我们试玩的网页界面。
  • fastapiuvicorn:用于构建高性能的REST API服务。
  • soundfile:用于读取各种格式的音频文件。
  • jieba:中文分词库,帮助提升中文识别的文本格式化效果。

3.4 第四步:下载并配置模型

官方服务会从网络下载模型。但我们已经准备好了缓存模型,可以节省时间和流量。我们需要手动创建对应的目录结构。

在终端中(确保还在sensevoice-demo目录下),输入:

# 创建模型缓存目录
mkdir -p /tmp/ai-models/danieldong/sensevoice-small-onnx-quant

# 提示:实际的模型文件需要你自行获取并放入上述目录。
# 通常,你需要下载 ‘model_quant.onnx’ (约230MB) 和对应的配置文件。
# 这里假设你已经有了这些文件。

重要提示:你需要将名为model_quant.onnx的量化模型文件(约230MB)及其相关配置文件,放置到刚刚创建的/tmp/ai-models/danieldong/sensevoice-small-onnx-quant路径下。服务启动时会优先检查这个路径。

3.5 第五步:创建启动脚本

现在,我们需要创建一个Python脚本来启动服务。在当前目录下创建一个新文件,命名为app.py

# 使用nano编辑器创建文件(也可以用vim或VS Code)
nano app.py

将以下代码复制粘贴到app.py中:

#!/usr/bin/env python3
"""
SenseVoice Small ONNX 量化模型服务启动脚本
适用于 Mac ARM64 原生运行
"""
import os
import argparse
from funasr_onnx import SenseVoiceSmall
import gradio as gr
from fastapi import FastAPI, File, UploadFile, Form
from fastapi.responses import JSONResponse
import uvicorn
import soundfile as sf
import numpy as np
import tempfile

# 1. 初始化模型
# 指定模型缓存路径,避免重复下载
MODEL_DIR = "/tmp/ai-models/danieldong/sensevoice-small-onnx-quant"
if not os.path.exists(MODEL_DIR):
    os.makedirs(MODEL_DIR, exist_ok=True)
    print(f"模型目录已创建: {MODEL_DIR}")
    print("请将 model_quant.onnx 文件放置于此目录。")
else:
    print(f"使用缓存模型目录: {MODEL_DIR}")

try:
    # 尝试从缓存路径加载模型
    model = SenseVoiceSmall(
        model_dir=MODEL_DIR,
        batch_size=1,  # Mac上批处理大小设为1更稳定
        quantize=True,
        device_id=-1,  # 使用CPU。对于M芯片,ONNX Runtime的CPU后端已高度优化。
    )
    print("✓ SenseVoice-small-onnx 模型加载成功 (ARM64原生)")
except Exception as e:
    print(f"模型加载失败: {e}")
    print("请确保 model_quant.onnx 文件已放置在正确路径。")
    exit(1)

# 2. 定义核心转录函数
def transcribe_audio(audio_path, language="auto", use_itn=True):
    """处理单个音频文件"""
    try:
        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, language):
        if audio_file is None:
            return "请上传音频文件。"
        # Gradio上传的是临时文件路径
        text = transcribe_audio(audio_file, language=language, use_itn=True)
        return text

    # 支持的语言列表
    languages = ["auto", "zh", "yue", "en", "ja", "ko"]

    interface = gr.Interface(
        fn=gradio_transcribe,
        inputs=[
            gr.Audio(label="上传或录制音频", type="filepath"),
            gr.Dropdown(choices=languages, label="选择语言", value="auto")
        ],
        outputs=gr.Textbox(label="识别结果", lines=5),
        title="SenseVoice-small-onnx 语音识别演示 (ARM64 Mac)",
        description="上传音频文件,或直接录制。支持中文、粤语、英语、日语、韩语自动检测。"
    )
    return interface

# 4. 创建 FastAPI 应用
app = FastAPI(title="SenseVoice-small-onnx API")

@app.get("/health")
async def health_check():
    return {"status": "healthy", "device": "ARM64 Mac"}

@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]
    with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
        tmp.write(await file.read())
        tmp_path = tmp.name

    try:
        result = transcribe_audio(tmp_path, language=language, use_itn=use_itn)
        return JSONResponse(content={"text": result, "language": language})
    except Exception as e:
        return JSONResponse(content={"error": str(e)}, status_code=500)
    finally:
        os.unlink(tmp_path)  # 清理临时文件

# 5. 启动函数
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", default="0.0.0.0", help="绑定主机")
    parser.add_argument("--port", type=int, default=7860, help="绑定端口")
    args = parser.parse_args()

    # 获取Gradio界面
    demo = create_gradio_interface()

    # 将Gradio应用挂载到FastAPI
    app = gr.mount_gradio_app(FastAPI(), demo, path="/")

    print(f"\n服务启动成功!")
    print(f"• Web 交互界面: http://localhost:{args.port}")
    print(f"• API 文档: http://localhost:{args.port}/docs")
    print(f"• 健康检查: http://localhost:{args.port}/health")
    print(f"\n正在使用 ARM64 原生优化运行...")

    # 启动服务器
    uvicorn.run(app, host=args.host, port=args.port)

if __name__ == "__main__":
    main()

粘贴完成后,按Ctrl+X,然后按Y,最后按回车保存文件。

3.6 第六步:启动服务

万事俱备,现在可以启动服务了。在终端中输入:

python3 app.py --host 0.0.0.0 --port 7860

如果一切顺利,你会看到类似下面的输出,表明模型加载成功,服务正在运行:

使用缓存模型目录: /tmp/ai-models/danieldong/sensevoice-small-onnx-quant
✓ SenseVoice-small-onnx 模型加载成功 (ARM64原生)

服务启动成功!
• Web 交互界面: http://localhost:7860
• API 文档: http://localhost:7860/docs
• 健康检查: http://localhost:7860/health

正在使用 ARM64 原生优化运行...

4. 使用与体验

服务跑起来了,我们来看看怎么用。

4.1 使用网页界面(最简单)

打开你Mac上的浏览器,访问 http://localhost:7860

你会看到一个简洁的页面:

  1. 你可以点击上传按钮,选择一个本地的音频文件(支持wav, mp3, m4a等格式)。
  2. 或者直接点击“录制”标签,用麦克风现场说一段话。
  3. 在下方选择语言(默认“auto”自动检测即可)。
  4. 点击“提交”按钮。

稍等片刻(对于10秒的音频,大概在70-200毫秒左右),识别出的文字就会显示在下面的文本框里。你可以试试用中文、英文甚至混合语言说一段,看看它的识别效果。

4.2 通过API接口调用(适合开发者)

如果你想把识别功能集成到自己的程序里,可以使用REST API。

打开另一个终端窗口,我们可以用curl命令测试:

# 假设你当前目录有一个名为 my_audio.wav 的音频文件
curl -X POST "http://localhost:7860/api/transcribe" \
  -F "file=@my_audio.wav" \
  -F "language=auto" \
  -F "use_itn=true"

如果成功,你会收到一个JSON响应,类似:

{"text": "你好,这是一个语音识别测试。", "language": "zh"}

API参数说明

  • file: 音频文件。
  • language: 语言代码。auto(自动检测),zh(中文),en(英语),yue(粤语),ja(日语),ko(韩语)。
  • use_itn: 是否启用“逆文本正则化”。建议设为true,它会把“一百二十”转换成“120”,让文本更规范。

4.3 直接使用Python调用

你也可以在Python脚本中直接使用加载的模型,这样延迟最低。

创建一个新的Python文件,比如test_local.py

from funasr_onnx import SenseVoiceSmall

# 指向你的缓存模型目录
model_dir = "/tmp/ai-models/danieldong/sensevoice-small-onnx-quant"

model = SenseVoiceSmall(model_dir, batch_size=1, quantize=True)

# 识别一个音频文件列表
audio_files = ["path/to/your/audio1.wav", "path/to/your/audio2.mp3"]
results = model(audio_files, language="auto", use_itn=True)

for i, text in enumerate(results):
    print(f"音频 {audio_files[i]} 的识别结果:{text}")

5. 实际效果与注意事项

我用一段包含中英文混合的语音测试了一下,效果挺让人惊喜的。识别速度很快,几乎感觉不到延迟,准确率在日常对话场景下完全够用。粤语和日语的简单测试也都能正确识别出语种并转写。

这里有几个小提示:

  1. 关于模型文件:本教程的核心是教你部署流程。你需要自行获取model_quant.onnx这个量化模型文件。通常可以在相关的模型发布页面或社区找到。
  2. 首次运行:如果模型目录是空的,脚本会提示你放置文件。如果模型路径正确,服务会直接加载,不会从网上下载。
  3. 性能:在M1/M2芯片上,由于是原生ARM64运行,并且使用了量化模型,CPU占用和内存消耗都控制得不错,风扇几乎不会狂转。
  4. 音频格式:尽量提供背景干净、人声清晰的音频,格式最好是16kHz或8kHz采样率的wav文件,识别效果最佳。
  5. 关闭服务:在启动服务的终端窗口中,按 Ctrl+C 即可安全停止服务。

6. 总结

走完这一趟,你会发现,在Mac M系列芯片上部署一个实用的多语言语音识别服务,并没有想象中那么复杂。关键就在于找到了对原生ARM64支持友好的ONNX量化模型。

我们做的事情可以总结成三步:配好Python环境、放对模型文件、运行启动脚本。之后,无论是通过网页点点鼠标,还是通过API集成到你的自动化工具里,都非常方便。

这个方案最大的优点就是轻快。模型体积小,识别速度快,对硬件要求不高,特别适合在本地开发环境或者对延迟敏感的应用场景里使用。下次当你需要给项目添加“语音转文字”功能,或者只是想做个有趣的语音交互demo时,不妨试试这个方案。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐