支持语音识别、自然语言理解的微信小程序(“遥知之”智能小秘)完整源码分享

记录自己搭建https的silk录音文件语音识别服务的调用过程,所有代码可在文中找链接打包下载

>>>>>>>>>>>>>>>>>>>>>>>> 欢迎转载 <<<<<<<<<<<<<<<<<<<<<<<<

本文原地址:http://www.cnblogs.com/happycxz/p/7562702.html

“遥知之”微信小程序完整源码下载:

码云:http://git.oschina.net/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demo

github: https://github.com/happycxz/nlp_olami_yaozhizhi_wechat_littleapp_demo

与本小程序密切相关的几个文章:

本文中提到的silk转wav服务端https的API搭建过程详解见

微信小程序语音识别服务搭建全过程解析(内附免费的供小程序语音识别的https服务)

微信小程序——智能小秘“遥知之”源码分享(语义理解基于olami)(注:这个是原来不支持语音识别的版本)

这次的改动是基于原来的“遥知之”版本v0.2基础之上的。加上了语音识别,界面变化较大 。下面主要介绍一下新版本首页面的功能和代码实现。

实现功能

实现一个智能生活信息查询的小秘书功能,支持查天气、新闻、日历、汇率、笑话、故事、百科、诗词、邮编、区号、菜谱、股票、节目预告,还支持闲聊、算24点、数学计算、单位换算、购物、搜索等功能。

使用方式:

新版上线支持语音识别,按下说话,松开发送。

老版本上支持摇一摇、点界面按钮、手动输入、下拉刷新这四种方式。

扫码试用(左右皆可)

支持语音识别、自然语言理解的微信小程序(“遥知之”智能小秘)完整源码分享支持语音识别、自然语言理解的微信小程序(“遥知之”智能小秘)完整源码分享

界面展示

支持语音识别、自然语言理解的微信小程序(“遥知之”智能小秘)完整源码分享

支持语音识别、自然语言理解的微信小程序(“遥知之”智能小秘)完整源码分享

开发资源

  1. 免费开放语义接口平台 olami.ai
  2. 微信小程序平台
  3. js, css
  4. 我自己搭建的https的语音识别API接口

源码分析

这里主要介绍新版本首页相关的代码,其它部分代码在 微信小程序——智能小秘“遥知之”源码分享(语义理解基于olami)(注:这个是原来不支持语音识别的版本) 的基础上,变化不怎么大,具体可参考那篇文章。

asr.js源码:

