mirror of https://github.com/rhasspy/piper
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.6 KiB
Python
156 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
import argparse
|
|
import logging
|
|
from collections import defaultdict
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
|
|
@dataclass
|
|
class Voice:
|
|
lang_family: str
|
|
lang_code: str
|
|
dataset: str
|
|
quality: str
|
|
model_url: str
|
|
config_url: str
|
|
|
|
|
|
@dataclass
|
|
class Language:
|
|
native: str
|
|
english: str
|
|
country: str
|
|
|
|
|
|
_LANGUAGES = {
|
|
"ar_JO": Language("العربية", "Arabic", "Jordan"),
|
|
"ca_ES": Language("Català", "Catalan", "Spain"),
|
|
"cs_CZ": Language("Čeština", "Czech", "Czech Republic"),
|
|
"da_DK": Language("Dansk", "Danish", "Denmark"),
|
|
"de_DE": Language("Deutsch", "German", "Germany"),
|
|
"el_GR": Language("Ελληνικά", "Greek", "Greece"),
|
|
"en_GB": Language("English", "English", "Great Britain"),
|
|
"en_US": Language("English", "English", "United States"),
|
|
"es_ES": Language("Español", "Spanish", "Spain"),
|
|
"es_MX": Language("Español", "Spanish", "Mexico"),
|
|
"fa_IR": Language("فارسی", "Farsi", "Iran"),
|
|
"fi_FI": Language("Suomi", "Finnish", "Finland"),
|
|
"fr_FR": Language("Français", "French", "France"),
|
|
"is_IS": Language("íslenska", "Icelandic", "Iceland"),
|
|
"it_IT": Language("Italiano", "Italian", "Italy"),
|
|
"hu_HU": Language("Magyar", "Hungarian", "Hungary"),
|
|
"ka_GE": Language("ქართული ენა", "Georgian", "Georgia"),
|
|
"kk_KZ": Language("қазақша", "Kazakh", "Kazakhstan"),
|
|
"lb_LU": Language("Lëtzebuergesch", "Luxembourgish", "Luxembourg"),
|
|
"ne_NP": Language("नेपाली", "Nepali", "Nepal"),
|
|
"nl_BE": Language("Nederlands", "Dutch", "Belgium"),
|
|
"nl_NL": Language("Nederlands", "Dutch", "Netherlands"),
|
|
"no_NO": Language("Norsk", "Norwegian", "Norway"),
|
|
"pl_PL": Language("Polski", "Polish", "Poland"),
|
|
"pt_BR": Language("Português", "Portuguese", "Brazil"),
|
|
"pt_PT": Language("Português", "Portuguese", "Portugal"),
|
|
"ro_RO": Language("Română", "Romanian", "Romania"),
|
|
"ru_RU": Language("Русский", "Russian", "Russia"),
|
|
"sk_SK": Language("Slovenčina", "Slovak", "Slovakia"),
|
|
"sl_SI": Language("Slovenščina", "Slovenian", "Slovenia"),
|
|
"sr_RS": Language("srpski", "Serbian", "Serbia"),
|
|
"sv_SE": Language("Svenska", "Swedish", "Sweden"),
|
|
"sw_CD": Language("Kiswahili", "Swahili", "Democratic Republic of the Congo"),
|
|
"tr_TR": Language("Türkçe", "Turkish", "Turkey"),
|
|
"uk_UA": Language("украї́нська мо́ва", "Ukrainian", "Ukraine"),
|
|
"vi_VN": Language("Tiếng Việt", "Vietnamese", "Vietnam"),
|
|
"zh_CN": Language("简体中文", "Chinese", "China"),
|
|
}
|
|
|
|
_QUALITY = {"x_low": 0, "low": 1, "medium": 2, "high": 3}
|
|
|
|
|
|
_LOGGER = logging.getLogger()
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"--piper-voices", required=True, help="Path to piper-voices root"
|
|
)
|
|
parser.add_argument(
|
|
"--model-url-format",
|
|
default="https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/{lang_family}/{lang_code}/{dataset}/{quality}/{lang_code}-{dataset}-{quality}.onnx?download=true",
|
|
help="URL format for models with lang_family, lang_code, dataset, and quality",
|
|
)
|
|
parser.add_argument(
|
|
"--config-url-format",
|
|
default="https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/{lang_family}/{lang_code}/{dataset}/{quality}/{lang_code}-{dataset}-{quality}.onnx.json?download=true",
|
|
help="URL format for configs with lang_family, lang_code, dataset, and quality",
|
|
)
|
|
args = parser.parse_args()
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
voices_by_lang_code = defaultdict(list)
|
|
piper_voices = Path(args.piper_voices)
|
|
for onnx_path in piper_voices.rglob("*.onnx"):
|
|
_LOGGER.debug(onnx_path)
|
|
parts = onnx_path.stem.split("-")
|
|
if len(parts) != 3:
|
|
_LOGGER.warning("Skipping %s", onnx_path)
|
|
continue
|
|
|
|
lang_code, dataset, quality = parts
|
|
assert lang_code in _LANGUAGES, f"Missing {lang_code}"
|
|
lang_family = lang_code.split("_")[0]
|
|
model_url = args.model_url_format.format(
|
|
lang_family=lang_family,
|
|
lang_code=lang_code,
|
|
dataset=dataset,
|
|
quality=quality,
|
|
)
|
|
config_url = args.config_url_format.format(
|
|
lang_family=lang_family,
|
|
lang_code=lang_code,
|
|
dataset=dataset,
|
|
quality=quality,
|
|
)
|
|
|
|
voices_by_lang_code[lang_code].append(
|
|
Voice(
|
|
lang_family=lang_family,
|
|
lang_code=lang_code,
|
|
dataset=dataset,
|
|
quality=quality,
|
|
model_url=model_url,
|
|
config_url=config_url,
|
|
)
|
|
)
|
|
|
|
print("# Voices")
|
|
print("")
|
|
|
|
for lang_code in sorted(voices_by_lang_code):
|
|
lang_info = _LANGUAGES[lang_code]
|
|
if lang_code.startswith("en_"):
|
|
print("*", lang_info.english, f"({lang_code})")
|
|
else:
|
|
print("*", lang_info.english, f"(`{lang_code}`, {lang_info.native})")
|
|
|
|
last_dataset = None
|
|
for voice in sorted(
|
|
voices_by_lang_code[lang_code],
|
|
key=lambda v: (v.dataset, _QUALITY[v.quality]),
|
|
):
|
|
if voice.dataset != last_dataset:
|
|
print(" *", voice.dataset)
|
|
last_dataset = voice.dataset
|
|
|
|
print(
|
|
" *",
|
|
voice.quality,
|
|
"-",
|
|
f"[[model]({voice.model_url})]",
|
|
f"[[config]({voice.config_url}.json)]",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|