From 8f60860419e7997e4d8dddff5a95761c7ef778aa Mon Sep 17 00:00:00 2001 From: Zhengshou Lai Date: Sun, 26 Jul 2026 01:07:06 +0800 Subject: [PATCH] feat(voice): switch TTS to Seed 2.0 uranus voices Use classic male/female and sunny-sweet speakers with seed-tts-2.0 resource id. --- AGENTS.md | 4 ++-- mytoolkit/api/voice.py | 26 +++++++++++++++++++------- mytoolkit/commands/voice.py | 14 +++++++------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4e08dbf..f128880 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,10 +68,10 @@ mytoolkit env export # 导出为 shell export 语句 ```bash mytoolkit voice tts "你好,世界" mytoolkit voice tts -f script.txt -mytoolkit voice tts "文本" -v zh_male_wennuanahu_moon_bigtts --format mp3 --speed 10 -o output.mp3 +mytoolkit voice tts "文本" -v zh_female_xiaohe_uranus_bigtts --format mp3 --speed 10 -o output.mp3 ``` -可用音色:`zh_female_cancan_mars_bigtts`、`zh_female_shuangkuaisisi_moon_bigtts`、`zh_male_wennuanahu_moon_bigtts`(默认)、`zh_male_sunwukong_moon_bigtts` +可用音色:`zh_male_m191_uranus_bigtts`(经典男声)、`zh_female_xiaohe_uranus_bigtts`(经典女声,默认)、`ICL_uranus_zh_female_yuanqitianmei_tob`(阳光甜妹) 格式:`mp3`(默认)、`wav`、`pcm` diff --git a/mytoolkit/api/voice.py b/mytoolkit/api/voice.py index c099e46..64c8883 100644 --- a/mytoolkit/api/voice.py +++ b/mytoolkit/api/voice.py @@ -5,24 +5,36 @@ import json import uuid from pathlib import Path -_RESOURCE_ID = "volc.service_type.10029" +# TTS 1.0 (moon/mars) vs 2.0 (uranus / ICL_uranus) +_RESOURCE_TTS_1 = "volc.service_type.10029" +_RESOURCE_TTS_2 = "seed-tts-2.0" _ENDPOINT = "wss://openspeech.bytedance.com/api/v3/tts/unidirectional/stream" +# Product labels: 经典男声 / 经典女声 / 阳光甜妹 _VOICE_CHOICES = [ - "zh_female_cancan_mars_bigtts", - "zh_female_shuangkuaisisi_moon_bigtts", - "zh_male_wennuanahu_moon_bigtts", - "zh_male_sunwukong_moon_bigtts", + "zh_male_m191_uranus_bigtts", + "zh_female_xiaohe_uranus_bigtts", + "ICL_uranus_zh_female_yuanqitianmei_tob", ] +_DEFAULT_VOICE = "zh_female_xiaohe_uranus_bigtts" + _FORMAT_CHOICES = ["mp3", "wav", "pcm"] +def resource_id_for_speaker(speaker: str) -> str: + """Pick Volcengine resource id for a speaker.""" + s = speaker or "" + if "uranus" in s or s.startswith("ICL_uranus_"): + return _RESOURCE_TTS_2 + return _RESOURCE_TTS_1 + + def synthesize_tts( appid: str, token: str, text: str, - speaker: str = "zh_male_wennuanahu_moon_bigtts", + speaker: str = _DEFAULT_VOICE, fmt: str = "mp3", speech_rate: int = 0, output_path: str = "output.mp3", @@ -42,7 +54,7 @@ def synthesize_tts( headers = { "X-Api-App-Id": appid, "X-Api-Access-Key": token, - "X-Api-Resource-Id": _RESOURCE_ID, + "X-Api-Resource-Id": resource_id_for_speaker(speaker), "X-Api-Connect-Id": str(uuid.uuid4()), } diff --git a/mytoolkit/commands/voice.py b/mytoolkit/commands/voice.py index b4e2f66..6cd8495 100644 --- a/mytoolkit/commands/voice.py +++ b/mytoolkit/commands/voice.py @@ -13,11 +13,11 @@ from mytoolkit.config import config from mytoolkit.utils import handle_errors _VOICE_CHOICES = [ - "zh_female_cancan_mars_bigtts", - "zh_female_shuangkuaisisi_moon_bigtts", - "zh_male_wennuanahu_moon_bigtts", - "zh_male_sunwukong_moon_bigtts", + "zh_male_m191_uranus_bigtts", # 经典男声 (云舟 2.0) + "zh_female_xiaohe_uranus_bigtts", # 经典女声 (小何 2.0) + "ICL_uranus_zh_female_yuanqitianmei_tob", # 阳光甜妹 (元气甜妹 2.0) ] +_DEFAULT_VOICE = "zh_female_xiaohe_uranus_bigtts" _FORMAT_CHOICES = ["mp3", "wav", "pcm"] @@ -73,7 +73,7 @@ def voice(): "--voice", "speaker", type=click.Choice(_VOICE_CHOICES), - default="zh_male_wennuanahu_moon_bigtts", + default=_DEFAULT_VOICE, help="音色", ) @click.option("--format", "fmt", type=click.Choice(_FORMAT_CHOICES), default="mp3", help="输出格式") @@ -185,7 +185,7 @@ def _natural_sort_key(path: Path): @voice.command("tts-batch") @click.argument("text_dir", type=click.Path(exists=True, file_okay=False)) -@click.option("--voice", "speaker", type=click.Choice(_VOICE_CHOICES), default="zh_male_wennuanahu_moon_bigtts") +@click.option("--voice", "speaker", type=click.Choice(_VOICE_CHOICES), default=_DEFAULT_VOICE) @click.option("--output-dir", "-o", type=click.Path(), help="输出目录(默认与输入相同)") @click.option("--format", "fmt", type=click.Choice(_FORMAT_CHOICES), default="mp3") @handle_errors @@ -213,7 +213,7 @@ def tts_batch_cmd(text_dir, speaker, output_dir, fmt): @voice.command("tts-script") @click.argument("script", type=click.Path(exists=True)) @click.option("--output-dir", "-o", type=click.Path(), default="audio") -@click.option("--voice", "speaker", type=click.Choice(_VOICE_CHOICES), default="zh_male_wennuanahu_moon_bigtts") +@click.option("--voice", "speaker", type=click.Choice(_VOICE_CHOICES), default=_DEFAULT_VOICE) @click.option("--prefix", "-p", default="page") @click.option("--zero-pad", "-z", type=int, default=2) @click.option("--format", "fmt", type=click.Choice(_FORMAT_CHOICES), default="mp3")