/**
* 作者:happycxz
* 时间:2017.09.19
* 源码分享链接:http://blog.csdn.net/happycxz/article/details/78024986
*
* https的silk语音识别API(专供微信小程序调用):https://api.happycxz.com/test/silk2asr/olami/asr
* 该API服务搭建全过程解析及源码分享贴:http://blog.csdn.net/happycxz/article/details/78016299
* 需要使用此API请联系作者QQ:404499164
*
* 遵循开放、分享、*、免费的精神,把开源坚持到底
*/ //获取应用实例
var app = getApp() var UTIL = require('../../utils/util.js');
var GUID = require('../../utils/GUID.js');
var NLI = require('../../utils/NLI.js'); const appkey = require('../../config').appkey
const appsecret = require('../../config').appsecret //弹幕定时器
var timer; var pageSelf = undefined; var doommList = [];
class Doomm {
constructor() {
this.text = UTIL.getRandomItem(app.globalData.corpus);
this.top = Math.ceil(Math.random() * 40);
this.time = Math.ceil(Math.random() * 8 + 6);
this.color = getRandomColor();
this.display = true;
let that = this;
setTimeout(function () {
doommList.splice(doommList.indexOf(that), 1);
doommList.push(new Doomm()); pageSelf.setData({
doommData: doommList
})
}, this.time * 1000)
}
}
function getRandomColor() {
let rgb = []
for (let i = 0; i < 3; ++i) {
let color = Math.floor(Math.random() * 256).toString(16)
color = color.length == 1 ? '0' + color : color
rgb.push(color)
}
return '#' + rgb.join('')
} Page({
data: {
j: 1,//帧动画初始图片
isSpeaking: false,//是否正在说话
outputTxt : "", //输出识别结果 doommData: []
}, initDoomm: function () {
doommList.push(new Doomm());
doommList.push(new Doomm());
doommList.push(new Doomm());
this.setData({
doommData: doommList
})
}, onLoad: function () {
pageSelf = this;
this.initDoomm();
}, //手指按下
touchdown: function () {
UTIL.log("手指按下了... new date : " + new Date)
var _this = this;
speaking.call(this);
this.setData({
isSpeaking: true
})
//开始录音
wx.startRecord({
success: function (res) {
//临时路径,下次进入小程序时无法正常使用
var tempFilePath = res.tempFilePath;
UTIL.log('record SUCCESS file path:' + tempFilePath)
_this.setData({
recordPath: tempFilePath
});
},
fail: function (res) {
//录音失败
wx.showModal({
title: '提示',
content: '录音的姿势不对!',
showCancel: false,
success: function (res) {
if (res.confirm) {
UTIL.log('用户点击确定')
return
}
}
})
}
})
},
//手指抬起
touchup: function () {
UTIL.log("手指抬起了...")
this.setData({
isSpeaking: false,
})
clearInterval(this.timer)
wx.stopRecord() var _this = this
setTimeout(function () {
var urls = "https://api.happycxz.com/test/silk2asr/olami/asr";
UTIL.log(_this.data.recordPath);
wx.uploadFile({
url: urls,
filePath: _this.data.recordPath,
name: 'file',
formData: { "appKey": appkey, "appSecret": appsecret, "userId": UTIL.getUserUnique() },
header: { 'content-type': 'multipart/form-data' },
success: function (res) {
UTIL.log('res.data:' + res.data); var nliResult = getNliFromResult(res.data);
UTIL.log('nliResult:' + nliResult);
var stt = getSttFromResult(res.data);
UTIL.log('stt:' + stt); var sentenceResult;
try {
sentenceResult = NLI.getSentenceFromNliResult(nliResult);
} catch (e) {
UTIL.log('touchup() 错误' + e.message + '发生在' + e.lineNumber + '行');
sentenceResult = '没明白你说的,换个话题?'
} var lastOutput = "==>语音识别结果:\n" + stt + "\n\n==>语义处理结果:\n" + sentenceResult;
_this.setData({
outputTxt: lastOutput,
});
wx.hideToast();
},
fail: function (res) {
UTIL.log(res);
wx.showModal({
title: '提示',
content: "网络请求失败,请确保网络是否正常",
showCancel: false,
success: function (res) {
}
});
wx.hideToast();
}
});
}, 1000)
}, //切换到老版本
turnToOld: function() {
wx.navigateTo({
url: '../index/index',
})
}, }) function getNliFromResult(res_data) {
var res_data_json = JSON.parse(res_data);
var res_data_result_json = JSON.parse(res_data_json.result);
return res_data_result_json.nli;
} function getSttFromResult(res_data) {
var res_data_json = JSON.parse(res_data);
var res_data_result_json = JSON.parse(res_data_json.result);
return res_data_result_json.asr.result;
} //麦克风帧动画
function speaking() {
var _this = this;
//话筒帧动画
var i = 1;
this.timer = setInterval(function () {
i++;
i = i % 5;
_this.setData({
j: i
})
}, 200);
}

这部分主要实现录音按钮被按下和松开触发话筒录音及结束录音,当按钮被按下后,触发调用话筒动画特效(其实是四五个图片轮流显示的效果),同时调用wx.startRecord开始录音。

当按钮松开时停止录音,然后将录音临时文件往 https://api.happycxz.com/test/silk2asr/olami/asr 上发送,同时发olami上注册申请的appKey和appSecret,以及用户唯一识别号。

从语音识别接口返回的结果是原封不动的olami官方输出结果,我们只需要取一下语音识别结果以及语义理解结果即可。 语义理解结果在原来 微信小程序——智能小秘“遥知之”源码分享(语义理解基于olami)(注:这个是原来不支持语音识别的版本) 中已经有方法解析,为了代码复用性强些,把解析nli结果的方法简单改了下,即适用新版语音识别的,也适用以前老版本的手动输入的。

代码逻辑很简单,看看就明白了,这里不再多述。

上一篇:写了一个常规性生成merge 的小脚本


下一篇:iOS开发之本地化