1.准备工作
由于微信小程序和百度语音识别的记录博客少之又少,所以这篇博客就诞生了。
注册登录百度AI开放平台(http://ai.baidu.com/) 找到语音技术 - 应用列表,创建应用,填写相应信息,语音包名选择不需要 创建完成后可以找到:应用列表点击查看AppID、API Key、Secret Key 注意要领取免费赠送次数,有15万次的短语音识别,我已经用掉94次,不用白不用
2.思路和uni-app开发
1.思路
使用uni-app官方代码,经测试得出经过录音会在小程序上出现临时文件,我们就把这临时文件上传到服务器上供百度语音识别,然后把识别的内容返回到小程序前端展示。
2.uni-app端开发
<template>
<view>
<view style="padding: 40% 5%;font-size: 40rpx;text-align: center;margin-bottom: 5%;">
<text>以下是识别内容:</text>
</view>
<view style="font-size: 40rpx;text-align: center;">
<text>{{sbinfo}}</text>
</view>
<view style="padding: 50% 5%;">
<button @touchstart="gtouchstart()" @touchend="gtouchend()" style="background-color: #00CD98;color: #fff;">请长按语音识别</button>
</view>
</view>
</template>
<script>
const recorderManager = uni.getRecorderManager();
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
export default {
data() {
return {
voicePath: '',
sbinfo: '',
timeOutEvent: 0, //计时器
}
},
onLoad() {
let self = this;
recorderManager.onStop(function(res) {
console.log("录音文件属性");
console.log(res);
if (res.duration > 60000) {
uni.showToast({
icon: 'none',
position: 'bottom',
title: '说话时间过长,请控制在60秒内'
});
} else {
self.voicePath = res.tempFilePath;
if (self.voicePath != null || self.voicePath != '') {
self.uploadRecord(self.voicePath);
}
}
});
},
methods: {
//开始按
gtouchstart(item) {
var self = this;
this.timeOutEvent = setTimeout(function() {
self.startRecord()
uni.showToast({
// icon: 'none',
image: "../../../static/images/publicity/yysb.png",
position: 'bottom',
title: '取消长按识别',
duration: 60000
});
}, 100); //这里设置定时器,定义长按100毫秒触发长按事件
return false;
},
//手释放,则取消长按事件,此时可以执行onclick事件
gtouchend() {
this.endRecord();
uni.hideToast();
clearTimeout(this.timeOutEvent); //清除定时器
return false;
},
uploadRecord(tempFilePath) {
// tempFilePath为RecorderManager对象返回的录音文件临时地址
console.log("临时文件:");
console.log(tempFilePath)
//正式测试
const uploadTask = uni.uploadFile({
url: 'http://192.168.1.101:8080/zh_fsxwh/wxgl/XwhUpload.action',
filePath: tempFilePath, //录音结束后返回的临时路径
name: 'upload', // 文件对应的 key值对象名称
header: {
'content-type': 'multipart/form-data'
},
success: (res) => {
this.sbinfo = res.data;
console.log(res);
},
fail: (res) => {
console.log("上传失败" + res);
}
})
},
startRecord() {
console.log('开始录音');
let options = {
duration: 60000, // 指定录音的时常,单位ms
sampleRate: 16000, // 采样率 8000(原始数)
numberOfChannels: 1, // 录音通道数
encodeBitRate: 96000, // 编码码率 48000(原始数)
format: 'PCM', // 音频格式
// format: 'MP3', // 音频格式
frameSize: 50, // 指定帧大小,单位KB 5(原始数)
};
recorderManager.start(options);
},
endRecord() {
console.log('录音结束');
recorderManager.stop();
}
}
}
</script>
<style>
</style>
对于以上代码的注意事项:
-
微信小程序调用uploadFile在真机上测试不能进行上传,一直报错uploadFile:fail Connection refused 碰到以上问题,只要是小程序的uploadFile的,第一步检测是否有在微信公众平台|小程序配置上传域名,才可以在真机使用。 第二,检查上传的头文件的Content-Type是否是multipart/form-data,表示表单提交的。 -
为方便测试,还有一种方法:把请求地址的ip更换本机网络的ipv4的地址,真机请求务必在同一个网络下,也可以实现上传文件。 不需要在微信公众平台上配置上传域名。如:127.0.0.1:8080;更换成ipv4地址:192.168.1.101:8080 -
针对我在网上看到先将前端的mp3格式的录音文件上传到后台服务器转成pcm格式再进行识别也是可以的,在于你的业务场景,我前端不需要播放录音,所以只是简单的把pcm录音文件格式上传识别成文字发送给前端展示。
3.Java后台代码
maven导入百度sdk,或者jar包导入
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.12.0</version>
</dependency>
jar包连接:https://pan.baidu.com/s/1VR2PVUto4Ps59ru5pRewaA 提取码:njev
由于本次项目是struts2项目,所以就贴上struts2的文件上传代码,大家可以自己编写springMVC的文件上传代码
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.struts2.ServletActionContext;
public class WxProgram {
private List<File> upload;
private List<String> uploadContentType;
private List<String> uploadFileName;
private String result;
private String newName;
public List<File> getUpload() {
return upload;
}
public void setUpload(List<File> upload) {
this.upload = upload;
}
public List<String> getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(List<String> uploadContentType) {
this.uploadContentType = uploadContentType;
}
public List<String> getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getNewName() {
return newName;
}
public void setNewName(String newName) {
this.newName = newName;
}
public String WxuploadFile() throws IOException {
ServletContext sc = ServletActionContext.getServletContext();
String rootPath = sc.getRealPath("/wxUpload");
String str ="";
// String rootPath="E:\\wxUpload";
File file = new File(rootPath);
System.out.println("文件数量"+this.upload.size());
if(!file.exists()){
System.out.println("文件路径"+rootPath);
file.mkdir();
}
if(this.upload.size()==1) {
this.setNewName(UUID.randomUUID().toString().replace("-", "")+"."
+FilenameUtils.getExtension(uploadFileName.get(0)));
FileUtils.copyFile(upload.get(0), new File(rootPath,this.getNewName()));
System.out.println("文件名称"+this.getNewName());
String fileParh = rootPath+"\\"+this.getNewName();
System.out.println("文件路径"+fileParh);
//百度识别
VoiceRecognition recognition = new VoiceRecognition();
try {
Boolean i = recognition.recognizeVoice(fileParh);
if(i) {
str = recognition.getResultText();
//停止1秒执行下面内容
Thread.sleep(1 * 1000);
File fe = new File(rootPath,this.getNewName());
//如果文件在本地磁盘存在即删除
if (fe.isFile() && fe.exists()) {
fe.delete();
}
}else {
str = "识别错误,请稍后重试。";
}
} catch (Exception e) {
e.printStackTrace();
}
}else {
str="文件上传数量过多";
}
return str;
}
}
百度语音识别: 为方便大家能在java工程下本地文件测试,分享测试语音文件: 百度网盘链接: https://pan.baidu.com/s/16ajM6agWCQv0Gp6sa3K3kg 提取码: i4hs
import java.io.File;
import org.json.JSONObject;
import com.baidu.aip.speech.AipSpeech;
public class VoiceRecognition {
// 设置APPID/AK/SK
// 百度AI开发平台的控制台中创建一个语音应用即可获得
public static final String APP_ID = "";
public static final String API_KEY = "";
public static final String SECRET_KEY = "";
private static final AipSpeech aipSpeech = getAipSpeech();
private static String resultText;
public static String getResultText() {
return resultText;
}
//本地文件测试
public static void main(String[] args){
VoiceRecognition voiceRecognition = new VoiceRecognition();
try {
if(voiceRecognition.recognizeVoice("C:\\Users\\Administrator\\Desktop\\sample\\MscInvisibleDemo\\test.pcm")){
System.out.println("结果为:" + voiceRecognition.getResultText());
}else{
System.out.println("识别错误");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static AipSpeech getAipSpeech(){
// 初始化一个AipSpeech
AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);
// 可选:设置网络连接参数
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
// 可选:设置代理服务器地址, http和socket二选一,或者均不设置
//client.setHttpProxy("proxy_host", proxy_port); // 设置http代理
//client.setSocketProxy("proxy_host", proxy_port); // 设置socket代理
// 可选:设置log4j日志输出格式,若不设置,则使用默认配置
// 也可以直接通过jvm启动参数设置此环境变量
// System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");
return client;
}
public boolean recognizeVoice(String filePath) throws Exception{
// 对语音文件进行识别
String path = new File(filePath).getAbsolutePath();
System.out.println(path);
JSONObject asrRes = aipSpeech.asr(path, "pcm", 16000, null);
System.out.println(asrRes);
if(asrRes.getString("err_msg").equals("success.")){
resultText = asrRes.getJSONArray("result").getString(0);
return true;
}else{
return false;
}
// 对语音二进制数据进行识别
/*byte[] data = new byte[0]; //readFileByBytes仅为获取二进制数据示例
try {
data = Util.readFileByBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
JSONObject asrRes2 = client.asr(data, "pcm", 16000, null);
System.out.println(asrRes2);*/
}
}
以下是效果展示
|