【Python应用探索笔记二】百度语音合成与识别


依旧是百度AI开放平台的功能,这一次来研究一下百度的语音识别模块。
首先需要下载PyAudio用来录音。
所以这里需要安装。

一、使用国内源安装Python的第三方库

不过PyAudio安装的时候经常报错:

pip install pyaudio -i https://pypi.tuna.tsinghua.edu.cn/simple

这里是用pip安装,使用的是清华的源来安装。不过因为pip不能解决依赖关系,所以才报错。
具体更换的方式可参考清华镜像的使用帮助
因此如果是在Anaconda的环境下,则可以使用conda命令来安装。
这里也可以配置成国内的源:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge 
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
 
# 设置搜索时显示通道地址
conda config --set show_channel_urls yes

转载地址:https://blog.csdn.net/observador/article/details/83618540
清华官方镜像使用说明
安装命令:conda install pyaudio
如果是在Ubuntu下,则可以使用apt来安装:sudo apt-get install python-pyaudio

二、录音函数模块

如果是安装的anaconda3,那么其它的第三方库就不需要安装了,如果不是,那么请根据需求安装import中的第三方库。

import pyaudio
import numpy as np
from scipy import fftpack
import wave
import time

回来继续说语音识别,要搞语音识别,首先就需要录音,下面有两种录音方式:

1、固定录音时间的录音方式

这种录音方式较为死板,就是不管你说没说完话,到时间了就结束录音,但这种方式的优点就是代码较为简单。

def Luyin(filename, times=0):
	CHUNK = 1024  # 块大小
	FORMAT = pyaudio.paInt16  # 每次采集的位数
	CHANNELS = 1  # 声道数
	RATE = 16000  # 采样率:每秒采集数据的次数
	RECORD_SECONDS = times  # 录音时间
	WAVE_OUTPUT_FILENAME = filename  # 文件存放位置
	p = pyaudio.PyAudio()
	stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
	print("* 录音中...")
	frames = []
	for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
	    data = stream.read(CHUNK)
	    frames.append(data)
	print("* 录音结束")
	stream.stop_stream()
	stream.close()
	p.terminate()
	if startflag:
	    with wave.open(WAVE_OUTPUT_FILENAME, 'wb') as wf:
	        wf.setnchannels(CHANNELS)
	        wf.setsampwidth(p.get_sample_size(FORMAT))
	        wf.setframerate(RATE)
	        wf.writeframes(b''.join(frames))

2、根据音量大小控制录音开关

第二种录音方式较为灵活,通过设定一个阈值,在声音大于阈值时开始录音,小于阈值结束录音,设定一定时间,来判断是否是真的结束了说话,而不是停顿。
下面是两者融合之后的代码。
如果需要定时录音则设置times不等于0,如果不需要,则默认为根据音量来控制录音开关。

def recording(filename, times=0, threshold=7000):
    """
    :param filename: 文件名
    :param time: 录音时间,如果指定时间,按时间来录音,默认为自动识别是否结束录音
    :param threshold: 判断录音结束的阈值
    :return:
    """
    CHUNK = 1024  # 块大小
    FORMAT = pyaudio.paInt16  # 每次采集的位数
    CHANNELS = 1  # 声道数
    RATE = 16000  # 采样率:每秒采集数据的次数
    RECORD_SECONDS = times  # 录音时间
    WAVE_OUTPUT_FILENAME = filename  # 文件存放位置
    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
    print("* 录音中...")
    frames = []
    if times > 0:
        for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
            data = stream.read(CHUNK)
            frames.append(data)
    else:
        stopflag = 0
        stopflag2 = 0
        startflag = False
        f3 = False
        startTime = time.time()
        while True:
            data = stream.read(CHUNK)
            rt_data = np.frombuffer(data, np.dtype('<i2'))
            # print(rt_data*10)
            # 傅里叶变换
            fft_temp_data = fftpack.fft(rt_data, rt_data.size, overwrite_x=True)
            fft_data = np.abs(fft_temp_data)[0:fft_temp_data.size // 2 + 1]

            # 测试阈值,输出值用来判断阈值
            # print(sum(fft_data) // len(fft_data))
            # flags = sum(fft_data) // len(fft_data)

            # 判断麦克风是否停止,判断说话是否结束,# 麦克风阈值,默认7000
            if sum(fft_data) // len(fft_data) > threshold:
                stopflag += 1
                startflag = True
                f3 = True
                stopTime = time.time()
            else:
                stopflag2 += 1
                if f3:
                    stopTime = time.time()
                    f3 = False
            oneSecond = int(RATE / CHUNK)
            if stopflag2 + stopflag > oneSecond:
                # if stopflag2 > oneSecond // 3 * 2:
                if stopflag2 > oneSecond // 3 * 2 and startflag and time.time() - stopTime >= 1.5 or time.time() - startTime > 8:
                    break
                else:
                    stopflag2 = 0
                    stopflag = 0
            if startflag:
                frames.append(data)
    print("* 录音结束")
    stream.stop_stream()
    stream.close()
    p.terminate()
    if startflag:
        with wave.open(WAVE_OUTPUT_FILENAME, 'wb') as wf:
            wf.setnchannels(CHANNELS)
            wf.setsampwidth(p.get_sample_size(FORMAT))
            wf.setframerate(RATE)
            wf.writeframes(b''.join(frames))

三、发送音频文件到百度API

录音完之后,只需要直接上传音频文件即可,根据百度的开发文档,可以直接从json数据中提取出识别结果。

from aip import AipSpeech
''' 你的APPID AK SK  参数在申请的百度云语音服务的控制台查看'''
APP_ID = '你的app id'
API_KEY = '你的api key'
SECRET_KEY = '你的secret_key'
self.client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
def shiBie(path):
    '''
    语音识别模块
    path:音频文件所在路径
    输出:字符串
    '''
    with open(path, 'rb') as fp:
        voices = fp.read()
    try:
        result = self.client.asr(voices, 'wav', 16000, {'dev_pid': 1537, })
        # if result["err_no"] == "0":
        result_text = result["result"][0]
        print("you said: " + result_text)
        return result_text
    except KeyError:
        print("KeyError")

四、语音合成

语音合成也很简单,这里如果要播放音频的话还得安装一个第三方库playsound
最后建议封装成函数,使用的时候可以直接调用。

# 导入AipSpeech  AipSpeech是语音识别的Python SDK客户端
from aip import AipSpeech
''' 你的APPID AK SK  参数在申请的百度云语音服务的控制台查看'''
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

result  = client.synthesis('你要合成的话', 'zh', 1, {
    'vol': 5,
})
# 识别正确返回语音二进制 错误则返回dict 参照下面错误码
if not isinstance(result, dict):
    with open('auidio.mp3', 'wb') as f:
        f.write(result)

from playsound import playsound
#auidio.mp3是文件的名字,这里必须是mp3文件,且和上面的保存的名字要一致
playsound("auido.mp3")

版权声明:本文为weixin_40524689原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。