Skip to content

增加了一些只通过文本和角色就会调用的api,api_role_v3.py支持v3 #2164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

spawner1145
Copy link

功能:

  • 通过 GET 和 POST 请求提供 TTS 推理接口 (/),支持默认参考音频和参数调整。
  • 新增 /ttsrole 接口,支持基于角色的 TTS 推理,动态加载角色模型和参考音频,同时支持 GET 和 POST 请求。
  • 支持通过 POST 请求动态切换模型版本(v2 或 v3)。

运行服务:
python api_role_v3.py -s "path/to/sovits.pth" -g "path/to/gpt.ckpt" -dr "ref.wav" -dt "参考文本" -dl "zh" -p 9880

参数说明:
命令行参数:

  • -s, --sovits_path: SoVITS 模型路径(默认从 config 获取)。
  • -g, --gpt_path: GPT 模型路径(默认从 config 获取)。
  • -dr, --default_refer_path: 默认参考音频路径。
  • -dt, --default_refer_text: 默认参考音频文本。
  • -dl, --default_refer_language: 默认参考音频语言(zh, en, ja, ko 等)。
  • -d, --device: 设备(cuda 或 cpu,默认从 config 获取)。
  • -a, --bind_addr: 绑定地址(默认 0.0.0.0)。
  • -p, --port: 端口(默认 9880)。
  • -fp, --full_precision: 使用全精度(覆盖默认)。
  • -hp, --half_precision: 使用半精度(覆盖默认)。
  • -sm, --stream_mode: 流式模式(close 或 normal,默认 close)。
  • -mt, --media_type: 音频格式(wav, ogg, aac,默认 wav)。
  • -st, --sub_type: 数据类型(int16 或 int32,默认 int16)。
  • -cp, --cut_punc: 文本切分符号(默认空)。
  • -hb, --hubert_path: HuBERT 模型路径(默认从 config 获取)。
  • -b, --bert_path: BERT 模型路径(默认从 config 获取)。

接口参数(/):

  • refer_wav_path: 参考音频路径(可选)。
  • prompt_text: 参考音频文本(可选)。
  • prompt_language: 参考音频语言(可选)。
  • text: 待合成文本(必填)。
  • text_language: 目标文本语言(可选,默认 auto)。
  • cut_punc: 文本切分符号(可选)。
  • top_k: Top-K 采样值(默认 15)。
  • top_p: Top-P 采样值(默认 1.0)。
  • temperature: 温度值(默认 1.0)。
  • speed: 语速因子(默认 1.0)。
  • inp_refs: 辅助参考音频路径列表(默认空)。
  • sample_steps: 采样步数(默认 32,限定 [4, 8, 16, 32])。
  • if_sr: 是否超分(默认 False)。

接口参数(/ttsrole):

  • text: 待合成文本(必填)。
  • role: 角色名称(必填)。
  • text_language: 目标文本语言(默认 auto)。
  • ref_audio_path: 参考音频路径(可选)。
  • prompt_text: 参考音频文本(可选)。
  • prompt_language: 参考音频语言(可选)。
  • emotion: 情感标签(可选)。
  • top_k: Top-K 采样值(默认 15)。
  • top_p: Top-P 采样值(默认 0.6)。
  • temperature: 温度值(默认 0.6)。
  • speed: 语速因子(默认 1.0)。
  • inp_refs: 辅助参考音频路径列表(默认空)。
  • sample_steps: 采样步数(默认 32,限定 [4, 8, 16, 32])。
  • if_sr: 是否超分(默认 False)。
  • version: 模型版本(可选,v2 或 v3,POST 请求支持动态切换)。

完整请求示例 (/ttsrole POST)

