框架介绍
前端
使用微信小程序进行录音,并将录音内容上传至后端,根据后端返回的结果判断录音内容所表达的情绪
后端
基于Python的flask框架搭建一个简易的后端,用于保存上传录音的音频,并对音频进行转码后提交至百度语音识别接口获取识别的文字内容,再将识别的文字内容提交至百度对话情绪识别接口获取所带情绪的系数比,根据系数比判断所表达的情绪
所需环境
语言环境
Python 3.0+(并安装相关模块:pip install flask
、pip install baidu-aip
)
工具
微信开发者工具(开发微信小程序)
下载链接:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
ffmpeg(对录音音频进行转码)
下载链接:https://ffmpeg.zeranoe.com/builds/
微信小程序开发
全局配置文件
app.json
{
"pages": [
"pages/index/index",
"pages/show/show",
"pages/logs/logs"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#0094ff",
"navigationBarTitleText": "录音界面",
"navigationBarTextStyle": "black"
},
"tabBar": {
"color": "#000",
"selectedColor": "#f23030",
"backgroundColor": "#0094ff",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/index/index",
"text": "初始页面"
},
{
"pagePath": "pages/show/show",
"text": "查看结果"
}
]
},
"sitemapLocation": "sitemap.json"
}
录音及请求界面
界面设计代码(pages/index/index.wxml)
<view class="main">
<button bindtap='play'>播放录音</button>
<button bindtap='submit'>上传</button>
<button bindtouchstart="clickDown" bind:touchend="clickUp" touchcancel="clickUp" bindtouchmove="clickMove" class="record_btn">
<span wx:if="{{recording}}">{{cancel_record?'松开取消':'松开发送'}}</span>
<span wx:else>按下录音</span>
</button>
</view>
录音及上传功能代码(pages/index/index.js)
const app = getApp();
const recorder = wx.getRecorderManager();
const player = wx.createInnerAudioContext();
const file = wx.getFileSystemManager();
var that;
var file_path;
Page({
onLoad: function (options) {
that = this;
//先定好停止录音后要干嘛
recorder.onStop(function suc(e) {
console.log(e.tempFilePath);
file_path = e.tempFilePath;
//保存录音文件的临时路径
that.setData({
filePath: e.tempFilePath,
})
wx.setStorageSync('filePath', e.tempFilePath);
wx.showLoading({
title: '文件读取中...'
})
wx.hideLoading();
})
},
submit() {
wx.uploadFile({
// 将音频上传
url: 'http://127.0.0.1:5000/voice',
filePath: file_path,
name: 'file',
header: {
'content-type': 'multipart/form-data'
},
success: function (res) {
console.log(res.data);
app.globalData.result = res.data;
// 将返回的数据放入全局里
},
fail: function (res) {
}
});
},
//手指按下
clickDown(e) {
console.log('start');
that.setData({
recording: true,
start_y: e.touches[0].clientY,
cancel_record: false,
})
//开始录音
recorder.start({
// duration: 60000,//最大时长
// sampleRate: that.data.rate,//采样率
// numberOfChannels: 1,//录音通道数
// encodeBitRate: 16000,//编码码率,有效值见下表格
format: 'silk',//音频格式
// frameSize: 2000,//指定大小 kb
})
},
//手指移动
clickMove(e) {
if (e.touches[0].clientY - that.data.start_y <= -50) {
that.setData({
cancel_record: true,
})
} else {
that.setData({
cancel_record: false,
})
}
return false;
},
//手指松开
clickUp(e) {
if (that.data.cancel_record) {
wx.showModal({
title: '提示',
content: '您选择了取消发送,确定吗?',
confirmText: '继续发送',
cancelText: '取消重录',
success: res => {
if (res.confirm) {
wx.showToast({
title: '发送成功',
})
} else {
wx.showToast({
title: '您选择了取消',
})
}
that.setData({
recording: false
})
}
})
} else {
wx.showToast({
title: '发送成功',
})
that.setData({
recording: false
})
}
recorder.stop();
return false;
},
//播放
play() {
player.src = that.data.filePath;
player.play();
},
})
注:
开发时注意关闭合法域名等的校验,如图:
数据展示界面
界面设计代码(pages/show/show.wxml)
<text>你说的话是:</text>
<view> {{result.result.text}}</view>
<text>识别的情绪是:</text>
<view> {{result.result.emotion}}</view>
载入数据代码(pages/show/show.js)
var app = getApp();
Page({
onLoad: function (options) {
console.log(app.globalData);
var that = this;
if (app.globalData.result){
that.setData({
result: JSON.parse(app.globalData.result),
// 将数据转json格式供读取
});
}else{
}
},
onShow() {
this.onLoad();
// 每次打开页面时重新载入
},
})
后端代码(.py)
from flask import Flask, request
from aip import AipSpeech, AipNlp
import os
import json
app = Flask(__name__)
@app.route('/voice', methods=['GET','POST'])
def main():
'''后端请求处理接口,将小程序上传的音频保存、转码,并发送到语音识别接口识别文字后,再调用对话情绪识别接口'''
result = {"status": 0}
try:
f = request.files['file']
f.save("voice/xxx.silk")
# 保存文件至本地路径,需要提前在py文件的路径下创建个voice文件夹
os.system("ffmpeg -y -i voice/xxx.silk -acodec pcm_s16le -f s16le -ac 1 -ar 16000 voice/a.pcm")
# 文件转码
text = get_result()
# 调用语音识别接口获取识别文字
emotion = get_emotion(text)
# 调用对话情绪识别接口获取判断结果
result["status"] = 1
result["result"] = emotion
except Exception as e:
print(repr(e))
finally:
return json.dumps(result)
def get_result(path='voice/a.pcm'):
'''调用百度语音识别接口,返回识别后的文字结果'''
# 百度语音识别接口的ID、KEY等信息
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
# 读取转码后的文件
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
result = client.asr(get_file_content(path), 'pcm', 16000, {
'dev_pid': 1536,
})
print(result)
return result["result"][0]
def get_emotion(text=""):
'''调用百度对话情绪识别接口,返回判断的情绪结果'''
# 百度自然语言处理接口的ID、KEY等信息
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
emotion_result = {
"text": text
}
client = AipNlp(APP_ID, API_KEY, SECRET_KEY)
options = {
"scene": "talk"
}
try:
result = client.emotion(text, options)
for each in result["items"]:
if each["label"] == "optimistic":
opti = each["prob"]
elif each["label"] == "pessimistic":
pess = each["prob"]
if opti >= pess:
emotion_result["emotion"] = "高兴"
else:
emotion_result["emotion"] = "悲伤"
except Exception as e:
print(repr(e))
finally:
return emotion_result
if __name__ == '__main__':
app.run(debug=True)
使用测试
使用步骤
先运行Python后端文件,然后在微信小程序当中点击录音->上传,当在控制台看到返回的结果时,进入查看结果页面查看
结果图示
注意点
百度语音识别接口音频转码问题
对于调用百度语音识别接口,并非直接上传音频即可正确识别,在上传前需要进行音频的转码,否则往往结果会返回错误码3301,并提示你音频质量不行,其中转码基于ffmpeg
工具,相关命令可参考官方提供的文档:https://cloud.baidu.com/doc/SPEECH/ASR-Tool.html#.E8.BD.AC.E6.8D.A2.E5.91.BD.E4.BB.A4.E7.A4.BA.E4.BE.8B
当然鉴于微信小程序的录音格式还很特殊,建议直接生成.silk
文件,然后根据如下命令直接生成转码后的.pcm
文件供接口识别:
ffmpeg -y -i xxx.silk(源文件) -acodec pcm_s16le -f s16le -ac 1 -ar 16000 xxx.pcm(输出文件)
微信小程序录音格式问题
由于微信小程序的录音格式比较特殊(貌似是silk格式),因此当后端将录音保存到本地时,无法直接打开文件读取,当然上传到百度语音识别接口也同样无法识别,为此如果想要在本地播放该音频,可以下载软件:silk v3(建议下载完整版),将文件转格式后即可播放,软件地址:https://kn007.net/topics/batch-convert-silk-v3-audio-files-to-mp3-in-windows/
使用步骤
1.在软件下载完成后,将压缩包内文件都拷贝到一个文件夹下,打开文件silk2mp3.exe
如图:
2.导入对应的silk文件,并选择:解码->开始转换即可,此时生成的解码文件就可以播放了