大家好,欢迎来到《分享本周所学》第三期。本人是一名人工智能初学者,最近一周给自己的Linux虚拟机配置了GPU环境,然后还借助PaddleSpeech里面一个流式语音识别的demo实现了实时录音的流式语音识别,学到了非常多的知识,就想把学到的东西分享给大家,不管你是想跟着我从头到尾做一个流式语音识别,还是只想借鉴一下我其中某个环节是怎么做的,相信你都可以有所收获。这周我也遇到了很多困难,有的困难到现在还没解决,我也不知道有没有办法解决,所以也想向大家求助一下(见第一章1.1末尾)。然后因为我也只是一名小白,所以有错误的地方还希望大佬们多多指正。

目录

一、Linux上的GPU环境咋配啊

1. 关于我在Linux上配GPU环境这件事

2. CUDA安装与环境变量配置

3. CUDNN安装

二、实时录音的流式语音识别咋搞啊

1. Linux上的语音识别

1.1 Python环境配置

1.2 使用实时录音

2. Windows上的语音识别


上期文章链接:《分享本周所学——Transformer模型详解》http://t.csdn.cn/XCPfW

本期封面:


 

一、Linux上的GPU环境咋配啊

        注:实时流式语音识别是可以在Windows上实现的,并不需要配置Linux环境,如果你只想实现这个语音识别,可以直接跳到第二章的1.2。另外,如果需要在Linux上配置GPU环境,建议Linux系统内至少有32G可用空间。我的Linux系统是Ubuntu20.04,不过其他系统应该都是类似的。

        我在这里先讲一个关于我在Linux上配GPU环境的小故事啊,如果你不想看这个小故事可以跳到下面第一章第2节,直接进入教程部分。

1. 关于我在Linux上配GPU环境这件事

        其实我在Linux上配GPU环境就是为了能用PaddleHub里一个语音识别的预训练模型。PaddleHub是PaddlePaddle的一个预训练模型库,PaddlePaddle是百度开发的一个和PyTorch类似的人工智能库。我用的模型是下面这个,大家有兴趣可以去看一眼。

u2_conformer_wenetspeechhttps://www.paddlepaddle.org.cn/hubdetail?name=u2_conformer_wenetspeech&en_category=AutomaticSpeechRecognition

        简单来说就是一个基于Transformer和Conformer的语音识别模型。Wenet这个模型其实还挺著名的,有兴趣的朋友们可以去查一查这个模型具体的结构,我这里就不赘述了。

        然后我就去装这个模型。我一看见那个网页里给出的安装模型的命令最前面那个“$”符号,就觉得这玩意大概不是给Windows用的,那我用Windows装这玩意不出意外的话估计就要出点意外了。果然啊,装的时候开始给我报错,一开始是说我的PaddleSpeech里面缺了一个模块(模块还是函数来着,忘了),然后我就寻思是不是我PaddleSpeech的版本太高了啊?我就去给PaddleSpeech降级,一级一级地降,边降边试,一直降到0.1.0(对,就是最初的版本)才解决这个问题。我就纳闷了,你们自己家的一套东西,怎么自己还不能适配自己的新版本呢?真是跟巨硬一个德行。

        但是这还没完,这个问题解决之后它理所当然地又报了另一个错,说有一个叫Soxbindings的库我没装。那就装呗。但是死活装不上,我去Pypi上查了一下,发现他们根本就没有Windows版本……

        那怎么办?我想着我要是愣在Windows上装个这玩意出来估计比开个Linux虚拟机重新配一遍环境还麻烦,然后就开了个WSL(Windows Subsystem for Linux,适用于Linux的Windows子系统)开始给它配GPU环境。这里说一句啊,我其实是第一次正儿八经地接触Linux,之前虽然也配置过Linux的虚拟机,但是从来没有在命令行里用过一句哪怕是从网上复制下来的指令,这次开始整的时候连sudo是啥意思我都琢磨了半天,所以我装CUDA和CUDNN这两个库其实是花了大量的时间,查了各种各样的资料,也踩了一大堆坑。然后为了让看我这篇文章的那些不怎么了解Linux的朋友们能够避免我踩的这些坑,我这里用的都是比较简单通用的办法,写的也比较啰嗦,如果有大佬看不惯的话还请见谅。

        配完GPU环境之后,把那个模型需要的各种Python库也都装了一遍,然后录了一个音频文件给它识别,效果还挺好。但我的目的没达到啊,我是想做实时录音的流式语音识别。于是我就装了PyAudio想要录音,结果报错了,告诉我说我缺了一个叫portaudio.h的文件。然后我就去装portaudio.h,又是Linux小白的一场灾难。费了半天劲装上了,但是PyAudio还是报错,这次报的错我是死活也看不懂了,我就去网上一通乱查,查了好久好久,但是真的查不到为什么。虽说查不到为什么,但是在网上看了各种资料之后,我不由得产生了怀疑:我严重怀疑WSL根本调用不了系统声卡。如果真是这样,那我怎么可能在WSL上录音?于是我放弃了在WSL上继续干下去的打算。

        不能用WSL的话倒是也有其他办法。我在VMware Workstation上装了一个Ubuntu。我用VMware的原因是之前上网课的时候,我在VMware里装的Classin(一个网课软件)是可以检测到我的麦克风的,我说话老师也能听见,这说明VMware的录音功能肯定是没有问题的,起码能调用声卡。至于我为什么要把Classin装在VMware里,主要是因为Classin有一个阻止切屏的功能,老师一旦启用这个功能,我就切不了屏了,所以为了在上网课的时候去干一些有意义的事情,我就被迫把Classin装在了虚拟机里。扯远了,总之我就是又重新走了一遍这个流程:配GPU环境、配Python环境、装PortAudio、写代码。这次录音功能正常了,我说的话也能实时被识别出来了,但是又出现了一个同样严重的问题:Vmware里的Ubuntu似乎不能调用我的显卡……

        我真的崩溃了,一怒之下我直接弃用PaddleHub,在Windows上用PaddleSpeech重新做了一个,然后一切正常……

        不过我这里真的要求助一下各位大佬啊,怎么在WSL里调用声卡,怎么在VMware Workstation里调用显卡,各位大佬救救我吧……

