Linux命令行机器人之---5.语音识别+千帆大模型实现个人专属语音助理
大模型开发/技术交流
- 社区上线
- 开箱评测
- 文心大模型
2023.10.061339看过
Linux命令行机器人系列文章导航
如果前三步骤都很熟悉了,请跳过直接第4步。否则强烈建议查看学习!!!
Linux命令行机器人之---1.初识百度智能云千帆大模型平台: https://cloud.baidu.com/qianfandev/topic/267409
Linux命令行机器人之---2.初学者快速入门千帆大模型平台: https://cloud.baidu.com/qianfandev/topic/267410
Linux命令行机器人之---3.千帆大模型平台HelloWorld实例: https://cloud.baidu.com/qianfandev/topic/267411
Linux命令行机器人之---(4.)100行代码挑战开发一个完整的命令行机器人: https://cloud.baidu.com/qianfandev/topic/267413
Linux命令行机器人之---5. 语音识别+千帆大模型实现个人专属语音助理: https://cloud.baidu.com/qianfandev/topic/267428
功能演示可以直接翻到最下面。
前言
上一篇文章,实现了纯文字的小助手,接下来,我们实现语音版的小助手。
完成本节的内容,需要你具备一些音视频领域的简单知识,例如音频的采样率,音频的编码格式。
不会也没关系,先做后理解皆可。
先来回顾一下上一个篇文章实现的功能:
如下图所示,这就是我们上一篇文章里不到100行代码,实现的文字版的问答小助手。
支持你输入问题,我回答问题的形式。
文字版的还是不太舒服,还需要手动输入才行。
如果我们实现了语音版的该多好,可以节省很多时间。
那么问答的形式就会改进成:
-
1、你语音录入问题;
-
2、我回答你;
实现智能语音助手的流程
至少完成以下几部分,才能完成整体的功能:
-
1、语音输入;(那么就需要支持声音的录制)
-
2、语音识别;(那么就需要支持声音的识别+声音转文字功能)
-
3、问答功能;(以上一篇文章实现的代码为基础进行改进实现)
功能流程大致如下:
不卖官司了,本篇文章是结合百度语音识别功能+百度千帆大模型实现了你的“智能语音小助手”。
具体实现步骤
步骤如下:
1、录音功能;(因为需要上传录音才能转文字,所以这是前提)
2、语音转文字;
3、扩展代码;
1、录音功能;(因为需要上传录音才能转文字,所以这是前提)
2、语音转文字;
3、扩展代码;
1、实现录音功能
因为本次开发的案例,是全使用的python,所以也会使用python的库。
使用pyaudio库进行音频的录制;
有以下几点需要注意:
-
1、百度语音识别技术,要求的语音的格式包括PCM格式,PCM是语音的一种格式,是无压缩的,所以无需转码的操作,可以节省时间。
-
2、要求采样率需要是16000或者8000单位是Hz;(如果你开发过音视频领域的项目,一定很熟悉,否则需要百度下进行简单学习)
-
3、要求是单声道;
经过摸索和实践,下面这段代码就可以实现录音功能:
实现了录制16Khz采样率,单声道的PCM数据;
代码中限制了只录制5s。
import pyaudioimport waveclass Audio_AI:def __init__(self):# 配置录音参数self.FORMAT = pyaudio.paInt16 # 音频格式,可以根据需要选择self.CHANNELS = 1 # 声道数(单声道)self.RATE = 16000 # 采样率,可以根据需要选择self.RECORD_SECONDS = 5 # 录制时长(秒)self.OUTPUT_FILENAME = "recorded_audio.pcm" # 输出文件名def audio_record(self):# 初始化PyAudioaudio = pyaudio.PyAudio()# 打开音频输入流stream = audio.open(format=self.FORMAT, channels=self.CHANNELS,rate=self.RATE, input=True,frames_per_buffer=1024)print("开始录制...")frames = []# 录制音频for i in range(0, int(self.RATE / 1024 * self.RECORD_SECONDS)):data = stream.read(1024)frames.append(data)print("录制完成.")# 停止音频流stream.stop_stream()stream.close()# 关闭PyAudioaudio.terminate()# 保存录音结果为WAV文件with wave.open(self.OUTPUT_FILENAME, 'wb') as wf:wf.setnchannels(self.CHANNELS)wf.setsampwidth(audio.get_sample_size(self.FORMAT))wf.setframerate(self.RATE)wf.writeframes(b''.join(frames))print(f"音频已保存为 {self.OUTPUT_FILENAME}")return self.OUTPUT_FILENAME
运行后,会在当前目录下生成一个".pcm"为后缀的音频文件:
recorded_audio.pcm
如果想测试音频,可以使用ffplay:
```shellffplay -f s16le -ar 16000 -ac 1 recorded_audio.pcm
2、语音转文字
具体的语音转文字如何在官方操作的这里就不过多说明了,可以参考官方的文档和千帆大模型平台调用API的流程是一样的。需要先创建一个应用,然后就有key了。
拿到了key就可以获取token,然后才能继续调用其他语音技术的API;
下面的代码中补充了语音转文字的代码:
audio_ai.py:
import pyaudioimport waveimport requestsimport jsonimport base64import timetimer = time.perf_counterAPI_KEY = 'xxx'SECRET_KEY = 'zzzz'# 需要识别的文件# AUDIO_FILE = './16k.pcm' # 只支持 pcm/wav/amr 格式,极速版额外支持m4a 格式AUDIO_FILE = './recorded_audio.pcm' # 只支持 pcm/wav/amr 格式,极速版额外支持m4a 格式# 文件格式FORMAT = AUDIO_FILE[-3:] # 文件后缀只支持 pcm/wav/amr 格式,极速版额外支持m4a 格式CUID = '123456PYTHON'# 采样率RATE = 16000 # 固定值# 普通版DEV_PID = 1537 # 1537 表示识别普通话,使用输入法模型。根据文档填写PID,选择语言及识别模型ASR_URL = 'http://vop.baidu.com/server_api'TOKEN_URL = 'http://aip.baidubce.com/oauth/2.0/token'class Audio_AI:def __init__(self):# 配置录音参数self.FORMAT = pyaudio.paInt16 # 音频格式,可以根据需要选择self.CHANNELS = 1 # 声道数(单声道)self.RATE = 16000 # 采样率,可以根据需要选择self.RECORD_SECONDS = 5 # 录制时长(秒)self.OUTPUT_FILENAME = "recorded_audio.pcm" # 输出文件名def audio_record(self):# 初始化PyAudioaudio = pyaudio.PyAudio()# 打开音频输入流stream = audio.open(format=self.FORMAT, channels=self.CHANNELS,rate=self.RATE, input=True,frames_per_buffer=1024)print("开始录制...")frames = []# 录制音频for i in range(0, int(self.RATE / 1024 * self.RECORD_SECONDS)):data = stream.read(1024)frames.append(data)print("录制完成.")# 停止音频流stream.stop_stream()stream.close()# 关闭PyAudioaudio.terminate()# 保存录音结果为WAV文件with wave.open(self.OUTPUT_FILENAME, 'wb') as wf:wf.setnchannels(self.CHANNELS)wf.setsampwidth(audio.get_sample_size(self.FORMAT))wf.setframerate(self.RATE)wf.writeframes(b''.join(frames))print(f"音频已保存为 {self.OUTPUT_FILENAME}")return self.OUTPUT_FILENAMEdef get_token(self):# 组装数据params = {'grant_type': 'client_credentials','client_id': API_KEY,'client_secret': SECRET_KEY}response = requests.post(TOKEN_URL, timeout=10, params=params)if response.status_code == 200:# 转成JSONresult = json.loads(response.text)# print(result)if ('access_token' in result.keys() and 'scope' in result.keys()):return result['access_token']else:print("获取token失败!")else:print("请求失败")def read_audio_data(self, audio_filename):speech_data = []with open(audio_filename, 'rb') as speech_file:speech_data = speech_file.read()return speech_datadef asr_audio(self, speech_data, length, token):# 进行base64编码speech = base64.b64encode(speech_data)speech = str(speech, 'utf-8')headers = { "Content-Type": "application/json" }# 封装识别API请求的参数body = {'dev_pid': DEV_PID,#"lm_id" : LM_ID, #测试自训练平台开启此项'format': FORMAT,'rate': RATE,'token': token,'cuid': CUID,'channel': 1,'speech': speech,'len': length}result = {}begin = timer()json_data = json.dumps(body, indent=4) # indent 参数可选,用于格式化输出response = requests.post(ASR_URL,headers=headers, timeout=10, data=json_data)print(response.status_code)if response.status_code == 200:# 转成JSONresult_json = json.loads(response.text)result = result_json["result"]else:print("请求失败")print ("Request time cost %f" % (timer() - begin))return resultdef run_audio_asr(self, audio_filename):# 获取tokentoken = self.get_token()print("get token:", token)# 读取音频文件speech_data = self.read_audio_data(audio_filename)length = len(speech_data)if length == 0:print("发送识别失败,录音数据可能为空")else:result = self.asr_audio(speech_data, length, token)print(result)return result
3、扩展代码
到这个阶段上面的代码,就得到了audio_ai.py文件,接下来就扩展到我们之前实现的命令行的代码上。
1、import引入文件
import audio_ai as audio_ai
2、在__init__代码中初始化audio_ai对象:
# audioself.audio_ai = audio_ai.Audio_AI()
3、改造run_loop函数:
下面的代码就是改造后的,支持了用户选择使用语音输入还是手动输入。
def run_loop(self):while True:# print("##########################")# # 使用 input() 函数接收用户输入# user_input_msg = input("问:")# recv_msg = self.send_chat(user_input_msg)# print("答:", recv_msg)# print("##########################")while True:print("##########################")# 使用 input() 函数接收用户输入print("#指令---> 1:语音输入;2:手动输入;")user_input_msg = input("指令:")if user_input_msg == "1":print(" 语音输入 ")# 1.录制声音audio_filename = self.audio_ai.audio_record()# 2.识别结果results = self.audio_ai.run_audio_asr(audio_filename)print("问:", results)print("问:", results[0])# 3.将识别结果发送至千帆大模型recv_msg = self.send_chat(results[0])print("答:", recv_msg)elif user_input_msg == "2":print(" 手动输入 ")print("##########################")# 使用 input() 函数接收用户输入user_input_msg = input("问:")recv_msg = self.send_chat(user_input_msg)print("答:", recv_msg)print("##########################")print("##########################")
功能演示
1、首次运行:
会提供一个选项:
输入1即可语音输入,输入2即可手动输入文字;
2、先来体验一下手动输入
输入2回车,会提示选择的是手动输入,然后会提示你输入问题
例如输入:
眨眼间就会有结果:
3、再体验下语音输入
可以继续选择1,也可以重新运行:
提示“开始录制...”时,然后就可以开始说话了,因为限制了5s,所以请尽快说完.
结果:
视频演示:
因为文章中不能插入视频,录制的演示视频放到了视频号里,可以自行扫码查看。
全部代码位置
代码已放在了github上,欢迎点赞收藏:
https://github.com/truedei/cmdchat
https://github.com/truedei/cmdchat
其他问题排查
原来获取token不支持浏览器跨域,我说怎么解决都不可以。
评论