1.初始教程
1.登录百度云管理中心,点击管理控制台
2.进入后,下拉在已开通服务中选择百度语音
3.点击创建应用,得到以下应用
4.这里也可以查看它的相关技术文档
2.文字合成语音
1.安装使用Python SDK,终端下:
pip install baidu-aip
使用
from aip import AipSpeech
""" 你的 APPID AK SK """
APP_ID = '11793737'
API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH'
SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR'
client = AipSpeech(APP_ID,API_KEY,SECRET_KEY)
result = client.synthesis("第一次把下列文字转成MP3语音","zh",1,{
"spd":4,
"vol":7,
"pit":8,
"per":4
})
if not isinstance(result,dict):
# 创建一个auido.mp3文件
with open("auido.mp3","wb") as f:
f.write(result)
print(result) # 打印bytes字节
此时文件中会多出一个mp3结尾的文件,我们把改文字已经转换成语音写入在了该文件中
3.语音转义成文字
参考技术文档说明,这里支持的语音格式文件有:pcm(不压缩)、wav(不压缩,pcm编码)、amr(压缩格式)
我们需要借助第三方工具ffmpeg把任意格式的语音转移成pcm格式
3.1 ffmpeg说明:
FFmpeg 是一个自由软件,可以运行音频和视频多种格式的录影、转换、流功能包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,
以及libavformat——一个音频与视频格式转换库。说简单点,这个工具可以将wav wma mp3 等音频文件转换为 pcm 无压缩音频文件
下载链接:猛戳此处
或者此处链接:链接: https://pan.baidu.com/s/1-TEQZP9QbJSlGSYedyAUFw 密码: 2z8l
下载后解压缩(我把它放在了D盘下),注意可执行的exe文件是在文件的bin目录,配置我们的环境变量
配置后,在终端测试效果:
使用
我们用命令行对这个 auido.mp3 进行pcm格式的转换然后得到 audio.pcm
命令是 : ffmpeg -y -i audio.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 audio.pcm
from aip import AipSpeech
import os
""" 你的 APPID AK SK """
APP_ID = '11793737'
API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH'
SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR'
client = AipSpeech(APP_ID,API_KEY,SECRET_KEY)
# 读取文件
filePath = "auido.mp3"
def get_file_content(filePath):
# 用于将任何形式的语音文件格式转化成pcm格式,这里使用的是py3.6的模板语法,其他版本可以使用字符串的格式化语法
os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
with open(f"{filePath}.pcm",'rb') as fp:
return fp.read()
# 识别本地文件
liu = get_file_content(filePath)
res = client.asr(liu,'pcm',16000,{
'dev_pid':1536
})
print(res) # 查看格式
# {'corpus_no': '6599876657908188502', 'err_msg': 'success.', 'err_no': 0,
# 'result': ['第一次把下列文字转MP3语音'], 'sn': '465883505901536653530'}
if res.get("result"):
print(res.get('result')[0])
else:
print(res)
# 注意这里转化后文件中会搓出一个auido.mp3.pcm格式的文件
相关参数说明:
asr函数需要四个参数
第一个参数: speech 音频文件流 建立包含语音内容的Buffer对象, 语音文件的格式,pcm 或者 wav 或者 amr
第二个参数: format 文件的格式,包括pcm(不压缩)、wav、am
第三个参数: rate 音频文件采样率 如果使用刚刚的FFmpeg的命令转换的,你的pcm文件就是16000
第四个参数: dev_pid 音频文件语言id 默认1537(普通话 输入法模型)
1636 # 普通话,支持简单英文识别
1737 # 英文
View Code
4.输入语音实现自动交互
这里需要我们的图灵机器人技术,创建一个机器人
对我们的机器人进行相关设置
4.1 api接口使用
测试:
import requests
import json
apiKey = "d76b3e9669404fe7b5a1949466fd6376"
userId = "taylor" # 机器人名称
data = {
# 请求的类型 0 文本 1 图片 2 音频
"reqType": 0,
"perception": {
"inputText": {
"text": "你是谁"
}
},
"userInfo": {
"apiKey": apiKey,
"userId": userId
}
}
tuling_url = "http://openapi.tuling123.com/openapi/api/v2"
res = requests.post(tuling_url,json=data) # 请求url
# 将返回信息解码
res_dic = json.loads(res.content.decode("utf-8")) # type:dict
# 得到返回信息中的文本信息
res_type = res_dic.get("results")[0].get("values").get("text")
print(res_type)
效果:
现在有文本信息了,我们可以调用上面的文本信息转换成语音,让它实现语音播放
third.py
import os
from aip import AipSpeech
from aip import AipNlp
""" 你的 APPID AK SK """
APP_ID = '11793737'
API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH'
SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR'
client = AipSpeech(APP_ID,API_KEY,SECRET_KEY)
# 用于将任何形式的语音文件格式转化成pcm格式
# 这里使用的是py3.6的模板语法,其他语言可以使用字符串的格式化语法
def get_file_content(filePath):
os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
with open(f"{filePath}.pcm",'rb') as fp:
return fp.read()
def text2audio(text):
result = client.synthesis(text, 'zh', 1, {
"spd": 4,
'vol': 7,
"pit": 8,
"per": 4
})
if not isinstance(result, dict):
# 创建一个auido.mp3文件
with open('auido.mp3', 'wb') as f:
f.write(result)
return get_file_content('auido.mp3')
test.py
import requests
import json
import third
apiKey = "d76b3e9669404fe7b5a1949466fd6376"
userId = "taylor" # 机器人名称
data = {
# 请求的类型 0 文本 1 图片 2 音频
"reqType": 0,
"perception": {
"inputText": {
"text": "你是谁"
}
},
"userInfo": {
"apiKey": apiKey,
"userId": userId
}
}
tuling_url = "http://openapi.tuling123.com/openapi/api/v2"
res = requests.post(tuling_url,json=data) # 请求url
# 将返回信息解码
res_dic = json.loads(res.content.decode("utf-8")) # type:dict
# 得到返回信息中的文本信息
res_type = res_dic.get("results")[0].get("values").get("text")
# 调用text2audio函数
third.text2audio(res_type)
执行后,此时文件中会多出一个auido.mp3和一个auido.mp3.pcm文件,文件内容就是机器人对我们的文本回复的内容
5.web录音实现互动问答
5.1 websocket监听
ai.py
from flask import Flask,request,render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket
app = Flask(__name__,template_folder="../templates")
@app.route("/index")
def index():
# 获取请求的WebSocket对象
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
print(user_socket) # <geventwebsocket.websocket.WebSocket object at 0x000002718C07F798>
print(request.remote_addr) # 远程ip地址127.0.0.1
while True:
# 接收消息
msg = user_socket.receive()
print(msg)
@app.route("/")
def home():
return render_template("index.html")
if __name__ == "__main__":
http_serv = WSGIServer(("0.0.0.0",9520),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script type="application/javascript">
//创建 WebSocket 对象
var ws = new WebSocket("ws://127.0.0.1:9520/index");
</script>
</html>
这里我们启动我们的程序,在浏览器输入http://127.0.0.1:9520/,此时在pycharm上就会传回我们的websocket对象以及远程IP地址
我们利用websocket已经实现了前端与后端的交互吗,现在我们需要通过websocket把我们网页上录的语音换到后端去
5.2 recorder.js录音插件
recorder.js是HTML5录音插件,它可以实现在线录音。
部分浏览器还存在兼容性(如ie,Safari)
Chrome47以上以及QQ浏览器需要HTTPS支持
github下载地址为:https://github.com/mattdiamond/Recorderjs
html5 Audio常用属性和函数事件参考链接:
项目构架
./
├── ai.py
├── static
│ └── recorder.js
└── templates
└── index.html
在index.html中导入我们的recorder.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{#audio是HTML5的标签,autoplay表示自动播放,controls表示展示组件#}
<audio src="" autoplay controls id="player"></audio>
<br>
<button onclick="start_reco()">开始废话</button>
<br>
<button onclick="stop_reco()">发送语音</button>
</body>
<script src="/static/recorder.js"></script>
<script type="application/javascript">
// 创建WebSocket对象
var ws = new WebSocket("ws://127.0.0.1:5300/index");
var reco = null; //录音对象
// 创建AudioContext对象
// AudioContext() 构造方法创建了一个新的 AudioContext 对象 它代表了一个由音频模块链接而成的音频处理图, 每一个模块由 AudioNode 表示
var audio_context = new AudioContext();
//要获取音频和视频,需要用到getUserMedia。桌面平台支持的浏览器包括Chrome, Firefox, Opera和Edge。
// 这里的|| 表示或者的关系,也就是能支持的浏览器
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
// 拿到媒体对象,允许音频对象
navigator.getUserMedia({audio: true}, create_stream, function (err) {
console.log(err)
});
//创建媒体流容器
function create_stream(user_media) {
//AudioContext接口的createMediaStreamSource()方法用于创建一个新的MediaStreamAudioSourceNode 对象,
// 需要传入一个媒体流对象(MediaStream对象)(可以从 navigator.getUserMedia 获得MediaStream对象实例),
// 然后来自MediaStream的音频就可以被播放和操作。
// MediaStreamAudioSourceNode 接口代表一个音频接口,是WebRTC MediaStream (比如一个摄像头或者麦克风)的一部分。
// 是个表现为音频源的AudioNode。
var stream_input = audio_context.createMediaStreamSource(user_media);
// 给Recoder 创建一个空间,麦克风说的话,都可以录入。是一个流
reco = new Recorder(stream_input);
}
function start_reco() { //开始录音
reco.record(); //往里面写流
}
function stop_reco() { //停止录音
reco.stop(); //停止写入流
get_audio(); //调用自定义方法
reco.clear(); //清空容器
}
// 获取音频
function get_audio() {
reco.exportWAV(function (wav_file) {
// 发送数据给后端
ws.send(wav_file);
})
}
</script>
</html>
启动程序后,点击开始按钮,后台会接收到一个bytearray类型的字符,这就是我们的声音字节,现在需要我们把它写入文件
修改我们的后台程序
from flask import Flask,request,render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket
app = Flask(__name__,template_folder="../templates")
@app.route("/index")
def index():
# 获取请求的WebSocket对象
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
print(user_socket) # <geventwebsocket.websocket.WebSocket object at 0x000002718C07F798>
print(request.remote_addr) # 远程ip地址127.0.0.1
while True:
# 接收消息
msg = user_socket.receive()
if type(msg) == bytearray:
# 写入文件123.wav
with open("123.wav", "wb") as f:
f.write(msg)
@app.route("/")
def home():
return render_template("index.html")
if __name__ == "__main__":
http_serv = WSGIServer(("0.0.0.0",5300),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
此时重启文件,我们就能把我们的声音录制成一个123.wav格式的文件,这个就是我们录制的声音
5.3 整合以上内容
现在我们需要完成在浏览器输入语音,在线实时和图灵机器人交互的效果,我们把以上代码进行整合
流程:通过浏览器发送语音给后端-->后端将音频文件转成文字发个图灵机器人-->后端再讲图灵回执的文字转成音频文件-->回执的音频文件发送给前端
test.py
import requests
import json
import third
apiKey = "d76b3e9669404fe7b5a1949466fd6376"
userId = "taylor" # 机器人名称
data = {
# 请求的类型 0 文本 1 图片 2 音频
"reqType": 0,
"perception": {
"inputText": {
"text": "你是谁"
}
},
"userInfo": {
"apiKey": apiKey,
"userId": userId
}
}
tuling_url = "http://openapi.tuling123.com/openapi/api/v2"
def to_tuling(question,user_id):
# 修改请求参数中的inputText,也就是问题
data["perception"]["inputText"]["text"] = question
# # 修改userInfo
data["userInfo"]["userId"] = user_id
res = requests.post(tuling_url,json=data) # 请求url
# 将返回信息解码
res_dic = json.loads(res.content.decode("utf-8")) # type:dict
# 得到返回信息中的文本信息
result = res_dic.get("results")[0].get("values").get("text")
# print(res_type)
return result
third.py
import os
from aip import AipSpeech
from aip import AipNlp
import test
""" 你的 APPID AK SK """
APP_ID = '11793737'
API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH'
SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR'
client = AipSpeech(APP_ID,API_KEY,SECRET_KEY)
nlp_client = AipNlp(APP_ID, API_KEY, SECRET_KEY)
# 用于将任何形式的语音文件格式转化成pcm格式
# 这里使用的是py3.6的模板语法,其他语言可以使用字符串的格式化语法
def get_file_content(filePath):
os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
with open(f"{filePath}.pcm",'rb') as fp:
return fp.read()
def text2audio(text):
result = client.synthesis(text, 'zh', 1, {
"spd": 4,
'vol': 7,
"pit": 8,
"per": 4
})
if not isinstance(result, dict):
# 创建一个auido.mp3文件
with open('audio.mp3', 'wb') as f:
f.write(result)
return 'audio.mp3'
# 识别本地文件,转义成文本信息
def audio2text(file_path):
a = client.asr(get_file_content(file_path), 'pcm', 16000, {
'dev_pid': 1536,
})
if a.get("result") :
return a.get("result")[0]
def my_nlp(q,uid):
a = test.to_tuling(q,uid)
return a
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{#audio是HTML5的标签,autoplay表示自动播放,controls表示展示组件#}
<audio src="" autoplay controls id="player"></audio>
<br>
<button onclick="start_reco()">开始废话</button>
<br>
<button onclick="stop_reco()">发送语音</button>
</body>
<script src="/static/recorder.js"></script>
<script type="application/javascript">
// 创建WebSocket对象,index后面的是userid,是图灵机器人需要的
var ws = new WebSocket("ws://127.0.0.1:5300/index/taylor");
var reco = null; //录音对象
// 创建AudioContext对象
// AudioContext() 构造方法创建了一个新的 AudioContext 对象 它代表了一个由音频模块链接而成的音频处理图, 每一个模块由 AudioNode 表示
var audio_context = new AudioContext();
//要获取音频和视频,需要用到getUserMedia。桌面平台支持的浏览器包括Chrome, Firefox, Opera和Edge。
// 这里的|| 表示或者的关系,也就是能支持的浏览器
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
// 拿到媒体对象,允许音频对象
navigator.getUserMedia({audio: true}, create_stream, function (err) {
console.log(err)
});
//创建媒体流容器
function create_stream(user_media) {
//AudioContext接口的createMediaStreamSource()方法用于创建一个新的MediaStreamAudioSourceNode 对象,
// 需要传入一个媒体流对象(MediaStream对象)(可以从 navigator.getUserMedia 获得MediaStream对象实例),
// 然后来自MediaStream的音频就可以被播放和操作。
// MediaStreamAudioSourceNode 接口代表一个音频接口,是WebRTC MediaStream (比如一个摄像头或者麦克风)的一部分。
// 是个表现为音频源的AudioNode。
var stream_input = audio_context.createMediaStreamSource(user_media);
// 给Recoder 创建一个空间,麦克风说的话,都可以录入。是一个流
reco = new Recorder(stream_input);
}
function start_reco() { //开始录音
reco.record(); //往里面写流
}
function stop_reco() { //停止录音
reco.stop(); //停止写入流
get_audio(); //调用自定义方法
reco.clear(); //清空容器
}
// 获取音频
function get_audio() {
reco.exportWAV(function (wav_file) {
// 发送数据给后端
ws.send(wav_file);
})
}
// 接收到服务端数据时触发
ws.onmessage = function (data) {
console.log(data.data); //打印文件名
}
</script>
</html>
ai.py -->执行文件
from flask import Flask,request,render_template,send_file
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket
import third
app = Flask(__name__,template_folder="../templates",static_folder="../static")
@app.route("/index/<uid>")
def index(uid): # 接收uid
# 获取请求的WebSocket对象
user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
print(user_socket)
# print(request.remote_addr) # 远程ip地址
while True:
# 接收消息
msg = user_socket.receive()
if type(msg) == bytearray:
# 写入文件123.wav
with open("123.wav", "wb") as f:
f.write(msg)
# 将音频文件转换为文字
res_q = third.audio2text("123.wav")
# 调用my_nlp函数,内部调用图灵机器人
res_a = third.my_nlp(res_q,uid)
# 将文字转换为音频文件
file_name = third.text2audio(res_a)
# 发送文件名给前端
user_socket.send(file_name)
@app.route("/")
def home_page():
return render_template("index.html")
@app.route("/get_file/<file_name>") # 获取音频文件
def get_file(file_name): # 此方法用于前端调取后端的音频文件,用于自动播放
return send_file(file_name)
if __name__ == "__main__":
http_serv = WSGIServer(("0.0.0.0",5300),app,handler_class=WebSocketHandler)
http_serv.serve_forever()
相关说明:这里浏览器很关键,很容易失败,多试几个浏览器,我调试的是谷歌浏览器,需要我们把油猴插件关掉,还需要把静态文件路径加上
执行完后,页面打印台会输出一个audio.mp3文件
5.4 实现自动播放
实现页面自动播放生成的audio.mp3文件
index.html -->直接替换上面html的即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{#audio是HTML5的标签,autoplay表示自动播放,controls表示展示组件#}
<audio src="" autoplay controls id="player"></audio>
<br>
<button onclick="start_reco()">开始废话</button>
<br>
<button onclick="stop_reco()">发送语音</button>
</body>
<script src="/static/recorder.js"></script>
<script type="application/javascript">
// 访问后端的get_file,得到一个文件名
var get_file = "http://127.0.0.1:5300/get_file/";
// 创建WebSocket对象,index后面的是userid,是图灵机器人需要的
var ws = new WebSocket("ws://127.0.0.1:5300/index/taylor");
var reco = null; //录音对象
// 创建AudioContext对象
// AudioContext() 构造方法创建了一个新的 AudioContext 对象 它代表了一个由音频模块链接而成的音频处理图, 每一个模块由 AudioNode 表示
var audio_context = new AudioContext();
//要获取音频和视频,需要用到getUserMedia。桌面平台支持的浏览器包括Chrome, Firefox, Opera和Edge。
// 这里的|| 表示或者的关系,也就是能支持的浏览器
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
// 拿到媒体对象,允许音频对象
navigator.getUserMedia({audio: true}, create_stream, function (err) {
console.log(err)
});
//创建媒体流容器
function create_stream(user_media) {
//AudioContext接口的createMediaStreamSource()方法用于创建一个新的MediaStreamAudioSourceNode 对象,
// 需要传入一个媒体流对象(MediaStream对象)(可以从 navigator.getUserMedia 获得MediaStream对象实例),
// 然后来自MediaStream的音频就可以被播放和操作。
// MediaStreamAudioSourceNode 接口代表一个音频接口,是WebRTC MediaStream (比如一个摄像头或者麦克风)的一部分。
// 是个表现为音频源的AudioNode。
var stream_input = audio_context.createMediaStreamSource(user_media);
// 给Recoder 创建一个空间,麦克风说的话,都可以录入。是一个流
reco = new Recorder(stream_input);
}
function start_reco() { //开始录音
reco.record(); //往里面写流
}
function stop_reco() { //停止录音
reco.stop(); //停止写入流
get_audio(); //调用自定义方法
reco.clear(); //清空容器
}
// 获取音频
function get_audio() {
reco.exportWAV(function (wav_file) {
// 发送数据给后端
ws.send(wav_file);
})
}
// 接收到服务端数据时触发
ws.onmessage = function (data) {
// console.log(data.data);
console.log(get_file + data.data); //打印文件名
// 修改id为player的src属性,
document.getElementById("player").src = get_file + data.data;
}
</script>
</html>
ok,下来就可以听到声音了
# 补充说明:这里生成的文件名我们给写死了,最好生成动态文件名,可以引入uuid,否则会出现缓存现象,得不到我们的效果