2. CUDA安装与环境变量配置

        其实这个CUDA环境很好配啊,直接到下面NVIDIA的这个网站找一个你喜欢的版本。我这里以目前最新的11.7.0为例啊。如果你来自2022年7月以后的遥远未来,估计这个版本对你来说可能已经比较老了。CUDA Toolkit Archivehttps://developer.nvidia.com/cuda-toolkit-archive        网站长这个样子(至少2022年7月长这个样子)。如果你用的是WSL这种没有图形界面的系统,你可以在Windows里打开这个网页,然后把命令复制进Linux里执行。效果是一样的。

        接下来根据你的系统版本选择对应的CUDA版本。我这里用的是Ubuntu20.04。最底下Installer Type那一行的三个选项应该都可以选。我个人对这三个选项的理解(不一定准确,仅供参考)是:deb是一种类似压缩包的东西,而runfile有点像可执行文件;然后local表示下载之后从本地安装,network表示从网络上安装。我个人比较推荐用runfile那个啊,主要就是因为只有两句命令比较方便。

        先别急着装CUDA,如果你是刚刚装完Linux系统,我建议你先在命令行里运行一下下面两句话,更新一下包。善意地提醒一下,在命令行里复制粘贴是Ctrl+Shift+C和Ctrl+Shift+V(这是昨天刚从一个朋友那学到的)。

sudo apt update
sudo apt upgrade -y

        在upgrade的过程中有可能会出现奇奇怪怪的问题然后中断。如果出现这种情况可以试试以下命令:

sudo apt upgrade -y --fix-missing

        如果还是不行就算了,应该不会有太大影响。接下来挨个在命令行里运行网页上给出的命令。这个过程中,如果有报错显示“Failed to verify gcc version”,就用下面这个命令升级一下gcc:

sudo apt upgrade -y gcc

        如果过程中发生中断,同样也可以用--fix-missing来抢救一下:

sudo apt upgrade -y gcc --fix-missing

        然后应该就可以正常安装了。这里提醒一句啊,如果你是用runfile安装的,安装过程中有可能会弹出这样一个界面:

        最上面的一句话的意思大概是:“亲,我们这边呢,就是发现您这边的包管理器呢是已经安装了一个驱动了,那我们这边呢就是说比较建议您移除掉您这边这个驱动哈。”这个其实不需要管它,只不过待会在安装的时候就不需要再额外安装驱动了。用键盘上的上下箭头移动光标到“Continue”,然后按回车确认。

        这里需要你同意它这个License,如果你同意就敲一个“accept”然后回车。

        这里是选择要安装的组件。最上面那个是驱动,如果它提示你已经安装过驱动,就按回车把它取消掉,把“Driver”那一栏的中括号里的大叉子去掉。你可以去掉其他你不想要的组件,不过这里我是推荐除了Driver以外全都保留。更改完之后按“Install”就可以自动装好了。

        但是还没完啊,我们还得手动配置一下环境变量。输入下面这条命令:

