/******************************************* ASR 阿里云-智能语音交互-一句话识别 生成Token的api接口,本地测试http后端服务 https://github.com/xiangyuecn/Recorder 【运行】直接在当前文件夹内用命令行执行命令,即可运行: node NodeJsServer_asr.aliyun.short.js 【运行前先修改以下配置必填项】: *******************************************/ global.Config={ //请到阿里云开通 一句话识别 服务(可试用一段时间,正式使用时应当开通商用版,很便宜),得到AccessKey、Secret,参考:https://help.aliyun.com/document_detail/324194.html AccessKey:"" //【必填】根据文档创建RAM用户,分配好权限,生成访问密钥 ,Secret:"" //【必填】 //请到阿里云智能语音交互控制台创建相应的语音识别项目,每个项目可以设置一种语言模型,要支持多种语言就创建多个项目,然后填写每个项目对应的Appkey到这里,前端调用本接口的时候传入lang参数来获取到对应的Appkey ,Langs:{ "普通话":"" //【必填】至少创建一个普通话语言模型的项目用于测试 ,"粤语":"" ,"英语":"" ,"日语":"" //...... 按需提供语言对应的项目Appkey } }; global.Port=9527;//http服务端口 global.SSL={ CertFile:"" //cert.pem 证书路径,不为空将开启https ,KeyFile:"" //cert.key 密钥路径 }; //如果提供了这个本地文件,就加载过来,可覆盖global下挂载的对象 var fs = require("fs"); var localFile="NodeJsServer_asr.aliyun.short__local.js"; fs.existsSync(localFile) && require("./"+localFile); /***************一句话识别Token生成***************/ var GetAsrToken=async function(ctx, args){ var lang=args.lang;//unsafe var rtv={}; var errTag="[GetAsrToken]"; if(!Config.AccessKey || !Config.Secret){ return ctx.error(errTag+"未配置AccessKey"); } //根据前端需要的语言获得appkey,一种语言模型对应一个项目 var appkey=Config.Langs[lang]; if(!appkey){ return ctx.error(errTag+"lang["+lang+"]未配置Appkey"); } rtv.appkey=appkey; //获得Access Token,Token有效期内可以重复使用,实际使用时应当全局共享,并做好并发控制 var cache=AccessToken_RedisCache;//假装读取Redis缓存数据 if(!cache || cache.ExpireTime-Date.now()/1000<60){//缓存无效 /*RedisLock()*/{ //假装加锁,得到锁的允许更新Token cache=AccessToken_RedisCache;//假装得到锁后,二次确认是否抢占到更新机会 if(!cache || cache.ExpireTime-Date.now()/1000<60){ cache=await NewAccessToken(ctx); if(ctx.isError()){ return ctx.error(errTag+ctx.getMsg()); } console.log("NewAccessToken", cache); AccessToken_RedisCache=cache;//假装写入Redis缓存 } } } rtv.token=cache.Id; ctx.v=rtv; return ctx; }; var AccessToken_RedisCache=null; //调用阿里云接口,获得新的Access Token,文档:https://help.aliyun.com/document_detail/113251.html var NewAccessToken=async function(ctx){ var params={ AccessKeyId:Config.AccessKey ,Action:"CreateToken" ,Version:"2019-02-28" ,Format:"JSON" ,RegionId:"cn-shanghai" ,Timestamp:JSON.stringify(new Date()).replace(/"/g,"") ,SignatureMethod:"HMAC-SHA1" ,SignatureVersion:"1.0" ,SignatureNonce:RandomHEX(32).replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/,"$1-$2-$3-$4-$5") }; var arr=[]; for(var k in params){ arr.push(urlEncodeX(k)+"="+urlEncodeX(params[k])); }; arr.sort(); params=arr.join("&"); var signStr="GET&"+urlEncodeX("/")+"&"+urlEncodeX(params); var sign=HMAC('sha1',Config.Secret+"&",signStr,'base64'); params="Signature="+urlEncodeX(sign)+"&"+params; //直接发起get请求 var load=LoadRequest("http://nls-meta.cn-shanghai.aliyuncs.com/?"+params); await load.getString(false); var respTxt=load.response.data; var data={}; try{ data=JSON.parse(respTxt); }catch(e){} if(!data.Token){ ctx.error("获取Token失败["+data.Code+"]:"+data.Message); return null; }; return data.Token; }; //一些函数 var LoadRequest=require("./lib.load.js"); var Crypto=require('crypto'); var urlEncodeX=function(val){ return encodeURIComponent(val).replace(/[^\w\-\.\~\%]/g,function(a){ return "%"+("0"+a.charCodeAt(0).toString(16)).substr(-2).toUpperCase(); }); }; var RandomHEX=function(len){ var s=[]; for(var i=0,r;i