Fun-ASR-Nano-2512 部署教程

一、模型介绍

Fun-ASR 是通义实验室推出的一款端到端语音识别大模型。它基于数千万小时的真实语音数据训练而成,具备强大的上下文理解能力和行业适应性。支持低延迟实时转写,覆盖31种语言。在教育、金融等垂直领域表现出色,能够精准识别专业术语和行业表达,有效解决“幻觉”生成和语言混淆等问题,实现“听得清、懂得意、写得准”。

轻量化版本Fun-ASR-Nano-2512参数量 0.8B ,推理成本更低,支持本地部署与定制化微调,核心特性包括远场高噪声场景深度优化,识别准确率可达 93% ;支持吴语、粤语、闽语、客家话、赣语、湘语、晋语 7大方言 及河南、陕西、湖北、四川等 26个地区口音 ;强化音乐背景下的歌词识别能力;引入 RAG 机制将定制热词上限提升至 10000条 ,满足金融、医疗、教育等专业领域需求。

二、部署过程

项目上正好要用到语音转文本,该版本发布后,第一时间花了两个半天部署起来了,部署过程坑还是比较多的,我把部署过程都记录了下来,如果有正好需要部署的,可以参考这个部署过程。

我是在 Linux 服务器( NVIDIA 3090 显卡,24G显存)上部署 Fun-ASR-Nano-2512,启动完成后占用2590MiB显存,有请求调用后上升到3858MiB显存占用,可以按这个来评估显存需求,目前官方明确说不支持FP16部署,显存只能占么这多了。


下面是具体的安装过程:

1. 安装ffmpeg

sudo apt update && sudo apt install ffmpeg

2. 进入部署目录:

 cd /data/asr

具体目录自己定,我这设定为 /data/asr

3.创建 Python 虚拟环境

# (推荐使用 Conda 创建 Python 3.10 环境,因为系统默认 Python 3.13 可能存在兼容性问题)
conda create -n asr python=3.10 -y
conda activate asr

# 或者使用原生 venv (如果 Python 版本 < 3.13)
# python3 -m venv venv
# source venv/bin/activate

4. 升级 pip

pip install --upgrade pip

5. 安装 PyTorch (根据您的 CUDA 版本选择,这里适配 CUDA 12.x)

pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu121

6. 安装 FunASR 及相关依赖

pip install funasr modelscope websockets transformers sentencepiece

7.下载模型,以下代码保存为download_model.py,然后运行 python download_model.py 下载模型

import os
import shutil
"""
Download FunASR Models
作者:凌封
来源:https://aibook.ren (AI全书)
"""
from modelscope import snapshot_download

# 配置
MODELS_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models')
FUNASR_MODEL_ID = 'FunAudioLLM/Fun-ASR-Nano-2512'
QWEN_MODEL_ID = 'Qwen/Qwen3-0.6B'

def download_and_setup_models():
    if not os.path.exists(MODELS_ROOT):
        os.makedirs(MODELS_ROOT)

    print(f"=== 开始下载模型 ===")
    print(f"本地保存目录: {MODELS_ROOT}")

    # 1. 下载 Fun-ASR-Nano-2512
    print(f"\n[1/2] 正在下载主模型: {FUNASR_MODEL_ID}")
    try:
        funasr_dir = snapshot_download(FUNASR_MODEL_ID, cache_dir=MODELS_ROOT)
        print(f"主模型已就绪: {funasr_dir}")
    except Exception as e:
        print(f"[失败] 主模型下载出错: {e}")
        return

    # 2. 下载并配置 Qwen3-0.6B 子模块
    # FunASR 代码期望 Qwen3 位于 Fun-ASR-Nano-2512/Qwen3-0.6B 目录下
    qwen_target_dir = os.path.join(funasr_dir, 'Qwen3-0.6B')
    
    print(f"\n[2/2] 正在配置子模块: {QWEN_MODEL_ID}")
    print(f"目标子目录: {qwen_target_dir}")

    try:
        # 下载 Qwen3 到缓存
        print(f"正在下载 Qwen3 模型...")
        qwen_temp_dir = snapshot_download(QWEN_MODEL_ID, cache_dir=MODELS_ROOT)
        
        # 检查是否需要复制/更新
        # 如果目标目录不存在,或者为空,则进行复制
        if os.path.exists(qwen_target_dir):
            print("检测到目标子目录已存在,清理旧文件以确保完整性...")
            shutil.rmtree(qwen_target_dir)
        
        print(f"正在复制文件到子目录...")
        shutil.copytree(qwen_temp_dir, qwen_target_dir)
        print(f"子模块配置完成!")

    except Exception as e:
        print(f"[失败] 子模块配置出错: {e}")
        return

    print(f"\n=== 所有模型下载与配置完成 ===")
    print(f"最终路径: {funasr_dir}")

if __name__ == '__main__':
    download_and_setup_models()

8. 加载模型,推理

这个要自己写测试代码了,以下我写的测试代码 test_inference.py

import os
import torch
from funasr.models.fun_asr_nano.model import FunASRNano

# === 参数设置 ===
# 默认精度为 FP32 (float32)。设置为 True 可节省约 50% 显存。
# 如果想用默认的 FP32,将此处改为 False 即可,无需注释下面的代码
USE_FP16 = False 

def get_vram_usage():
    if torch.cuda.is_available():
        allocated = torch.cuda.memory_allocated() / 1024**3
        reserved = torch.cuda.memory_reserved() / 1024**3
        return f"Allocated: {allocated:.2f} GB, Reserved: {reserved:.2f} GB"
    return "N/A"

print("=== Fun-ASR 推理测试 ===")
print(f"Initial VRAM: {get_vram_usage()}")

# 自动检测 GPU
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Running on device: {device}")

# 模型 ID (会自动去 modelscope cache 找,或者下载)
MODEL_ID = 'FunAudioLLM/Fun-ASR-Nano-2512'

# 指定本地缓存目录 (与 download_model.py 保持一致)
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
MODELS_ROOT = os.path.join(CURRENT_DIR, 'models')

# 构建本地模型路径 (确保之前 download_model.py 已执行成功)
# 结构: models/FunAudioLLM/Fun-ASR-Nano-2512
local_model_path = os.path.join(MODELS_ROOT, MODEL_ID)

print(f"Loading model from local path: {local_model_path}")

print(f"FPS16: {USE_FP16}")

try:
    from funasr import AutoModel
    from funasr.models.fun_asr_nano.model import FunASRNano # Manual import to register model
    # 加载模型
    # 直接指定本地绝对路径,避免 FunASR 尝试去 modelscope 下载
    model = AutoModel(
        model=local_model_path,
        trust_remote_code=True,
        fp16=USE_FP16
    )
    
    print(f"Model loaded. VRAM: {get_vram_usage()}")

    # 测试音频 (使用阿里云的示例音频)
    audio_file = "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_example_zh.wav"
    print(f"\nTranscribing: {audio_file}")

    # 1. Download/Read as bytes to simulate server receiving bytes
    import requests
    audio_bytes = requests.get(audio_file).content
    print(f"Audio bytes len: {len(audio_bytes)}")

    print("\n=== Testing with raw bytes input (Should Fail) ===")
    try:
        res = model.generate(input=audio_bytes, batch_size_s=300)
        print(res)
    except Exception as e:
        print(f"Failed with bytes: {e}")

    print("\n=== Testing with decoded numpy array (Solution) ===")
    try:
        import numpy as np
        
        # Simplified load_bytes logic from official load_utils.py
        # Assuming input is valid PCM 16k 16bit mono for now (or wav bytes)
        def simple_load_bytes(input_bytes):
            # If it's a WAV file with header (like from URL), we must skip header or use soundfile
            # But here let's try assuming it's just raw PCM for the "streaming" simulation part
            # Or use soundfile for the file part.
            pass

        import io
        import soundfile as sf
        # 1. Decode properly to float32 numpy
        audio_data, samplerate = sf.read(io.BytesIO(audio_bytes))
        audio_data = audio_data.astype(np.float32)
        print(f"Decoded shape: {audio_data.shape}, dtype: {audio_data.dtype}")
        
        # 2. Wrap in list!
        print("Input: [audio_data]")
        res = model.generate(input=[audio_data], batch_size_s=300)
        print(res)
    except Exception as e:
        print(f"Failed with numpy list: {e}")
        import traceback
        traceback.print_exc()
    except Exception as e:
        print(f"Failed with bytes: {e}")
        import traceback
        traceback.print_exc()

    print("\n=== Recognition Result (BYTES TEST) ===")
    print(f"Final VRAM: {get_vram_usage()}")

except Exception as e:
    print(f"[Error] An error occurred: {e}")
    # 打印更详细的错误可能有助于排查 OOM
    import traceback
    traceback.print_exc()

三、完整部署和服务启动代码(提供流式调用接口)

以上只是简单部署了模型,实际上要使用起来,还必须运行服务,以提供应用调用,以及调用过程的接口协议等等,我项目中采用流试调用推理(为了保证推理效果,但又不能几帧几帧推理作为结果,需要整个半句有上下文推理转文本出来才比较准确),需要用到2pass模运行,中间遇到问题还是比较多的,包括包找不到、模型加载失败、找不到Qwen3-0.6B(Fun-ASR-Nano-2512依赖这个模型,但是模型库没放一起)、入参转Tensor等等,有些问题网友也反馈出来了,我一个个坑踩过去一一解决了。

为了方便大家快速部署和运行起了,我把整个过程都写成文档,并且把启动websoket服务的代码、客户端测试代码等等全整理放到github开源社区了,主要文件包括以下这些:

  • install.sh: 环境安装脚本

  • start_server.sh: 启动 Fun-ASR WebSocket 服务脚本

  • funasr_wss_server.py: WebSocket 服务主程序

  • download_model.py: 模型下载脚本(安装时下载模型)

  • test_inference.py: 本地推理测试脚本(验证环境)

  • funasr_wss_client.py: 测试客户端(验证部署是否OK)

  • web_client: Web 测试客户端目录,方便WEB页面测试(未实现VAD检测,仅用于测试流式识别)

只要把这些文件上传到需要运行的服务器的器下面,修改下部署目录(默认是/data/asr/),参考Readme.md文档就可以快速部署起来,提供应用调用了。

开源地址访问:https://github.com/fengin/Fun-ASR-Nano-2512-Deploy,如果觉得对你有用的话,点个star。

License:  CC BY 4.0

©2025 AI全书. Some rights reserved.

    备案号: 浙ICP备06043869号-8