{
"text": "你好", # str, 必填, 要合成的文本内容
"role": "role1", # str, 必填, 角色名称,决定使用 roles/{role} 中的配置和音频
"emotion": "开心", # str, 可选, 情感标签,用于从 roles/{role}/reference_audios 中选择音频
"text_lang": "auto", # str, 可选, 默认 "auto", 文本语言,"auto" 时根据 emotion 或角色目录动态选择
"ref_audio_path": "/path/to/ref.wav", # str, 可选, 参考音频路径,若提供则优先使用,跳过自动选择
"aux_ref_audio_paths": ["/path1.wav", "/path2.wav"], # List[str], 可选, 辅助参考音频路径,用于多说话人融合
"prompt_lang": "ja", # str, 可选, 提示文本语言,若提供 ref_audio_path 则需指定,"auto" 模式下动态选择
"prompt_text": "こんにちは", # str, 可选, 提示文本,与 ref_audio_path 配对使用,自动选择时从文件或文件名生成
"top_k": 10, # int, 可选, Top-K 采样值,覆盖 inference.top_k
"top_p": 0.8, # float, 可选, Top-P 采样值,覆盖 inference.top_p
"temperature": 1.0, # float, 可选, 温度值,覆盖 inference.temperature
"text_split_method": "cut5", # str, 可选, 文本分割方法,覆盖 inference.text_split_method, 具体见text_segmentation_method.py
"batch_size": 2, # int, 可选, 批处理大小,覆盖 inference.batch_size
"batch_threshold": 0.75, # float, 可选, 批处理阈值,覆盖 inference.batch_threshold
"split_bucket": true, # bool, 可选, 是否按桶分割,覆盖 inference.split_bucket
"speed_factor": 1.2, # float, 可选, 语速因子,覆盖 inference.speed_factor
"fragment_interval": 0.3, # float, 可选, 片段间隔(秒),覆盖 inference.fragment_interval
"seed": 42, # int, 可选, 随机种子,覆盖 seed
"media_type": "wav", # str, 可选, 默认 "wav", 输出格式,支持 "wav", "raw", "ogg", "aac"
"streaming_mode": false, # bool, 可选, 默认 false, 是否流式返回
"parallel_infer": true, # bool, 可选, 默认 true, 是否并行推理
"repetition_penalty": 1.35, # float, 可选, 重复惩罚值,覆盖 inference.repetition_penalty
"version": "v2", # str, 可选, 配置文件版本,覆盖 version,动态切换 v2 或 v3
"languages": ["zh", "ja", "en"], # List[str], 可选, 支持的语言列表,覆盖 languages
"bert_base_path": "/path/to/bert", # str, 可选, BERT 模型路径,覆盖 bert_base_path
"cnhuhbert_base_path": "/path/to/hubert", # str, 可选, HuBERT 模型路径,覆盖 cnhuhbert_base_path
"device": "cpu", # str, 可选, 统一设备,覆盖 device
"is_half": true, # bool, 可选, 是否使用半精度,覆盖 is_half
"t2s_weights_path": "/path/to/gpt.ckpt", # str, 可选, GPT 模型路径,覆盖 t2s_weights_path
"vits_weights_path": "/path/to/sovits.pth", # str, 可选, SoVITS 模型路径,覆盖 vits_weights_path
"t2s_model_path": "/path/to/gpt.ckpt", # str, 可选, GPT 模型路径(与 t2s_weights_path 同义)
"t2s_model_device": "cpu", # str, 可选, GPT 模型设备,覆盖 t2s_model.device,默认检测显卡
"vits_model_path": "/path/to/sovits.pth", # str, 可选, SoVITS 模型路径(与 vits_weights_path 同义)
"vits_model_device": "cpu" # str, 可选, SoVITS 模型设备,覆盖 vits_model.device,默认检测显卡
}

参数必要性和优先级

  • 必填参数:
    • /ttsrole: text, role
    • /tts: text, ref_audio_path, prompt_lang
  • 可选参数: 其他均为可选,默认值从 roles/{role}/tts_infer.yaml 或 GPT_SoVITS/configs/tts_infer.yaml 获取
  • 优先级: POST 请求参数 > roles/{role}/tts_infer.yaml > 默认 GPT_SoVITS/configs/tts_infer.yaml

目录结构

GPT-SoVITS-roleapi/
├── api_role_v3.py # 本文件, API 主程序
├── GPT_SoVITS/ # GPT-SoVITS 核心库
│ └── configs/
│ └── tts_infer.yaml # 默认配置文件
├── roles/ # 角色配置目录
│ ├── role1/ # 示例角色 role1
│ │ ├── tts_infer.yaml # 角色配置文件(可选)
│ │ ├── model.ckpt # GPT 模型(可选)
│ │ ├── model.pth # SoVITS 模型(可选)
│ │ └── reference_audios/ # 角色参考音频目录
│ │ ├── zh/
│ │ │ ├── 【开心】voice1.wav
│ │ │ ├── 【开心】voice1.txt
│ │ ├── ja/
│ │ │ ├── 【开心】voice2.wav
│ │ │ ├── 【开心】voice2.txt
│ ├── role2/
│ │ ├── tts_infer.yaml
│ │ ├── model.ckpt
│ │ ├── model.pth
│ │ └── reference_audios/
│ │ ├── zh/
│ │ │ ├── 【开心】voice1.wav
│ │ │ ├── 【开心】voice1.txt
│ │ │ ├── 【悲伤】asdafasdas.wav
│ │ │ ├── 【悲伤】asdafasdas.txt
│ │ ├── ja/
│ │ │ ├── 【开心】voice2.wav
│ │ │ ├── 【开心】voice2.txt

