# 这里是flask框架 from flask import Flask, request, send_file import setting import os from uuid import uuid4 import baidu_ai import json # 底下这三个包用来包装代码 from geventwebsocket.handler import WebSocketHandler from geventwebsocket.websocket import WebSocket from gevent.pywsgi import WSGIServer app = Flask(__name__) # 如果不自动提示加 # type:Flask @app.route("/getfile/<filename>") def getfile(filename): # 引入文件路径 audio_file = os.path.join(setting.AUDIO_FILE_PATH, filename) # send_file是将括号里的文件发送到指定地方,谁请求的就返回给谁 return send_file(audio_file) # 写一个前端往后端传输的一个地址 @app.route("/upload/<user_id>") def upload(user_id): # 取到一个websocket对象。取到用户带过来的websocket的所有东西 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket print(user_socket) # 只能WebSocket访问 if type(user_socket) != WebSocket: return "请使用WebSocket访问" # 让一直循环接收 while 1: # 接收 user_send = user_socket.receive() # print(user_send) # bytearray() 方法返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256。 if type(user_send) == bytearray: # 定义名字 wav_name = f"{uuid4()}.wav" # 定义一个存放路径以及名字 file_wav_name = os.path.join(setting.AUDIO_PCM_PATH, wav_name) # 写入这个文件中 with open(file_wav_name, "wb") as f: # 将接收到的文件写入新文件中 f.write(user_send) # 录音文件转成文本文件,拿到的是一个字符串 asr_str = baidu_ai.audio2text(wav_name) print(asr_str) # asr_str问题,去my_nlp找答案 answer = baidu_ai.my_nlp(asr_str, user_id) # 把获取的答案转化成语音,返回的是一个音频文件的文件名 file_mp3_name = baidu_ai.text2audio(answer) # 把文件已字典形式发给前端,并序列化成一个字符串 send_str = json.dumps({ # 文件名 "filename": file_mp3_name, # 文件类型 "play_type": "audio", "sendtime": 123, }) # 把文件发到前端进行播放 user_socket.send(send_str) if __name__ == "__main__": # 传入ip,端口号,debug # app.run("0.0.0.0", 5000, debug=True) # 三个参数,第二个传入要启动的app,第三个表示如果是WebSocket请求就加WebSocketHandler一个请求头 http_server = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler) # 然后把这个http_server 启动起来 http_server.serve_forever()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <audio autoplay="autoplay" controls id="play_mp3" src="http://127.0.0.1:5000/getfile/44e62976-01ac-447e-beb7-5d461e92a190.mp3"> 浏览器不支持 </audio> <button onclick="start_reco()">开始录音</button> <button onclick="stop_reco()">结束录音</button> </body> <script type="text/javascript" src="Recorder.js"></script> <script type="text/javascript"> // 建立WebSocket链接 var ws = new WebSocket("ws://127.0.0.1:5000/upload/oldboyedu"); // onopen 是当建立链接后帮我执行后面的函数 // ws.onopen = function () { // ws.send("hello") // }; // 如何录音 // 定义这个字符串,去后面去拼接 var get_file = "http://127.0.0.1:5000/getfile/"; var reco = null; // AudioContext支持audio音频文件 vadeo视频文件 var audio_context = new AudioContext(); // 浏览器兼容,我的浏览器中有那个有用哪个 navigator.getUserMedia = (navigator.getUserMedia || // 这个是火狐的 navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); // 这个是ie浏览器的 // navigator是浏览器的所有对象 // 第一个参数是{ audio:true } 第二个待定,第三个是报错信息 navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err); }); // 第一个strem是流保存器 第二个stream是上面的函数创建的对象 // 这是会掉函数 function create_stream(stream) { // 通过audio_context这个实例创建一个容纳声波的容器,一个流,就是一个空盒子 var stream_input = audio_context.createMediaStreamSource(stream); // Recorder需要stream_input这个盒子 // 这个用的少,谁他么还用web reco = new Recorder(stream_input); } // 开始录音 function start_reco() { reco.record(); } // 结束录音 function stop_reco() { reco.stop(); // stop之后服务掉一下 get_audio(); reco.clear(); } // 输出 function get_audio() { // 里面是一个回掉函数,传一个wav_file一个文件流 reco.exportWAV(function (wav_file) { // 拿到它可以往后端操作,因为这个录音后再发,录音时间也常,就不需要在等了 ws.send(wav_file); }); // 当信息回来之后。data是后端传过来的信息 ws.onmessage = function (luqibazao) { // console.log(data) var res = JSON.parse(luqibazao.data); // 拿到id="play_mp3", 进行字符串拼接。src这个属性发生变化会自动播放 document.getElementById("play_mp3").src = get_file + res.file_name; } } </script> </html>
# 配置文件存放路径
# 录音文件的路径
AUDIO_FILE_PATH = "audio"
# 转的pcm格式存的的路径
AUDIO_PCM_PATH = "audio_pcm"
import requests import json def goto_tuling(text,uid): post_data = { "key": "自己的KEY", "info": text, "userid": uid } res = requests.post("http://www.tuling123.com/openapi/api", post_data) res_json = json.loads(res.content.decode("utf8")) return res_json.get("text")
# 这个是合成音频合成文本的 from aip import AipSpeech # 这个是自然语言处理的 from aip import AipNlp # 引入图灵 import tuling # 生成随机字符串 from uuid import uuid4 import setting import os APP_ID = '自己的' API_KEY = '自己的' SECRET_KEY = '自己的 ' baidu_client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) baidu_nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) # 云识别,把语音合成文本,用synthesis def text2audio(text): print(222222222222222222) # 定义合成的语音文件的名字,生成的是一个随机的字符串,加上格式 file_name = f"{uuid4()}.mp3" # 拼接路径和名字 file_path = os.path.join(setting.AUDIO_FILE_PATH, file_name) # 合成语音,带上合成语音的文本,语言,浏览器类型1,定制好的语言信息 res = baidu_client.synthesis(text, 'zh', 1, { # 音量 'vol': 5, # 语调 'pit': 7, # 语速 'spd': 4, # cosplay合成角色语音 'per': 4 }) # 判断这个流是不是一个字典,如果是,返回这个dict if type(res) == dict: return res # 成功就写入文件,这样语音文件就合成了,这里给的完整的文件路径和文件 with open(file_path, 'wb') as f: # 把这个流先写入到文件中 f.write(res) # 返回文件,可以取到文件 return file_name # print(text2audio("小明")) # text2audio("你好,小明") # 把文本合成语音,把录好音的文件名给他,用asr def audio2text(file_name): # 把文件存到audio_pcm文件夹内 print(1111111111111111111) file_pcm_path = os.path.join(setting.AUDIO_PCM_PATH, file_name) # 把mp3格式转成pcm格式 cmd_str = f"ffmpeg -y -i {file_pcm_path} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {file_pcm_path}.pcm" # os.system()会执行括号中的命令,如果命令成功执行,这条语句返回0,否则返回1 # 即成功识别文件,这个文件就有价值 os.system(cmd_str) # 定义一个内容 # audio_context = None # 把转好的名字放进去,读取文件 with open(f"{file_pcm_path}.pcm", "rb") as f: # 有值了,是读取的内容 audio_context = f.read() # 接下来调baidu的asr,传给他音频文件流,pcm,16000是音频采样率,云库 # audio_context是一个音频文件流,使用pcm格式 res = baidu_client.asr(audio_context, 'pcm', 16000, { # 识别的语种,默认1537,包含简单英文的普通话识别 "dev_pid": 1537 }) # 如果错误就返回错误 if res.get("err_no"): # 成功就返回 return res # 否则就是成功,返回 return res.get("result")[0] # print(audio2text("音频_0001.wma")) # print(audio2text("44e62976-01ac-447e-beb7-5d461e92a190.mp3")) # simnet是判断两个句子的相似度 # res = baidu_nlp.simnet("小军", "小明") # print(res) def my_nlp(text, uid): print(333333333333333333333333333333) if baidu_nlp.simnet("你叫什么名字", text).get("score") >= 0.7: return "我的名字是小明" if baidu_nlp.simnet("你今年几岁了", text).get("score") >= 0.7: return "我今年三岁了" if baidu_nlp.simnet("你喜欢吃什么", text).get("score") >= 0.7: return "我喜欢吃西瓜" tuling_str = tuling.goto_tuling(text, uid) print(tuling_str) return tuling_str # print(my_nlp("你年龄几许"))
1 把以上代码文件放到一个项目里,按照setting里面的配置创建那两个文件夹。
2 前端HTML页面需要进入一个Recorder.js文件,网上可以下载。
3 图灵里面的key自己去图灵注册,并创建自己的图灵机器人,key就在里面,里面有图灵的教程。
4 百度云指的是https://console.bce.baidu.com,里面需要自己创建一个百度语音应用,不懂可以百度一下非常简单。
5 百度云里面有APP_ID, API_KEY, SECRET_KEY。
6 里面用到的第三方库,自己去下载即可。
7 启动项目要启动Flask。
8 这个项目对新手来说不友好。