Initial commit: FunASR Speech Recognition Toolkit
Update API Documentation / build-api-docs (push) Has been cancelled

Add complete FunASR codebase including models, runtime, and documentation.
This commit is contained in:
freedakgmail
2026-07-09 22:38:58 +08:00
commit 6116b1f3c6
3683 changed files with 990984 additions and 0 deletions
View File
@@ -0,0 +1,20 @@
def download_dataset():
"""Download dataset."""
pass
def download_dataset_from_ms(**kwargs):
"""Download dataset from ms.
Args:
**kwargs: Additional keyword arguments.
"""
from modelscope.msdatasets import MsDataset
dataset_name = kwargs.get("dataset_name", "speech_asr/speech_asr_aishell1_trainsets")
subset_name = kwargs.get("subset_name", "default")
split = kwargs.get("split", "train")
data_dump_dir = kwargs.get("data_dump_dir", None)
ds = MsDataset.load(
dataset_name=dataset_name, subset_name=subset_name, split=split, cache_dir=data_dump_dir
)
+292
View File
@@ -0,0 +1,292 @@
import logging
import os
import json
from omegaconf import OmegaConf, DictConfig
from funasr.download.name_maps_from_hub import name_maps_ms, name_maps_hf, name_maps_openai
def download_model(**kwargs):
"""Download model from hub and parse its configuration.
Resolves model name aliases, downloads from ModelScope or HuggingFace,
reads config.yaml and configuration.json, and returns complete kwargs
for model instantiation.
Args:
**kwargs: Must include 'model' (str). Optional: 'hub', 'model_revision',
'is_training', etc.
Returns:
dict: Complete kwargs with resolved paths, model class name, and config.
"""
hub = kwargs.get("hub", "ms")
if hub == "ms" or hub == "modelscope":
kwargs = download_from_ms(**kwargs)
elif hub == "hf" or hub == "huggingface":
kwargs = download_from_hf(**kwargs)
elif hub == "openai":
model_or_path = kwargs.get("model")
if os.path.exists(model_or_path):
# local path
kwargs["model_path"] = model_or_path
kwargs["model"] = "WhisperWarp"
else:
# model name
if model_or_path in name_maps_openai:
model_or_path = name_maps_openai[model_or_path]
kwargs["model_path"] = model_or_path
return kwargs
def download_from_ms(**kwargs):
"""Download from ms.
Args:
**kwargs: Additional keyword arguments.
"""
model_or_path = kwargs.get("model")
if model_or_path in name_maps_ms:
model_or_path = name_maps_ms[model_or_path]
model_revision = kwargs.get("model_revision", "master")
if not os.path.exists(model_or_path) and "model_path" not in kwargs:
try:
model_or_path = get_or_download_model_dir(
model_or_path,
model_revision,
is_training=kwargs.get("is_training"),
check_latest=kwargs.get("check_latest", True),
)
except Exception as e:
print(f"Download: {model_or_path} failed!: {e}")
kwargs["model_path"] = model_or_path if "model_path" not in kwargs else kwargs["model_path"]
model_or_path = kwargs["model_path"]
if os.path.exists(os.path.join(model_or_path, "configuration.json")):
with open(os.path.join(model_or_path, "configuration.json"), "r", encoding="utf-8") as f:
conf_json = json.load(f)
cfg = {}
if "file_path_metas" in conf_json:
add_file_root_path(model_or_path, conf_json["file_path_metas"], cfg)
# cfg.update(kwargs)
cfg = OmegaConf.merge(cfg, kwargs)
if "config" in cfg:
config = OmegaConf.load(cfg["config"])
kwargs = OmegaConf.merge(config, cfg)
kwargs["model"] = config["model"]
elif os.path.exists(os.path.join(model_or_path, "config.yaml")):
config = OmegaConf.load(os.path.join(model_or_path, "config.yaml"))
kwargs = OmegaConf.merge(config, kwargs)
init_param = os.path.join(model_or_path, "model.pt")
if "init_param" not in kwargs or not os.path.exists(kwargs["init_param"]):
kwargs["init_param"] = init_param
assert os.path.exists(kwargs["init_param"]), "init_param does not exist"
if os.path.exists(os.path.join(model_or_path, "tokens.txt")):
kwargs["tokenizer_conf"]["token_list"] = os.path.join(model_or_path, "tokens.txt")
if os.path.exists(os.path.join(model_or_path, "tokens.json")):
kwargs["tokenizer_conf"]["token_list"] = os.path.join(model_or_path, "tokens.json")
if os.path.exists(os.path.join(model_or_path, "seg_dict")):
kwargs["tokenizer_conf"]["seg_dict"] = os.path.join(model_or_path, "seg_dict")
if os.path.exists(os.path.join(model_or_path, "bpe.model")):
kwargs["tokenizer_conf"]["bpemodel"] = os.path.join(model_or_path, "bpe.model")
kwargs["model"] = config["model"]
if os.path.exists(os.path.join(model_or_path, "am.mvn")):
kwargs["frontend_conf"]["cmvn_file"] = os.path.join(model_or_path, "am.mvn")
if os.path.exists(os.path.join(model_or_path, "jieba_usr_dict")):
kwargs["jieba_usr_dict"] = os.path.join(model_or_path, "jieba_usr_dict")
if isinstance(kwargs, DictConfig):
kwargs = OmegaConf.to_container(kwargs, resolve=True)
logging.warning(f'trust_remote_code: {kwargs.get("trust_remote_code", False)}')
if os.path.exists(os.path.join(model_or_path, "requirements.txt")) and kwargs.get(
"trust_remote_code", False
):
requirements = os.path.join(model_or_path, "requirements.txt")
print(f"Detect model requirements, begin to install it: {requirements}")
from funasr.utils.install_model_requirements import install_requirements
install_requirements(requirements)
if kwargs.get("trust_remote_code", False):
from funasr.utils.dynamic_import import import_module_from_path
model_code = kwargs.get("remote_code", "model")
import_module_from_path(model_code)
# from funasr.register import tables
# tables.print("model")
return kwargs
def download_from_hf(**kwargs):
"""Download from hf.
Args:
**kwargs: Additional keyword arguments.
"""
model_or_path = kwargs.get("model")
if model_or_path in name_maps_hf:
model_or_path = name_maps_hf[model_or_path]
model_revision = kwargs.get("model_revision", "master")
if not os.path.exists(model_or_path) and "model_path" not in kwargs:
try:
model_or_path = get_or_download_model_dir_hf(
model_or_path,
model_revision,
is_training=kwargs.get("is_training"),
check_latest=kwargs.get("check_latest", True),
)
except Exception as e:
print(f"Download: {model_or_path} failed!: {e}")
kwargs["model_path"] = model_or_path if "model_path" not in kwargs else kwargs["model_path"]
if os.path.exists(os.path.join(model_or_path, "configuration.json")):
with open(os.path.join(model_or_path, "configuration.json"), "r", encoding="utf-8") as f:
conf_json = json.load(f)
cfg = {}
if "file_path_metas" in conf_json:
add_file_root_path(model_or_path, conf_json["file_path_metas"], cfg)
cfg.update(kwargs)
if "config" in cfg:
config = OmegaConf.load(cfg["config"])
kwargs = OmegaConf.merge(config, cfg)
kwargs["model"] = config["model"]
elif os.path.exists(os.path.join(model_or_path, "config.yaml")) and os.path.exists(
os.path.join(model_or_path, "model.pt")
):
config = OmegaConf.load(os.path.join(model_or_path, "config.yaml"))
kwargs = OmegaConf.merge(config, kwargs)
init_param = os.path.join(model_or_path, "model.pt")
kwargs["init_param"] = init_param
if os.path.exists(os.path.join(model_or_path, "tokens.txt")):
kwargs["tokenizer_conf"]["token_list"] = os.path.join(model_or_path, "tokens.txt")
if os.path.exists(os.path.join(model_or_path, "tokens.json")):
kwargs["tokenizer_conf"]["token_list"] = os.path.join(model_or_path, "tokens.json")
if os.path.exists(os.path.join(model_or_path, "seg_dict")):
kwargs["tokenizer_conf"]["seg_dict"] = os.path.join(model_or_path, "seg_dict")
if os.path.exists(os.path.join(model_or_path, "bpe.model")):
kwargs["tokenizer_conf"]["bpemodel"] = os.path.join(model_or_path, "bpe.model")
kwargs["model"] = config["model"]
if os.path.exists(os.path.join(model_or_path, "am.mvn")):
kwargs["frontend_conf"]["cmvn_file"] = os.path.join(model_or_path, "am.mvn")
if os.path.exists(os.path.join(model_or_path, "jieba_usr_dict")):
kwargs["jieba_usr_dict"] = os.path.join(model_or_path, "jieba_usr_dict")
if isinstance(kwargs, DictConfig):
kwargs = OmegaConf.to_container(kwargs, resolve=True)
logging.warning(f'trust_remote_code: {kwargs.get("trust_remote_code", False)}')
if os.path.exists(os.path.join(model_or_path, "requirements.txt")) and kwargs.get(
"trust_remote_code", False
):
requirements = os.path.join(model_or_path, "requirements.txt")
print(f"Detect model requirements, begin to install it: {requirements}")
from funasr.utils.install_model_requirements import install_requirements
install_requirements(requirements)
return kwargs
def add_file_root_path(model_or_path: str, file_path_metas: dict, cfg={}):
"""Add file root path.
Args:
model_or_path: TODO.
file_path_metas: TODO.
cfg: Configuration overrides.
"""
if isinstance(file_path_metas, dict):
if isinstance(cfg, list):
cfg.append({})
for k, v in file_path_metas.items():
if isinstance(v, str):
p = os.path.join(model_or_path, v)
if os.path.exists(p):
if isinstance(cfg, dict):
cfg[k] = p
elif isinstance(cfg, list):
# if len(cfg) == 0:
# cfg.append({})
cfg[-1][k] = p
elif isinstance(v, dict):
if isinstance(cfg, dict):
if k not in cfg:
cfg[k] = {}
add_file_root_path(model_or_path, v, cfg[k])
# elif isinstance(cfg, list):
# cfg.append({})
# add_file_root_path(model_or_path, v, cfg)
elif isinstance(v, (list, tuple)):
for i, vv in enumerate(v):
if k not in cfg:
cfg[k] = []
if isinstance(vv, str):
p = os.path.join(model_or_path, vv)
# file_path_metas[i] = p
if os.path.exists(p):
if isinstance(cfg[k], dict):
cfg[k] = p
elif isinstance(cfg[k], list):
cfg[k].append(p)
elif isinstance(vv, dict):
add_file_root_path(model_or_path, vv, cfg[k])
return cfg
def get_or_download_model_dir(
model,
model_revision=None,
is_training=False,
check_latest=True,
):
"""Get local model directory or download model if necessary.
Args:
model (str): model id or path to local model directory.
model_revision (str, optional): model version number.
:param is_training:
"""
from modelscope.hub.check_model import check_local_model_is_latest
from modelscope.hub.snapshot_download import snapshot_download
from modelscope.utils.constant import Invoke, ThirdParty
key = Invoke.LOCAL_TRAINER if is_training else Invoke.PIPELINE
if os.path.exists(model) and check_latest:
model_cache_dir = model if os.path.isdir(model) else os.path.dirname(model)
try:
check_local_model_is_latest(
model_cache_dir, user_agent={Invoke.KEY: key, ThirdParty.KEY: "funasr"}
)
except:
print("could not check the latest version")
else:
model_cache_dir = snapshot_download(
model, revision=model_revision, user_agent={Invoke.KEY: key, ThirdParty.KEY: "funasr"}
)
return model_cache_dir
def get_or_download_model_dir_hf(
model,
model_revision=None,
is_training=False,
check_latest=True,
):
"""Get local model directory or download model if necessary.
Args:
model (str): model id or path to local model directory.
model_revision (str, optional): model version number.
:param is_training:
"""
from huggingface_hub import snapshot_download
model_cache_dir = snapshot_download(model)
return model_cache_dir
+405
View File
@@ -0,0 +1,405 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import contextlib
import os
import tempfile
from abc import ABCMeta, abstractmethod
from pathlib import Path
from typing import Generator, Union
import requests
from urllib.parse import urlparse
def download_from_url(url):
"""Download from url.
Args:
url: TODO.
"""
result = urlparse(url)
file_path = None
if result.scheme is not None and len(result.scheme) > 0:
storage = HTTPStorage()
# bytes
data = storage.read(url)
work_dir = tempfile.TemporaryDirectory().name
if not os.path.exists(work_dir):
os.makedirs(work_dir)
file_path = os.path.join(work_dir, os.path.basename(url))
with open(file_path, "wb") as fb:
fb.write(data)
assert file_path is not None, f"failed to download: {url}"
return file_path
class Storage(metaclass=ABCMeta):
"""Abstract class of storage.
All backends need to implement two apis: ``read()`` and ``read_text()``.
``read()`` reads the file as a byte stream and ``read_text()`` reads
the file as texts.
"""
@abstractmethod
def read(self, filepath: str):
"""Read.
Args:
filepath: TODO.
"""
pass
@abstractmethod
def read_text(self, filepath: str):
"""Read text.
Args:
filepath: TODO.
"""
pass
@abstractmethod
def write(self, obj: bytes, filepath: Union[str, Path]) -> None:
"""Write.
Args:
obj: TODO.
filepath: TODO.
"""
pass
@abstractmethod
def write_text(self, obj: str, filepath: Union[str, Path], encoding: str = "utf-8") -> None:
"""Write text.
Args:
obj: TODO.
filepath: TODO.
encoding: TODO.
"""
pass
class LocalStorage(Storage):
"""Local hard disk storage"""
def read(self, filepath: Union[str, Path]) -> bytes:
"""Read data from a given ``filepath`` with 'rb' mode.
Args:
filepath (str or Path): Path to read data.
Returns:
bytes: Expected bytes object.
"""
with open(filepath, "rb") as f:
content = f.read()
return content
def read_text(self, filepath: Union[str, Path], encoding: str = "utf-8") -> str:
"""Read data from a given ``filepath`` with 'r' mode.
Args:
filepath (str or Path): Path to read data.
encoding (str): The encoding format used to open the ``filepath``.
Default: 'utf-8'.
Returns:
str: Expected text reading from ``filepath``.
"""
with open(filepath, "r", encoding=encoding) as f:
value_buf = f.read()
return value_buf
def write(self, obj: bytes, filepath: Union[str, Path]) -> None:
"""Write data to a given ``filepath`` with 'wb' mode.
Note:
``write`` will create a directory if the directory of ``filepath``
does not exist.
Args:
obj (bytes): Data to be written.
filepath (str or Path): Path to write data.
"""
dirname = os.path.dirname(filepath)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname, exist_ok=True)
with open(filepath, "wb") as f:
f.write(obj)
def write_text(self, obj: str, filepath: Union[str, Path], encoding: str = "utf-8") -> None:
"""Write data to a given ``filepath`` with 'w' mode.
Note:
``write_text`` will create a directory if the directory of
``filepath`` does not exist.
Args:
obj (str): Data to be written.
filepath (str or Path): Path to write data.
encoding (str): The encoding format used to open the ``filepath``.
Default: 'utf-8'.
"""
dirname = os.path.dirname(filepath)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname, exist_ok=True)
with open(filepath, "w", encoding=encoding) as f:
f.write(obj)
@contextlib.contextmanager
def as_local_path(self, filepath: Union[str, Path]) -> Generator[Union[str, Path], None, None]:
"""Only for unified API and do nothing."""
yield filepath
class HTTPStorage(Storage):
"""HTTP and HTTPS storage."""
def read(self, url):
# TODO @wenmeng.zwm add progress bar if file is too large
"""Read.
Args:
url: TODO.
"""
r = requests.get(url)
r.raise_for_status()
return r.content
def read_text(self, url):
"""Read text.
Args:
url: TODO.
"""
r = requests.get(url)
r.raise_for_status()
return r.text
@contextlib.contextmanager
def as_local_path(self, filepath: str) -> Generator[Union[str, Path], None, None]:
"""Download a file from ``filepath``.
``as_local_path`` is decorated by :meth:`contextlib.contextmanager`. It
can be called with ``with`` statement, and when exists from the
``with`` statement, the temporary path will be released.
Args:
filepath (str): Download a file from ``filepath``.
Examples:
>>> storage = HTTPStorage()
>>> # After existing from the ``with`` clause,
>>> # the path will be removed
>>> with storage.get_local_path('http://path/to/file') as path:
... # do something here
"""
try:
f = tempfile.NamedTemporaryFile(delete=False)
f.write(self.read(filepath))
f.close()
yield f.name
finally:
os.remove(f.name)
def write(self, obj: bytes, url: Union[str, Path]) -> None:
"""Write.
Args:
obj: TODO.
url: TODO.
"""
raise NotImplementedError("write is not supported by HTTP Storage")
def write_text(self, obj: str, url: Union[str, Path], encoding: str = "utf-8") -> None:
"""Write text.
Args:
obj: TODO.
url: TODO.
encoding: TODO.
"""
raise NotImplementedError("write_text is not supported by HTTP Storage")
class OSSStorage(Storage):
"""OSS storage."""
def __init__(self, oss_config_file=None):
# read from config file or env var
"""Initialize OSSStorage.
Args:
oss_config_file: TODO.
"""
raise NotImplementedError("OSSStorage.__init__ to be implemented in the future")
def read(self, filepath):
"""Read.
Args:
filepath: TODO.
"""
raise NotImplementedError("OSSStorage.read to be implemented in the future")
def read_text(self, filepath, encoding="utf-8"):
"""Read text.
Args:
filepath: TODO.
encoding: TODO.
"""
raise NotImplementedError("OSSStorage.read_text to be implemented in the future")
@contextlib.contextmanager
def as_local_path(self, filepath: str) -> Generator[Union[str, Path], None, None]:
"""Download a file from ``filepath``.
``as_local_path`` is decorated by :meth:`contextlib.contextmanager`. It
can be called with ``with`` statement, and when exists from the
``with`` statement, the temporary path will be released.
Args:
filepath (str): Download a file from ``filepath``.
Examples:
>>> storage = OSSStorage()
>>> # After existing from the ``with`` clause,
>>> # the path will be removed
>>> with storage.get_local_path('http://path/to/file') as path:
... # do something here
"""
try:
f = tempfile.NamedTemporaryFile(delete=False)
f.write(self.read(filepath))
f.close()
yield f.name
finally:
os.remove(f.name)
def write(self, obj: bytes, filepath: Union[str, Path]) -> None:
"""Write.
Args:
obj: TODO.
filepath: TODO.
"""
raise NotImplementedError("OSSStorage.write to be implemented in the future")
def write_text(self, obj: str, filepath: Union[str, Path], encoding: str = "utf-8") -> None:
"""Write text.
Args:
obj: TODO.
filepath: TODO.
encoding: TODO.
"""
raise NotImplementedError("OSSStorage.write_text to be implemented in the future")
G_STORAGES = {}
class File(object):
_prefix_to_storage: dict = {
"oss": OSSStorage,
"http": HTTPStorage,
"https": HTTPStorage,
"local": LocalStorage,
}
@staticmethod
def _get_storage(uri):
"""Internal: get storage.
Args:
uri: TODO.
"""
assert isinstance(uri, str), f"uri should be str type, but got {type(uri)}"
if "://" not in uri:
# local path
storage_type = "local"
else:
prefix, _ = uri.split("://")
storage_type = prefix
assert storage_type in File._prefix_to_storage, (
f"Unsupported uri {uri}, valid prefixs: " f"{list(File._prefix_to_storage.keys())}"
)
if storage_type not in G_STORAGES:
G_STORAGES[storage_type] = File._prefix_to_storage[storage_type]()
return G_STORAGES[storage_type]
@staticmethod
def read(uri: str) -> bytes:
"""Read data from a given ``filepath`` with 'rb' mode.
Args:
filepath (str or Path): Path to read data.
Returns:
bytes: Expected bytes object.
"""
storage = File._get_storage(uri)
return storage.read(uri)
@staticmethod
def read_text(uri: Union[str, Path], encoding: str = "utf-8") -> str:
"""Read data from a given ``filepath`` with 'r' mode.
Args:
filepath (str or Path): Path to read data.
encoding (str): The encoding format used to open the ``filepath``.
Default: 'utf-8'.
Returns:
str: Expected text reading from ``filepath``.
"""
storage = File._get_storage(uri)
return storage.read_text(uri)
@staticmethod
def write(obj: bytes, uri: Union[str, Path]) -> None:
"""Write data to a given ``filepath`` with 'wb' mode.
Note:
``write`` will create a directory if the directory of ``filepath``
does not exist.
Args:
obj (bytes): Data to be written.
filepath (str or Path): Path to write data.
"""
storage = File._get_storage(uri)
return storage.write(obj, uri)
@staticmethod
def write_text(obj: str, uri: str, encoding: str = "utf-8") -> None:
"""Write data to a given ``filepath`` with 'w' mode.
Note:
``write_text`` will create a directory if the directory of
``filepath`` does not exist.
Args:
obj (str): Data to be written.
filepath (str or Path): Path to write data.
encoding (str): The encoding format used to open the ``filepath``.
Default: 'utf-8'.
"""
storage = File._get_storage(uri)
return storage.write_text(obj, uri)
@contextlib.contextmanager
def as_local_path(uri: str) -> Generator[Union[str, Path], None, None]:
"""Only for unified API and do nothing."""
storage = File._get_storage(uri)
with storage.as_local_path(uri) as local_path:
yield local_path
+57
View File
@@ -0,0 +1,57 @@
name_maps_ms = {
"paraformer": "iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch",
"paraformer-zh": "iic/speech_seaco_paraformer_large_asr_nat-zh-cn-16k-common-vocab8404-pytorch",
"paraformer-en": "iic/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020",
"paraformer-en-spk": "iic/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020",
"paraformer-zh-streaming": "iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online",
"fsmn-vad": "iic/speech_fsmn_vad_zh-cn-16k-common-pytorch",
"ct-punc": "iic/punc_ct-transformer_cn-en-common-vocab471067-large",
"ct-punc-c": "iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch",
"fa-zh": "iic/speech_timestamp_prediction-v1-16k-offline",
"cam++": "iic/speech_campplus_sv_zh-cn_16k-common",
"Whisper-large-v2": "iic/speech_whisper-large_asr_multilingual",
"Whisper-large-v3": "iic/Whisper-large-v3",
"Qwen-Audio": "Qwen/Qwen-Audio",
"emotion2vec_plus_large": "iic/emotion2vec_plus_large",
"emotion2vec_plus_base": "iic/emotion2vec_plus_base",
"emotion2vec_plus_seed": "iic/emotion2vec_plus_seed",
"Whisper-large-v3-turbo": "iic/Whisper-large-v3-turbo",
}
name_maps_hf = {
"paraformer": "funasr/paraformer-zh",
"paraformer-zh": "funasr/paraformer-zh",
"paraformer-en": "funasr/paraformer-zh",
"paraformer-zh-streaming": "funasr/paraformer-zh-streaming",
"fsmn-vad": "funasr/fsmn-vad",
"ct-punc": "funasr/ct-punc",
"ct-punc-c": "iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch",
"fa-zh": "funasr/fa-zh",
"cam++": "funasr/campplus",
"Whisper-large-v2": "iic/speech_whisper-large_asr_multilingual",
"Whisper-large-v3": "iic/Whisper-large-v3",
"Qwen-Audio": "Qwen/Qwen-Audio",
"emotion2vec_plus_large": "emotion2vec/emotion2vec_plus_large",
"iic/emotion2vec_plus_large": "emotion2vec/emotion2vec_plus_large",
"emotion2vec_plus_base": "emotion2vec/emotion2vec_plus_base",
"iic/emotion2vec_plus_base": "emotion2vec/emotion2vec_plus_base",
"emotion2vec_plus_seed": "emotion2vec/emotion2vec_plus_seed",
"iic/emotion2vec_plus_seed": "emotion2vec/emotion2vec_plus_seed",
"Whisper-large-v3-turbo": "iic/Whisper-large-v3-turbo",
}
name_maps_openai = {
"Whisper-tiny.en": "tiny.en",
"Whisper-tiny": "tiny",
"Whisper-base.en": "base.en",
"Whisper-base": "base",
"Whisper-small.en": "small.en",
"Whisper-small": "small",
"Whisper-medium.en": "medium.en",
"Whisper-medium": "medium",
"Whisper-large-v1": "large-v1",
"Whisper-large-v2": "large-v2",
"Whisper-large-v3": "large-v3",
"Whisper-large": "large",
"Whisper-large-v3-turbo": "turbo",
}
@@ -0,0 +1,59 @@
import os
import argparse
from pathlib import Path
from funasr.utils.type_utils import str2bool
def main():
"""Main."""
parser = argparse.ArgumentParser()
parser.add_argument("--model-name", type=str, required=True)
parser.add_argument("--export-dir", type=str, required=True)
parser.add_argument("--export", type=str2bool, default=True, help="whether to export model")
parser.add_argument("--type", type=str, default="onnx", help='["onnx", "torchscript", "bladedisc"]')
parser.add_argument("--device", type=str, default="cpu", help='["cpu", "cuda"]')
parser.add_argument("--quantize", type=str2bool, default=False, help="export quantized model")
parser.add_argument("--fallback-num", type=int, default=0, help="amp fallback number")
parser.add_argument("--audio_in", type=str, default=None, help='["wav", "wav.scp"]')
parser.add_argument("--model_revision", type=str, default=None, help="model_revision")
parser.add_argument("--calib_num", type=int, default=200, help="calib max num")
args = parser.parse_args()
model_dir = args.model_name
output_dir = args.model_name
if not Path(args.model_name).exists():
from modelscope.hub.snapshot_download import snapshot_download
try:
model_dir = snapshot_download(
args.model_name, cache_dir=args.export_dir, revision=args.model_revision
)
output_dir = os.path.join(args.export_dir, args.model_name)
except:
raise "model_dir must be model_name in modelscope or local path downloaded from modelscope, but is {}".format(
model_dir
)
if args.export:
model_file = os.path.join(model_dir, "model.onnx")
if args.quantize:
model_file = os.path.join(model_dir, "model_quant.onnx")
if args.type == "torchscript":
model_file = os.path.join(model_dir, "model.torchscript")
args.device = "cuda"
elif args.type == "bladedisc":
model_file = os.path.join(model_dir, "model_blade.torchscript")
args.device = "cuda"
if not os.path.exists(model_file):
print("model is not exist, begin to export " + model_file)
from funasr import AutoModel
export_model = AutoModel(model=args.model_name, output_dir=output_dir, device=args.device)
export_model.export(
quantize=args.quantize,
type=args.type,
)
if __name__ == "__main__":
main()