【详细代码拆解】PaddleSpeech学习笔记(非流式)

目录

什么是PaddleSpeech

​编辑安装PaddleSpeech

语音识别部分(ASR)代码拆解

main.py

utils.py

装饰器stats_wrapper

_parse_args_

_note_one_stat

infer.py

__call__

_init_from_path


本篇文章记录了paddlespeech的学习历程,有问题或不足之处请评论区指出。

什么是PaddleSpeech

PaddleSpeech是一个基于飞桨PaddlePaddle的语音技术工具集,它支持语音识别、语音翻译、语音合成等多种语音和音频处理任务。

安装PaddleSpeech

参考我之前的博客PaddleSpeech安装及环境测试-CSDN博客

语音识别部分(ASR)代码拆解

main.py

from pathlib import Path
from paddlespeech.cli.asr.infer import ASRExecutor
# 初始化ASRExecutor(可能需要添加其他配置参数)
asr = ASRExecutor()
# 使用pathlib.Path来包装字符串路径
audio_path = Path("zh.wav")
# 使用ASRExecutor处理音频文件
result = asr(audio_file=audio_path)
# 输出识别结果
print(result)

设置断点进入result。ASRExecutor是PaddleSpeech中的一个类。

utils.py

装饰器stats_wrapper

装饰器stats_wrapper 的作用是为一个类的方法添加一个额外的功能:接受一个方法 executor_func 作为参数,并返回一个新的函数 _wrapper。**kwargs接受到字典{'audio_file': zh.wav}。通过_parse_args_解析参数,再进入_note_one_stat()。

def stats_wrapper(executor_func):
    def _warpper(self, *args, **kwargs):
        try:
            _note_one_stat(
                type(self).__name__, _parse_args(executor_func, *args,
                                                 **kwargs))
        except Exception:
            pass
        return executor_func(self, *args, **kwargs)

    return _warpper

_parse_args_

def _parse_args(func, *args, **kwargs):
    # FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)
    argspec = inspect.getfullargspec(func)

    keys = argspec[0]
    if keys[0] == 'self':  # Remove self pointer.
        keys = keys[1:]

    default_values = argspec[3]
    values = [None] * (len(keys) - len(default_values))
    values.extend(list(default_values))
    params = dict(zip(keys, values))

    for idx, v in enumerate(args):
        params[keys[idx]] = v
    for k, v in kwargs.items():
        params[k] = v

    return params

该函数通过inspect获取完整的签名信息,并对参数进行处理。

_note_one_stat

该函数主要判断这次调用PaddleSpeech是为了执行哪种任务。paddlespeech可以执行的任务有:

  1. 'asr': 自动语音识别(Automatic Speech Recognition)

  2. 'st': 语音翻译(Speech Translation)

  3. 'tts': 文本到语音(Text-to-Speech)

  4. 'cls': 分类任务(Classification)

  5. 'text': 文本处理任务。恢复文本标点

还可以传入其他参数进行任务细分。这部份可以查看paddlespeech的使用教程。

由于我使用的是asr任务,在标红色该行会进入soudfile.py文件,调用了soundfile库,这部分的逻辑主要就是文件的处理与参数传递,不多赘述。对zh.wav文件进行采样。_为采样后数据,sr为采样率。

上述流程运行完后,终于到了return executor_func(self, *args, **kwargs),进入infer.py文件

infer.py

__call__