sudo vim ~/.bashrc

        如果你是刚刚装的系统,有可能会提示你“sudo: vim: command not found”。这时候你需要装一下vim。同理,遇到中断可以在后面加--fix-missing抢救,这里我就不放代码了。

sudo apt install -y vim

        之后我们有可能会进入这样一个界面:

        如果看见这个界面的话,按E就好,接下来会看到这个界面:

        现在我们要修改一下这个文件。但是你会发现文件现在修改不了,所以我们需要按I进入编辑模式。之后在文件最底下,也就是最后那个“fi”下面,加上这两行:

export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

        按ESC退出编辑模式,然后打一个冒号,输入“wq”(“w”表示write,保存;“q”表示quit,退出),回车,就可以了。

        完成之后重启系统,然后可以在命令行里用下面这条命令测试是不是成功安装了:

nvcc -V

        如果成功的话,应该会出现类似这样的结果:

        如果不成功,可以试着在刚才CUDA的下载网站上换一个Installer Type重装一遍试试;如果还不成功,我作为一个刚刚接触Linux的小白就真的不知道是什么问题了。

3. CUDNN安装

        CUDNN其实不一定要装,因为PyTorch这样的库是不需要额外安装CUDNN的。但是如果你像我一样要用到PaddlePaddle这种需要CUDNN的库,那就免不了要再装一样东西。下面这个是CUDNN的下载地址,你可能需要注册或者登录一下NVIDIA账号才能下载。cuDNN Downloadhttps://developer.nvidia.com/rdp/cudnn-download        选择一个你想要的版本点进去,进去之后大概是这个界面:

        我们选择第二个,也就是“Local Installer for Linux x86_64 [Tar]”下载。在下载好的文件所在的目录里打开命令行,然后用以下命令解压缩:

sudo tar -xvf cudnn-linux-x86_64-8.4.1.50_cuda11.6-archive.tar.xz

        -xvf后面是下载的文件的文件名。如果你下载的文件名和我不一样,记得把文件名换成你的。解压完了之后,我们用下面的命令进入解压好的目录里。和上面一样,不要忘了换文件名。

cd cudnn-linux-x86_64-8.4.1.50_cuda11.6-archive

        然后依次运行下面的命令:

