Sherpa 语音识别工具链安装指南(Linux CPU 版)

在语音识别、实时音频处理等场景中,Sherpa 是 k2-fsa 社区推出的轻量级工具集,支持 PyTorch 与 ONNX 双后端。本文将详解基于 Python 3.10 的 CPU 版安装流程,包含 torch、k2、kaldifeat 等核心组件的部署技巧。

一、环境准备

1. 系统与 Python 要求

  • 操作系统 :Ubuntu 18.04+/CentOS 7+(需支持manylinux_2_17标准)

  • Python 版本 :3.10.x(对应 whl 文件的cp310标识)

  • 依赖工具pip ≥ 20.0.0wget(建议提前升级 pip:pip install --upgrade pip

2. 虚拟环境建议

为避免依赖冲突,推荐使用虚拟环境隔离安装:

bash 复制代码
# 创建虚拟环境
python3.10 -m venv sherpa-env

# 激活环境
source sherpa-env/bin/activate

二、组件安装步骤

1. PyTorch 核心依赖(torch 2.5.0)

作为基础计算框架,需优先安装匹配版本的 PyTorch 套件:

bash 复制代码
pip install torch==2.5.0 torchvision==0.20.0 torchaudio==2.5.0 --index-url https://download.pytorch.org/whl/cpu

说明:指定cpu索引源可跳过 GPU 版本下载,节省带宽与磁盘空间。

2. k2 有限状态 transducer 库

k2 提供高效的语音识别解码能力,需离线下载预编译 whl 文件:

下载地址

本地安装

bash 复制代码
pip install k2-1.24.4.dev20250307%2Bcpu.torch2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 

3. kaldifeat 特征提取工具

用于音频特征提取,安装流程与 k2 一致:

下载地址

本地安装

bash 复制代码
pip install kaldifeat-1.25.5.dev20250307%2Bcpu.torch2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 

4. k2_sherpa 核心组件

Sherpa 的 PyTorch 后端实现,需匹配上述组件版本:

下载地址

本地安装

bash 复制代码
pip install k2_sherpa-1.4.0.dev20250307%2Bcpu.torch2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

5. Sherpa-ONNX 轻量推理引擎

适用于轻量化部署场景,支持直接在线安装:

bash 复制代码
# 国内用户建议添加清华镜像加速

pip install sherpa-onnx sherpa-onnx-bin -i https://pypi.tuna.tsinghua.edu.cn/simple

三、安装验证

1. 基础功能测试

运行以下代码检查核心组件是否正常导入:

复制代码
import torch
import k2
import kaldifeat
import sherpa_onnx

print("PyTorch版本:", torch.__version__)
print("k2版本:", k2.__dev_version__)
print("Sherpa-ONNX版本:", sherpa_onnx.__version__)
print("安装成功!")

2. 语音TTS demo 运行

下载预训练模型测试实际功能:

bash 复制代码
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-zh-hf-fanchen-wnj.tar.bz2
tar xvf vits-zh-hf-fanchen-wnj.tar.bz2
rm vits-zh-hf-fanchen-wnj.tar.bz2

sherpa-onnx-offline-tts \
  --vits-model=./vits-zh-hf-fanchen-wnj/vits-zh-hf-fanchen-wnj.onnx \
  --vits-dict-dir=./vits-zh-hf-fanchen-wnj/dict \
  --vits-lexicon=./vits-zh-hf-fanchen-wnj/lexicon.txt \
  --vits-tokens=./vits-zh-hf-fanchen-wnj/tokens.txt \
  --output-filename="./kuayue.wav" \
  "你好,这是生成的声音。"

四、Python调用

python 复制代码
#!/usr/bin/env python3
# simple_tts.py

import sys
import time
import logging
import sherpa_onnx
import soundfile as sf


class VitsTTS:
    def __init__(self, vits_model: str, vits_tokens: str, vits_lexicon: str, vits_dict_dir: str, num_threads: int = 4):
        """
        初始化通用 VITS TTS 引擎。

        Args:
            vits_model (str): VITS 模型的 ONNX 文件路径 (e.g., ./model/eula.onnx).
            vits_tokens (str): tokens.txt 文件路径.
            vits_lexicon (str): lexicon.txt 文件路径.
            vits_dict_dir (str): 分词词典目录路径.
            num_threads (int): 推理时使用的线程数.
        """
        # 直接使用传入的路径,不再硬编码文件名
        self.vits_model_path = vits_model
        self.vits_tokens_path = vits_tokens
        self.vits_lexicon_path = vits_lexicon
        self.vits_dict_dir_path = vits_dict_dir

        # 配置 VITS 模型参数
        self.vits_model_config = sherpa_onnx.OfflineTtsVitsModelConfig(
            model=self.vits_model_path,
            tokens=self.vits_tokens_path,
            lexicon=self.vits_lexicon_path,
            dict_dir=self.vits_dict_dir_path,
            noise_scale=0.667,
            noise_scale_w=0.8,
            length_scale=1.0
        )

        # 配置 TTS 引擎
        self.model_config = sherpa_onnx.OfflineTtsModelConfig(
            vits=self.vits_model_config,
            num_threads=num_threads,
            debug=False,
        )

        self.tts_config = sherpa_onnx.OfflineTtsConfig(
            model=self.model_config,
        )

        # 初始化 TTS 引擎
        self.tts = sherpa_onnx.OfflineTts(self.tts_config)
        logging.info(f"TTS 引擎已使用模型 '{vits_model}' 初始化成功!")

    def generate(self, text: str, sid: int = 0, speed: float = 1.0, output_filename: str = "output.wav"):
        """
        生成语音并保存为 WAV 文件。
        """
        logging.info(f"合成文本: {text}")
        logging.info(f"说话人 ID: {sid}, 语速: {speed}")

        start = time.time()

        # 动态调整语速
        self.vits_model_config.length_scale = 1.0 / speed
        self.model_config.vits = self.vits_model_config
        self.tts_config.model = self.model_config
        self.tts = sherpa_onnx.OfflineTts(self.tts_config)
        
        # 生成音频
        audio = self.tts.generate(text, sid)

        end = time.time()
        elapsed_seconds = end - start
        audio_duration = len(audio.samples) / audio.sample_rate
        real_time_factor = elapsed_seconds / audio_duration

        # 保存音频
        sf.write(
            output_filename,
            audio.samples,
            samplerate=audio.sample_rate,
            subtype="PCM_16",
        )

        # 打印日志和统计信息
        logging.info(f"音频已保存至: {output_filename}")
        logging.info(f"采样率: {audio.sample_rate}, 音频时长: {audio_duration:.2f}秒")
        print(f"推理耗时: {elapsed_seconds:.3f}秒")
        print(f"音频时长: {audio_duration:.3f}秒")
        print(f"实时率(RTF): {real_time_factor:.3f}")


if __name__ == "__main__":
    logging.basicConfig(
        format="%(asctime)s %(levelname)s: %(message)s",
        level=logging.INFO,
    )

    # --- 使用说明 ---
    # 运行命令: python3 your_script_name.py --vits-model ./model/theresa.onnx --vits-tokens ./model/tokens.txt ...

    # 使用 argparse 接收所有文件路径参数
    import argparse
    parser = argparse.ArgumentParser(description="通用 VITS TTS 合成工具")
    # 必需的模型文件参数
    parser.add_argument("--vits-model", type=str, required=True, help="VITS model.onnx 文件路径")
    parser.add_argument("--vits-tokens", type=str, required=True, help="tokens.txt 文件路径")
    parser.add_argument("--vits-lexicon", type=str, required=True, help="lexicon.txt 文件路径")
    parser.add_argument("--vits-dict-dir", type=str, required=True, help="分词词典目录路径")
    # 合成参数
    parser.add_argument("--text", type=str, required=True, help="要合成的文本")
    parser.add_argument("--sid", type=int, default=0, help="说话人 ID")
    parser.add_argument("--speed", type=float, default=1.0, help="语速")
    parser.add_argument("--output", type=str, default="output.wav", help="输出文件名")
    parser.add_argument("--num-threads", type=int, default=4, help="推理线程数")
    
    args = parser.parse_args()

    # 初始化 TTS
    vits = VitsTTS(
        vits_model=args.vits_model,
        vits_tokens=args.vits_tokens,
        vits_lexicon=args.vits_lexicon,
        vits_dict_dir=args.vits_dict_dir,
        num_threads=args.num_threads
    )

    # 生成音频
    vits.generate(text=args.text, sid=args.sid, speed=args.speed, output_filename=args.output)
bash 复制代码
python3 simple_tts.py \
  --vits-model ./vits-zh-hf-theresa/theresa.onnx \
  --vits-tokens ./vits-zh-hf-theresa/tokens.txt \
  --vits-lexicon ./vits-zh-hf-theresa/lexicon.txt \
  --vits-dict-dir ./vits-zh-hf-theresa/dict \
  --text "真诚就是不欺人也不自欺。热爱就是全心投入并享受其中。" \
  --sid 0 \
  --output reai-0.wav

五、参考资源

相关推荐
UNbuff_04 小时前
Linux top 命令使用说明
linux·运维·服务器
---学无止境---4 小时前
Linux中dcache和inode缓存回收函数的实现
linux
Мартин.4 小时前
[Meachines] [Hard] Pollution MyBB+Redis_session+PHP-Filter+PHP-FPM+prototype
linux
总有刁民想爱朕ha4 小时前
银河麒麟v10 Mysql8部署教程(小白版)
linux·mysql数据库备份
LCG元5 小时前
性能排查必看!当Linux服务器CPU/内存飙高,如何快速定位并"干掉"罪魁祸首进程?
linux·后端
christine-rr6 小时前
MySQL数据库管理、DDL、DQL、DML、DCL等总结
linux·数据库·mysql
奥尔特星云大使6 小时前
CentOS 7 上通过 RPM 包安装 Zabbix 4.x
linux·centos·zabbix
程序员勾践6 小时前
安装nginx
linux·nginx·centos
郝学胜-神的一滴6 小时前
Linux 进程控制块(PCB)解析:深入理解进程管理机制
linux·服务器·开发语言