装饰器stats_wrapper调用被修饰的函数__call__,这是ASRExecutor类中的函数

  • 转换 audio_file 为绝对路径。
  • 设置 PaddlePaddle 的设备。(该设备上为CPU)
  • 使用给定的参数从路径初始化模型和其他相关设置(_init_from_path)。
  • 检查音频文件是否符合要求(如采样率是否匹配),如果不满足且 force_yes 为 False,则退出程序。
  • 对音频进行预处理(preprocess
  • 执行音频识别(infer
  • 后处理识别的结果并返回(postprocess
  • 如果 rtf 为 True,则记录结束时间和音频的持续时间。
@stats_wrapper
    def __call__(self,
                 audio_file: os.PathLike,
                 model: str='conformer_wenetspeech',
                 lang: str='zh',
                 sample_rate: int=16000,
                 config: os.PathLike=None,
                 ckpt_path: os.PathLike=None,
                 decode_method: str='attention_rescoring',
                 num_decoding_left_chunks: int=-1,
                 force_yes: bool=False,
                 rtf: bool=False,
                 device=paddle.get_device()):
        """
        Python API to call an executor.
        """
        audio_file = os.path.abspath(audio_file)
        paddle.set_device(device)
        self._init_from_path(model, lang, sample_rate, config, decode_method,
                             num_decoding_left_chunks, ckpt_path)
        if not self._check(audio_file, sample_rate, force_yes):
            sys.exit(-1)
        if rtf:
            k = self.__class__.__name__
            CLI_TIMER[k]['start'].append(time.time())

        self.preprocess(model, audio_file)
        self.infer(model)
        res = self.postprocess()  # Retrieve result of asr.

        if rtf:
            CLI_TIMER[k]['end'].append(time.time())
            audio, audio_sample_rate = soundfile.read(
                audio_file, dtype="int16", always_2d=True)
            CLI_TIMER[k]['extra'].append(audio.shape[0] / audio_sample_rate)

        return res

_init_from_path

省略该函数中路径处理部分。该部分为模型初始化。

*创建一个新的 `CfgNode` 对象,该对象通常用于配置管理,并允许在运行时添加新的配置参数(因为 `new_allowed=True`)。 使用 `merge_from_file` 方法从指定的配置文件路径 `self.cfg_path` 中加载配置。

*如果 `spm_model_prefix` 存在,则更新其路径以包含 `self.res_path`。 * 创建一个 `TextFeaturizer` 对象,该对象使用从配置中读取的参数进行初始化。

选择模型:

根据 `model_type`(如 "deepspeech2"、"conformer" 或 "transformer"),执行不同的配置更新操作。

对于 "deepspeech2",更新语言模型路径,并可能下载相应的语言模型文件。

对于 "conformer" 或 "transformer",设置解码方法和可能的解码左块数量。

如果 `model_type` 不匹配任何已知的类型,则引发异常。

#Init body.
        self.config = CfgNode(new_allowed=True)
        self.config.merge_from_file(self.cfg_path)

        with UpdateConfig(self.config):
            if self.config.spm_model_prefix:
                self.config.spm_model_prefix = os.path.join(
                    self.res_path, self.config.spm_model_prefix)
            self.text_feature = TextFeaturizer(
                unit_type=self.config.unit_type,
                vocab=self.config.vocab_filepath,
                spm_model_prefix=self.config.spm_model_prefix)
            if "deepspeech2" in model_type:
                self.config.decode.lang_model_path = os.path.join(
                    MODEL_HOME, 'language_model',
                    self.config.decode.lang_model_path)

                lm_url = self.task_resource.res_dict['lm_url']
                lm_md5 = self.task_resource.res_dict['lm_md5']
                self.download_lm(
                    lm_url,
                    os.path.dirname(self.config.decode.lang_model_path), lm_md5)

            elif "conformer" in model_type or "transformer" in model_type:
                self.config.decode.decoding_method = decode_method
                if num_decoding_left_chunks:
                    assert num_decoding_left_chunks == -1 or num_decoding_left_chunks >= 0, "num_decoding_left_chunks should be -1 or >=0"
                    self.config.num_decoding_left_chunks = num_decoding_left_chunks

            else:
                raise Exception("wrong type")

从代码中可以得出,本次采用的为comformer模型,为paddlespeech中的U2Model,训练用数据集为wenetspeech。还有batchsize等参数,可以查看model_conf变量。

使用任务资源(`self.task_resource`)获取与模型名称对应的模型类。  
* 创建一个模型实例,该实例使用之前加载和更新的配置进行初始化。  
* 将模型设置为评估模式(`self.model.eval()`),这意味着模型将处于不执行任何训练或权重更新的状态,而是准备进行推理或评估。

        model_name = model_type[:model_type.rindex(
            '_')]  # model_type: {model_name}_{dataset}
        model_class = self.task_resource.get_model_class(model_name)
        model_conf = self.config
        model = model_class.from_config(model_conf)
        self.model = model
        self.model.eval()

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值