sudo cp include/* /usr/local/cuda/include/
sudo cp lib/* /usr/local/cuda/lib64/
sudo chmod +x /usr/local/cuda/include/cudnn.h
sudo chmod +x /usr/local/cuda/lib64/libcudnn*

        虽然你可能看不到任何输出,但是我们的确已经把CUDNN装好了。可以用以下的命令测试一下:

cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

        然后如果输出一段看起来明显像是C/C++头文件的代码,就说明装好了。


二、实时录音的流式语音识别咋搞啊

        这周我是做了两个版本的语音识别,一个在Linux上,一个在Windows,都支持实时录音。至于为什么我做了两个,可以看第一章第1节的小故事。

1. Linux上的语音识别

        这个语音识别是根据PaddleHub上的u2_conformer_wenetspeech修改出的实时录音版本,建议在Linux环境下使用。关于在Linux上配置GPU环境的问题可以看第一章。

1.1 Python环境配置

        首先在命令行里依次运行以下命令。先安装pip,然后安装依赖的Python库。

sudo apt install -y python3-pip
pip3 install paddlepaddle-gpu paddlehub paddlespeech==0.1.0 numpy==1.22.0 protobuf==3.20.0 paddlespeech-ctcdecoders -U -i https://pypi.tuna.tsinghua.edu.cn/simple

        重启系统,不然PaddleHub没法完成安装。重启之后用以下命令安装预训练好的模型。

hub install u2_conformer_wenetspeech

        这就完成了。可以试着自己录一段音频,然后运行下面的小程序来测一下模型的效果(不要忘了把wav_file的值改成自己的音频文件的路径)。第一次调用模型的时候可能会加载一段时间,之后再调用的时候就会快一点。

import paddlehub as hub

wav_file = './1.wav'
model = hub.Module(name='u2_conformer_wenetspeech', version='1.0.0')
text = model.speech_recognize(wav_file)
print(text)

1.2 使用实时录音

        首先说一下为什么我要把这个语音识别搞成实时录音的啊。其实实时录音很明显有两个优点:第一是如果没有实时录音,每次录完音之后我还得先给音频文件改名,再复制到正确的位置,这个过程实在是太麻烦了;第二是程序从硬盘里读取音频文件的速度肯定不如直接从内存里读取刚录好的热乎的音频。

        Python里面有一个挺好使的用来录音的库,叫PyAudio。但是我们不能直接装PyAudio啊,因为PyAudio会依赖一个叫portaudio.h的文件,这个文件一般的Linux上都不会自带,所以我们得先装一下这个玩意。依次运行以下命令,安装portaudio.h和PyAudio。

sudo apt install -y libjack-jackd2-dev portaudio19-dev
pip3 install pyaudio -U -i https://pypi.tuna.tsinghua.edu.cn/simple

        然后用以下代码就能实现一个简单的录音功能。这个程序里的前两句话其实就是为录音做准备,真正起到录音作用的只有最后一句stream.read。

import pyaudio

pa = pyaudio.PyAudio()
stream = pa.open(16000, # Sampling rate
                 1, # Channel
                 pyaudio.paFloat32, # The data type used to store the audio
                 input=True,
                 frames_per_buffer=16000) # The amount of data stored in each
                                          # piece of recording
wav = stream.read(16000)

        PyAudio录出来的音频是以bytes的形式存储的。在把音频扔给模型之前,我们得先把bytes转换成一个正常点的数据类型,比如float。幸运的是,NumPy专门有一个把bytes转成其他类型的函数,叫frombuffer。如果把上面存在变量wav里的bytes型数据转成float32,只需要(不算导入numpy的话)一行代码:

import numpy as np

audio = np.frombuffer(wav, dtype='float32')

        注意,这里的dtype要对应上上面pa.open中使用的数据类型,如果上面用的是paInt16,这里也要改成dtype='int16',不然会出现乱七八糟的结果。

        但是我们还要解决一个问题。这个PaddleHub的模型只支持文件输入,不支持直接使用音频数据。那一个非常简单粗暴的办法就是去改掉这个模型的代码,让它支持输入音频数据。想要实现这个功能,我们得先看看模型本来是怎么读音频文件的,它这个过程大概是这样的啊:它会调用PaddleSpeech(PaddlePaddle的自然语言处理库)里一个叫infer.py的文件,然后infer.py里有一个叫ASRExecutor的类,然后这个ASRExecutor里有一个叫preprocess的函数,然后这个preprocess有一个叫input的参数,传入的是我们要让模型识别的音频文件的地址,然后preprocess这个函数会调用SoundFile(一个用于音频处理的库)里一个叫read的函数来读取音频文件,read这个函数有两个返回值,一个是音频数据,另一个是音频采样率。如果你觉得看的有点迷糊,其实就可以理解为模型把音频文件的路径作为一个叫input的参数传给了一个叫preprocess的函数,让preprocess来用一个叫soundfile.read的函数处理这个文件。

        那我们可以把input传入的值改成np.frombuffer生成的音频数据。但是这时候soundfile.read肯定就会报错了,它觉得自己本来想要一个代表路径的字符串,你给我一串float算怎么回事啊。其实解决的办法也很简单,为了描述得更直观一点,我先在这里放一下preprocess这个函数,你完全不用看懂,只需要注意一下第45行的soundfile.read。

def preprocess(self,
               model_type: str,
               input: Union[str, os.PathLike],
               from_file=True):
    """
    Input preprocess and return paddle.Tensor stored in self.input.
    Input content can be a text(tts), a file(asr, cls) or a streaming(not supported yet).
    """

    audio_file = input
    if from_file:
        logger.info("Preprocess audio_file:" + audio_file)

    # Get the object for feature extraction
    if "ds2_online" in model_type or "ds2_offline" in model_type:
        audio, _ = self.collate_fn_test.process_utterance(
            audio_file=audio_file, transcript=" ")
        audio_len = audio.shape[0]
        audio = paddle.to_tensor(audio, dtype='float32')
        audio_len = paddle.to_tensor(audio_len)
        audio = paddle.unsqueeze(audio, axis=0)
        vocab_list = collate_fn_test.vocab_list
        self._inputs["audio"] = audio
        self._inputs["audio_len"] = audio_len
        logger.info(f"audio feat shape: {audio.shape}")

    elif "conformer" in model_type or "transformer" in model_type or "wenetspeech" in model_type:
        # logger.info("get the preprocess conf")
        preprocess_conf_file = self.config.collator.augmentation_config
        # redirect the cmvn path
        with io.open(preprocess_conf_file, encoding="utf-8") as f:
            preprocess_conf = yaml.safe_load(f)
            for idx, process in enumerate(preprocess_conf["process"]):
                if process['type'] == "cmvn_json":
                    preprocess_conf["process"][idx][
                        "cmvn_path"] = os.path.join(
                            self.res_path,
                            preprocess_conf["process"][idx]["cmvn_path"])
                    break
        # logger.info(preprocess_conf)
        preprocess_args = {"train": False}
        preprocessing = Transformation(preprocess_conf)
        # logger.info("read the audio file")
        if from_file:
            audio, audio_sample_rate = soundfile.read(audio_file,
                                                      dtype="int16",
                                                      always_2d=True)
        else:
            audio, audio_sample_rate = audio_file

        if self.change_format:
            if audio.shape[1] >= 2:
                audio = audio.mean(axis=1, dtype=np.int16)
            else:
                audio = audio[:, 0]
            # pcm16 -> pcm 32
            audio = self._pcm16to32(audio)
            audio = librosa.resample(audio, audio_sample_rate,
                                     self.sample_rate)
            audio_sample_rate = self.sample_rate
            # pcm32 -> pcm 16
            audio = self._pcm32to16(audio)
        else:
            audio = audio[:, 0]

        # logger.info(f"audio shape: {audio.shape}")
        # fbank
        audio = preprocessing(audio, **preprocess_args)

        audio_len = paddle.to_tensor(audio.shape[0])
        audio = paddle.to_tensor(audio, dtype='float32').unsqueeze(axis=0)
        text_feature = TextFeaturizer(
            unit_type=self.config.collator.unit_type,
            vocab=self.config.collator.vocab_filepath,
            spm_model_prefix=self.config.collator.spm_model_prefix)
        self._inputs["audio"] = audio
        self._inputs["audio_len"] = audio_len
        # logger.info(f"audio feat shape: {audio.shape}")

    else:
        raise Exception("wrong type")

        可以稍微浏览一下45行附近的几行代码。这个from_file是我给preprocess加的一个参数。如果from_file为True,就表示需要从文件读取音频,那就调用soundfile.read;如果为False,那就是直接把传入的input作为soundfile.read的结果(我这里input传入的是一个包含音频数据和采样率的元组)。

        这就把问题解决了。但是细心的朋友会注意到,我们在1.1节中的语音识别程序并没有直接调用preprocess,而是调用了一个叫speech_recognize的函数,所以其实我们是通过speech_recognize间接调用了preprocess。那我们就需要给speech_recognize也添加一个叫from_file的参数,然后把from_file=False传给speech_recognize,再让speech_recognize把from_file=False间接地传给preprocess。除此之外其实还有一些需要修改的地方,但是原理都差不多,所以我就不赘述了。需要修改的文件我放在Gitee上了,网址如下(仓库目前在审核阶段,你看到这篇文章的时候应该已经过审了,如果还没过审就麻烦你先登录一下再下载):Blog Code/CSDN/3/Linuxicon-default.png?t=M666https://gitee.com/rfdragon/blog-code/tree/master/CSDN/3/Linux        把仓库克隆或者下载到本地,然后打开CSDN/3/Linux文件夹。里面的module.py包含了speech_recognize这个函数。把它复制到/home/rfdragon/.paddlehub/u2_conformer_wenetspeech(这是默认路径,记得把rfdragon改成你自己的用户名,.paddlehub是隐藏文件夹,如果找不到可以试试启用显示隐藏文件夹)里替换原有文件;paddlespeech那个文件夹包含了preprocess那个函数和其他几个需要修改的函数,把它放到/home/rfdragon/.local/lib/python3.8/site-packages(记得把rfdragon改成你自己的用户名,把python3.8改成你自己的python版本;.local是隐藏文件夹)里。这些文件里面所有函数的from_file参数都是我添加的。其实paddlespeech那个文件夹里除了必须要修改的infer.py之外还有两个文件,一个是text_featureizer.py,另一个是tensor_utils.py。我把它们也做了一些改动,原因是它们会打印一大堆日志,比较烦。如果你希望保留日志的话也可以不改它们。做完这些改动之后,你就可以运行Speech Recognition.py开始语音识别了。这里放一下代码:

import numpy as np
import paddlehub as hub
import pyaudio

pa = pyaudio.PyAudio()
model = hub.Module(name='u2_conformer_wenetspeech', version='1.0.0')
# The following statement preloads the model by letting it recognize some
# random things.
model.speech_recognize((np.zeros((8000, 1), dtype='float32'), 16000),
                       device='gpu:0',
                       from_file=False)
# The model requires the sampling rate of the input audio to be 16000.
# Each audio segment recorded will last 2s.
stream = pa.open(16000,
                 1,
                 pyaudio.paFloat32,
                 input=True,
                 frames_per_buffer=32000)
print("Start recording...")
wav = b''  # This generates an empty bytes object.
while True:
    # Bytes objects can be concatenated with the operation "+" like strings.
    wav += stream.read(32000)
    audio = np.frombuffer(wav, dtype='float32')
    # The input array of the model must be 2-dimensional.
    audio = np.expand_dims(audio, -1)
    text = model.speech_recognize((audio, 16000),
                                  device='gpu:0',
                                  from_file=False)
    print(text)

        大概的原理就是,每次录2秒的音,然后和前面录的音接在一起放进模型里做识别,达到流式的效果。

2. Windows上的语音识别

        这个语音识别是根据PaddleSpeech上一个流式语音识别的demo修改出的实时录音版本。请先粗略地看一下这章1.2节,熟悉一下实时录音的实现方法,然后把Github上的PaddleSpeech克隆或者下载到本地。PaddlePaddle/PaddleSpeechicon-default.png?t=M666https://github.com/PaddlePaddle/PaddleSpeech

        还是要先装一下Python库。在命令行里运行以下命令:

python -m pip install paddlepaddle-gpu paddlespeech -U -i https://pypi.tuna.tsinghua.edu.cn/simple

        这个语音识别是针对流式识别优化的,而且还自带服务化,非常高级。它默认使用CPU进行计算,如果想改成GPU,需要到PaddleSpeech\demos\streaming_asr_server\conf\ws_conformer_wenetspeech_application.yaml里面,在第32行把“cpu”改成“gpu:0”。接下来到PaddleSpeech/demos/streaming_asr_server里打开命令行,运行以下命令就可以启动服务了。

paddlespeech_server start --config_file ./conf/ws_conformer_wenetspeech_application.yaml

        如果你不想用命令行,也可以用Python代替。

from paddlespeech.server.bin.paddlespeech_server import ServerExecutor

server_executor = ServerExecutor()
# The parameter config_file in the following function should be the path of
# PaddleSpeech\demos\streaming_asr_server\conf\ws_conformer_wenetspeech_application.yaml,
# but without ".yaml".
server_executor(
    config_file="./conf/ws_conformer_wenetspeech_application")

        然后用下面的程序就可以识别一个音频文件了。

from paddlespeech.server.bin.paddlespeech_client import ASROnlineClientExecutor

asrclient_executor = ASROnlineClientExecutor()
text = asrclient_executor(
    input="1.wav", # The audio file to be recognized.
    port=8090)
print(text)

        但问题还是在于怎么把识别音频文件改成实时录音。我看了一下,这个模型也是像刚才我在Linux里用的那个版本一样用SoundFile来读音频文件,但是不同之处在于这个版本为了给流式语音识别作优化,它会先把从音频文件里读取的数据分成小段,然后再放进模型识别。这应该说是正合我意啊,因为我录音的时候本来就是一小段一小段录的,那我直接用录出来的这些小段的音频替换掉音频文件分段的结果不就好了吗?实现这个功能也很简单,用一个简短的函数就好了。

def record_wave(self):
    pa = pyaudio.PyAudio()
    stream = pa.open(16000,
                     1,
                     pyaudio.paInt16,
                     input=True,
                     frames_per_buffer=32000)

    print("Start Recording...")
    while True:
        yield stream.read(32000)

        然后因为把音频输入模型识别的过程和录音是异步处理的,所以实际上发生的是我每录好一段音频就会进行一次识别,达到流式的效果。

        和上面的Linux版本一样,这个版本也还有很多函数需要修改,主要都是为了添加from_file参数,原理也差不多。具体修改的地方我就不赘述了,所有要改的文件我也已经改好放到Gitee上了。这里再放一遍链接:Blog Code/CSDN/3/Windowsicon-default.png?t=M666https://gitee.com/rfdragon/blog-code/tree/master/CSDN/3/Windows        下载或克隆,然后进入到CSDN\3\Windows文件夹下,把paddlespeech文件夹复制到[X]\Lib\site-packages,[X]是你装Python的位置。接下来运行Stream ASR.py就可以开始语音识别了,不过在这之前别忘了运行上面启动服务化的命令。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