text_lang, prompt_lang, prompt_text 选择逻辑 (/ttsrole)

  1. text_lang 选择逻辑:
    • 默认值: "auto"
    • 如果请求未提供 text_lang,视为 "auto"
    • 当 text_lang = "auto" 且存在 emotion 参数:
      • 从 roles/{role}/reference_audios 下所有语言文件夹中查找以 "【emotion】" 开头的音频
      • 随机选择一个匹配的音频,语言由音频所在文件夹确定
    • 当 text_lang 指定具体语言(如 "zh"):
      • 从 roles/{role}/reference_audios/{text_lang} 中选择音频
      • 如果指定语言无匹配音频,则尝试其他语言文件夹
  2. prompt_lang 选择逻辑:
    • 如果提供了 ref_audio_path,则需显式指定 prompt_lang
    • 如果未提供 ref_audio_path 且 text_lang = "auto" 且存在 emotion:
      • prompt_lang = 随机选择的音频所在语言文件夹名(如 "zh" 或 "ja")
    • 如果未提供 ref_audio_path 且 text_lang 指定具体语言:
      • prompt_lang = text_lang(如 "zh")
      • 如果 text_lang 无匹配音频,则为随机选择的音频所在语言
  3. prompt_text 选择逻辑:
    • 如果提供了 ref_audio_path(如 "/path/to/ref.wav"):
      • 检查文件名是否包含 "【xxx】" 前缀:
        • 如果有(如 "【开心】abc.wav"):
          • 若存在对应 .txt 文件(如 "【开心】abc.txt"),prompt_text = .txt 文件内容
          • 若无对应 .txt 文件,prompt_text = "abc"(去掉 "【开心】" 和 ".wav" 的部分)
        • 如果无 "【xxx】" 前缀:
          • 若存在对应 .txt 文件(如 "ref.txt"),prompt_text = .txt 文件内容
          • 若无对应 .txt 文件,prompt_text = "ref"(去掉 ".wav" 的部分)
    • 如果未提供 ref_audio_path:
      • 从 roles/{role}/reference_audios 中选择音频(基于 text_lang 和 emotion):
        • 优先匹配 "【emotion】" 前缀的音频(如 "【开心】voice1.wav")
        • 若存在对应 .txt 文件(如 "【开心】voice1.txt"),prompt_text = .txt 文件内容
        • 若无对应 .txt 文件,prompt_text = "voice1"(去掉 "【开心】" 和 ".wav" 的部分)
        • 未匹配 emotion 则随机选择一个音频,逻辑同上

讲解

  1. 必填参数:
    • /ttsrole: text, role
    • /tts: text, ref_audio_path, prompt_lang
  2. 音频选择 (/ttsrole):
    • 若提供 ref_audio_path,则使用它
    • 否则根据 role、text_lang、emotion 从 roles/{role}/reference_audios 中选择
    • text_lang = "auto" 时,若有 emotion,则跨语言匹配 "【emotion】" 前缀音频
    • emotion 匹配 "【emotion】" 前缀音频,未匹配则随机选择
  3. 设备选择:
    • 默认尝试检测显卡(torch.cuda.is_available()),若可用则用 "cuda",否则 "cpu"
    • 若缺少 torch 依赖或检测失败,回退到 "cpu"
    • POST 参数 device, t2s_model_device, vits_model_device 可强制指定设备,优先级最高
  4. 配置文件:
    • 默认加载 GPT_SoVITS/configs/tts_infer.yaml
    • 若 roles/{role}/tts_infer.yaml 存在且未被请求参数覆盖,则使用它 (/ttsrole)
    • 请求参数(如 top_k, bert_base_path)覆盖所有配置文件
  5. 返回格式:
    • 成功时返回音频流 (Response 或 StreamingResponse)
    • 失败时返回 JSON,包含错误消息和可能的异常详情
  6. 运行:
    • python api_role_v3.py -a 127.0.0.1 -p 9880
    • 检查启动日志确认设备
  7. 模型版本切换:
    • POST 请求中通过 "version" 参数指定 "v2" 或 "v3",动态影响推理逻辑。

@sunosv
Copy link

sunosv commented Mar 8, 2025

要是能单独 有个接口能切换模型就好了,除用role 情况之外 比如请求/ 时 好像只能用当时启动时传入的模型

@spawner1145
Copy link
Author

要是能单独 有个接口能切换模型就好了,除用role 情况之外 比如请求/ 时 好像只能用当时启动时传入的模型

因为就是多加了一个接口,原来的那些保留了😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants