在 Jetson AGX Orin 上部署 Fun-ASR-Nano-2512:踩坑、shim 与实时推理
目标:在 NVIDIA Jetson AGX Orin(JetPack 6.x / CUDA 12.x)上,用 Python 3.10 conda 环境把
Fun-ASR-Nano-2512部署到 GPU,并达到实时语音识别。最终成果:RTF ≈ 0.27,5.6 秒音频 1.5 秒出结果,支持离线文件、HTTP 服务、实时麦克风三种用法。
目录
- 背景与选型
- 硬件与软件环境
- 部署架构总览
- 踩坑一:torchaudio 与 Jetson PyTorch 的 C++ ABI 冲突
- 踩坑二:cuDNN 8 vs 9 与 CUBLAS 库路径顺序
- 踩坑三:Qwen3 需要 transformers >= 4.51
- 一键安装与模型下载
- 环境校验与端到端验证
- 性能测试
- 三种使用方式
- 可复现性总结
- 进一步优化方向
背景与选型
Fun-ASR-Nano-2512 是阿里巴巴通义实验室开源的端到端语音识别大模型,支持中/英/日及多方言、多口音,参数量 800M。它基于 FunASR 框架,音频编码器是 SenseVoiceEncoderSmall,LLM 是 Qwen3-0.6B。
在 Jetson 这类边缘设备上部署 LLM-ASR 模型,最大的挑战不是模型本身,而是PyTorch 生态在 ARM + JetPack 上的兼容性。官方 PyPI 的 aarch64 wheel 大多是 CPU 版,或者与 NVIDIA Jetson 专用 PyTorch 的 C++ ABI 不兼容。
因此本次部署没有走"pip install torch + pip install torchaudio"的常规路线,而是:
- 使用 NVIDIA 为 JetPack 6 编译的 PyTorch wheel
- 在项目内实现一个纯 Python 的
torchaudioshim - 用 conda 安装 cuDNN 8.9 解决 Jetson PyTorch 对
libcudnn.so.8的依赖 - 从源码安装 FunASR 并固定 commit
硬件与软件环境
| 项目 | 配置 |
|---|---|
| 设备 | NVIDIA Jetson AGX Orin 64GB |
| L4T | 36.4.4 |
| JetPack | 6.x |
| CUDA | 12.6 |
| Python | 3.10(conda 环境 funasr-nano) |
| PyTorch | torch-2.4.0a0+07cecf4168.nv24.05 |
| transformers | 4.57.6 |
| funasr | 源码 editable 安装,固定 commit f9937385 |
部署架构总览
┌─────────────────────────────────────────────┐
│ 应用层:infer_file.py / asr_server.py │
│ / realtime_mic.py │
├─────────────────────────────────────────────┤
│ 框架层:FunASR(源码 editable 安装) │
├─────────────────────────────────────────────┤
│ 兼容层:torchaudio/ 纯 Python shim │
├─────────────────────────────────────────────┤
│ 运行时:PyTorch Jetson wheel + conda cuDNN 8 │
├─────────────────────────────────────────────┤
│ 系统层:JetPack 6.x / CUDA 12.6 / cuDNN 9.x │
└─────────────────────────────────────────────┘
踩坑一:torchaudio 与 Jetson PyTorch 的 C++ ABI 冲突
现象
安装 PyPI 的 torchaudio==2.4.0 后,import 报错:
OSError: .../libtorchaudio.so: undefined symbol: _ZNK3c105Error4whatEv
本质是 PyPI wheel 针对官方 PyTorch 编译,而 NVIDIA Jetson PyTorch 的 C++ ABI(尤其是 c10::Error)与官方版不同。
解决思路
既然 funasr 对 torchaudio 的使用非常有限,何苦非要装那个带 C++ 扩展的 wheel?
我检查了 funasr 实际用到的接口:
torchaudio.load:音频文件读取torchaudio.transforms.Resample:重采样torchaudio.compliance.kaldi.fbank:Kaldi 风格滤波器组torchaudio.functional.create_dct/istft:少量符号
这些都是纯 Python 可实现的。
实现 torchaudio shim
在项目根目录下新建 torchaudio/ 包:
torchaudio/
├── __init__.py # load() 用 soundfile 实现,预加载子模块
├── compliance/
│ ├── __init__.py
│ └── kaldi.py # 从 torchaudio 源码拷贝的纯 Python fbank
├── functional/
│ └── __init__.py # resample / create_dct / istft
├── transforms/
│ └── __init__.py # Resample 纯 PyTorch 实现
└── sox_effects/
└── __init__.py # 占位
关键代码片段:
# torchaudio/__init__.py
def load(filepath, *args, **kwargs):
import soundfile as sf
data, sr = sf.read(filepath, dtype="float32", always_2d=True)
data = data.T # [channels, samples]
return torch.from_numpy(data), sr
# torchaudio/functional/__init__.py
# _get_sinc_resample_kernel / _apply_sinc_resample_kernel
# 直接从 torchaudio 源码搬运,去掉对 libtorchaudio.so 的依赖
然后让 PYTHONPATH 把项目根目录放在最前面,funasr 内部 import torchaudio 就会自动走到这个 shim。
效果
python -c "import torchaudio; print(torchaudio.__version__)"
# 2.4.0-jetson-shim
python -c "import torchaudio; print(torchaudio.__file__)"
# /home/dog-8/workspace/Audio/asr/torchaudio/__init__.py
不再报 ABI 错误,fbank、resample、音频读取全部正常工作。
踩坑二:cuDNN 8 vs 9 与 CUBLAS 库路径顺序
现象 1:libcudnn.so.8 找不到
Jetson PyTorch wheel 启动时报:
ImportError: libcudnn.so.8: cannot open shared object file: No such file or directory
原因
JetPack 6.x 系统级 cuDNN 是 9.x,但 NVIDIA 这个 PyTorch wheel 编译时链的是 cuDNN 8.x。
解决
在 conda 环境里单独装一套 cuDNN 8.9:
conda install -y cudnn=8.9.2.26
然后把 $CONDA_PREFIX/lib 加到 LD_LIBRARY_PATH。
现象 2:CUBLAS_STATUS_ALLOC_FAILED
解决 cuDNN 后,torch 能 import 了,但一跑 CUDA matmul 就报错:
RuntimeError: CUDA error: CUBLAS_STATUS_ALLOC_FAILED when calling `cublasCreate(handle)`
原因
conda 的 cuDNN 包里也带了 libcublas.so.12,但版本比系统 CUDA 12.6 的旧。如果 conda lib 排在系统 CUDA 前面,cublas 初始化就会失败。
解决
LD_LIBRARY_PATH 必须让系统 CUDA 优先:
export LD_LIBRARY_PATH="/usr/local/cuda-12.6/lib64:${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}"
而不是反过来。
我把这个设置写进了 conda activate 钩子,每次激活环境自动生效:
# $CONDA_PREFIX/etc/conda/activate.d/funasr-nano-env.sh
export _OLD_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="/usr/local/cuda-12.6/lib64:${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}"
export _OLD_PYTHONPATH="${PYTHONPATH}"
export PYTHONPATH="/home/dog-8/workspace/Audio/asr:${PYTHONPATH}"
踩坑三:Qwen3 需要 transformers >= 4.51
现象
加载模型时:
ValueError: The checkpoint you are trying to load has model type `qwen3`
but Transformers does not recognize this architecture.
解决
把 transformers 从 4.45.0 升级到 >=4.51,<5:
pip install "transformers>=4.51,<5"
同时 requirements.txt 中也相应锁定。
一键安装与模型下载
环境安装
bash scripts/install_jetson_deps.sh funasr-nano 3.10
这个脚本现在做了这些事:
- 检查 aarch64 平台
- 自动检测 conda base 和 CUDA 路径
- 创建 conda 环境
- 下载并安装 Jetson PyTorch 2.4.0
- 安装 conda cuDNN 8.9
- 安装 requirements.txt 依赖
- 从
FunASR/子目录或 GitHub 源码安装 FunASR(editable) - 固定 FunASR 到验证通过的 commit
- 降级 numpy 到 1.x
- 写入 conda 激活/退出钩子
模型下载
bash scripts/download_model.sh
优先从 ModelScope 下载 FunAudioLLM/Fun-ASR-Nano-2512,失败则 fallback 到 HuggingFace。
环境校验与端到端验证
环境校验
conda activate funasr-nano
python scripts/check_env.py
输出示例:
[1/7] 平台架构检查
✅ 平台: aarch64
[2/7] conda 环境检查
✅ conda 环境: funasr-nano
[3/7] PyTorch GPU 检查
✅ torch version: 2.4.0a0+07cecf4168.nv24.05
✅ CUDA available: True
✅ CUDA version: 12.2
✅ GPU: Orin
✅ CUDA matmul 测试通过
[5/7] torchaudio shim 检查
✅ torchaudio 路径: /home/dog-8/workspace/Audio/asr/torchaudio
✅ torchaudio 版本: 2.4.0-jetson-shim
✅ fbank 输出 shape: torch.Size([98, 80])
[6/7] FunASR 源码安装检查
✅ funasr path: /home/dog-8/workspace/Audio/asr/FunASR/funasr/__init__.py
✅ funasr 确实从项目内源码加载
[7/7] 模型目录检查
✅ 模型目录完整: /home/dog-8/models/Fun-ASR-Nano-2512
torchaudio shim 单元测试
python tests/test_torchaudio_shim.py
5 个测试全部通过。
端到端验证
bash scripts/verify_deployment.sh
会依次跑:环境校验 → shim 测试 → 离线推理 → HTTP 服务 curl 测试。
🎉 端到端验证全部通过
性能测试
在 Jetson AGX Orin 64GB 上,使用 example/zh.mp3(5.6 秒中文音频):
| 指标 | 数值 |
|---|---|
| 模型冷加载 | 约 36 秒 |
| 推理耗时 | 约 1.5 秒 |
| RTF | 0.27~0.30 |
| 识别结果 | 开饭时间早上九点至下午五点 |
RTF < 1.0 即视为实时,0.27 意味着处理速度是音频播放速度的约 3.7 倍,边缘场景完全够用。
三种使用方式
1. 离线文件识别
bash scripts/test_offline.sh \
/home/dog-8/models/Fun-ASR-Nano-2512 \
/home/dog-8/models/Fun-ASR-Nano-2512/example/zh.mp3
2. HTTP 服务(OpenAI 风格)
bash scripts/start_server.sh /home/dog-8/models/Fun-ASR-Nano-2512 0.0.0.0 8000
测试:
curl -X POST http://localhost:8000/v1/audio/transcriptions \
-F file=@/home/dog-8/models/Fun-ASR-Nano-2512/example/zh.mp3 \
-F language=中文
返回:
{"text":"开饭时间:早上九点至下午五点。"}
3. 实时麦克风识别
python src/realtime_mic.py \
--model /home/dog-8/models/Fun-ASR-Nano-2512 \
--language 中文 --chunk_duration 5
可复现性总结
为了让另一台相同 JetPack 版本的 Jetson AGX Orin 也能一键复现,我做了这些改造:
| 改造点 | 说明 |
|---|---|
| 自动检测 conda base | conda info --base,不再写死 ${HOME}/miniconda3 |
| 自动检测 CUDA 路径 | 优先 /usr/local/cuda,fallback /usr/local/cuda-* |
| FunASR 源码自动获取 | 子目录存在则直接用,否则自动 clone |
| FunASR commit 固定 | f9937385,避免未来源码更新破坏兼容性 |
| 模型自动下载 | scripts/download_model.sh,ModelScope + HuggingFace 双源 |
| 环境自动配置 | conda activate 钩子自动设置 LD_LIBRARY_PATH 和 PYTHONPATH |
| 完整校验链 | check_env.py + test_torchaudio_shim.py + verify_deployment.sh |
现在给新机器复现只需:
git clone <仓库> ~/workspace/Audio/asr
cd ~/workspace/Audio/asr
bash scripts/install_jetson_deps.sh funasr-nano 3.10
bash scripts/download_model.sh
conda activate funasr-nano
bash scripts/verify_deployment.sh
进一步优化方向
当前 RTF 0.27 已经满足实时,但想更低延迟或更高吞吐,可以优先考虑:
-
LLM 解码加速
- 用 vLLM 或 llama.cpp 替换 Qwen3-0.6B 的自回归解码
- 这是当前耗时最大头,收益最高
-
Audio encoder TensorRT / ONNX 化
- SenseVoiceEncoderSmall 做 TensorRT 推理
- 收益次之,但对长音频效果明显
-
服务化优化
- 用 gunicorn / uvicorn 替换 Flask 开发服务器
- 加推理队列和批处理,提升并发吞吐
-
模型量化
- LLM 用 INT8/INT4,audio encoder 用 FP16
- 在 Orin 上可降低显存占用并提速
结语
在 Jetson 上部署现代 LLM-ASR 模型,最大的工作量往往不是模型推理本身,而是让 PyTorch 生态在 ARM + JetPack 上跑起来。通过源码安装 FunASR、用纯 Python shim 替代 torchaudio、正确配置 cuDNN/cublas 库路径,最终实现了稳定可复现的 GPU 实时语音识别。
如果你也在做类似的事情,希望这篇笔记能帮你少踩几个坑。
项目结构参考:
.
├── FunASR/ # FunASR 源码
├── requirements.txt
├── scripts/
│ ├── install_jetson_deps.sh
│ ├── download_model.sh
│ ├── env.sh
│ ├── check_env.py
│ ├── verify_deployment.sh
│ ├── start_server.sh
│ └── test_offline.sh
├── src/
│ ├── infer_file.py
│ ├── asr_server.py
│ └── realtime_mic.py
├── tests/
│ └── test_torchaudio_shim.py
└── torchaudio/ # Jetson 兼容 shim