这篇博文应该是这个应用的最后一个部分,主要是实现调用本地麦克风录音的前后端。
前端页面的实现
在这个页面中,需要实现录音功能,而录音功能在参考了网上的相关资料之后,决定采用recorder.js
的现行库(因为如果要造轮子的话需要自己去了解语音采样等过程),这是库的链接。
对于我这种前端小白本来是没看懂要怎么使用的,后来才发现在其项目目录下有dist/recorder.js
文件,如果你使用是Flask框架只需要在static
文件夹中导入recorder.js
以及recorder.js.map
两个文件并采用如下方法引入
<script type="text/javascript" src="{{ url_for('static', filename='recorder.js') }}"></script>
通过recorder
我决定设置录音相关的六个按钮分别是开始、暂停、继续、结束、上传、播放。于是就有了以下的HTML代码
<body style="background-size: 100%; background-image:url({{ url_for('static', filename='cool-2.png') }})">
<div id="items">
<div>
<p>麦克风录制</p>
<input type="button" value="开始录制" id="record_btn" class="item_btn_left">
<input type="button" value="暂停录制" id="stop_btn" class="item_btn_left">
<input type="button" value="继续录制" id="resume_btn" class="item_btn">
<br>
<input type="button" value="结束录制" id="end_btn" class="item_btn_left">
<input type="button" value="播放录音" id="play_btn" class="item_btn_left">
<input type="button" value="上传录音" id="submit_btn" class="item_btn">
</div>
<div>
<p>识别文本</p>
<input type="text" id="res_text" disabled="disabled">
<input type="button" value="返回主页" onclick="back()" id="back_btn">
</div>
</div>
</body>
前端CSS样式
没有什么CSS基础又想让界面好看一点的我,在这个页面的按钮样式上参考了其他大佬的所写的CSS代码样式,并修改了其大小和变化时间长短,所以这里并没有太多可以讲述的东西。直接附上相关链接以及我修改后的CSS代码
.item_btn {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
width: 100px;
}
.item_btn_left {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
width: 100px;
float: left;
margin-right: 55px;
}
#back_btn {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
width: 100px;
left: 75%;
margin-top: 100px;
}
#back_btn, .item_btn, .item_btn_left {
border: 0;
border-radius: 10px;
background: #2ec4b6;
text-transform: uppercase;
color: white;
font-size: 16px;
font-weight: bold;
padding: 15px 30px;
outline: none;
position: relative;
transition: border-radius 1.5s;
-webkit-transition: border-radius 1.5s;
}
#back_btn:hover, .item_btn:hover, .item_btn_left:hover {
border-bottom-right-radius: 50px;
border-top-left-radius: 50px;
border-bottom-left-radius: 10px;
border-top-right-radius: 10px;
}
通过以上的CSS可以实现如下的鼠标悬停效果
前端功能实现
实现基础的录音功能
参阅recorder.js
API可以发现这个库提供基础的录音功能,且实现较为简单。以下为使用API的jQuery代码,用来实现相关的功能。这里需要注意的是当使用了jQuery中的on
函数来绑定相关的事件时,就不需要在HTML元素中使用属性onclick
来绑定相关函数了,这个问题一度折磨了我许久,最后还是感谢好友的修改。
<script>
window.onload = function() {
let recorder;
$("#record_btn").on('click', function (e) {
console.log("开始录制");
recorder = new Recorder({
sampleBits: 16,
sampleRate: 16000,
numChannels: 1
});
recorder.start().then(
() => {// 开始录音
},
(error) => {// 出错了
console.log(`${error.name} : ${error.message}`);
});
});
$("#stop_btn").on('click', function () {
console.log("暂停录制");
recorder.pause();
});
$("#resume_btn").on('click', function () {
console.log("继续录制");
recorder.resume();
});
$("#end_btn").on('click', function () {
console.log("结束录制");
recorder.stop();
});
$("#play_btn").on('click', function () {
console.log("播放");
recorder.play();
});
</script>
实现录音上传的功能
要实现录音上传首先我们要先获取录音文件,recorder.js
库提供了相应的API(getWAVBlob
)得到录音文件的.wav
形式的文件。
要上传这个文件就需要通过AJAX技术来上传,此时需要创建一个FormData
来提交这个文件,通过append函数来接收这个文件,并将其命名为audio.wav
。最后创建一个AJAX对象来上传这个文件。
在这个AJAX对象中,我们需要将提交方法设置为POST,并指定一个url来作为提交的目的。在这里有一个参数processData
默认值为true
,表示在上传文件时,jQuery会对数据进行序列化处理,在使用true
为参数值时,产生了提交文件的错误,所以这里建议将参数设置为false
。
最后通过recorder.js
的API将录音文件删除,以便下一次调用。JS代码如下
$("#submit_btn").on('click', function () {
let wav_blob = recorder.getWAVBlob();
let formData = new FormData();
formData.append('file', wav_blob, 'audio.wav'); {# 添加文件到表单中 #}
$.ajax({
type: "POST",
url: "/micro_upload",
data: formData,
cache: false,
processData: false,
contentType: false,
success: function (data) {
if (data.msg === 'success') {
recorder.destroy().then(function () {
recorder = null;
});
}
else {
console.log(data.msg);
recorder.destroy().then(function () {
recorder = null;
});
}
}
})
})
后端接收
在后端接收中,我们需要将上述对应的url利用装饰器映射到相应的接收函数中,在这个函数中可以参考之前的接收文件函数,提交的文件将保存在Flask中的request.file
中。
利用secure_filename
函数对文件名进行保留,最后保存至相应的工程目录中。相关代码如下
@app.route('/micro_upload', methods=['post'])
def micro_upload():
audio_input = request.files['file']
filename = secure_filename(audio_input.filename)
audio_input.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return
页面实现效果
小结
至此,此应用的框架基本完成,最后的识别部分需要等到算法实现后再行融合。