From a696bc3bbea9cf370828904ceee05dd0d2eceb4b Mon Sep 17 00:00:00 2001 From: abearxiong Date: Sun, 20 Apr 2025 18:46:48 +0800 Subject: [PATCH] temp --- backend/demo/index.html | 5 + backend/demo/index.js | 393 ++++++ backend/demo/recorder.mp3.min.js | 6 + backend/package.json | 14 + backend/src/NodeJsServer_asr.aliyun.short.cjs | 312 +++++ backend/src/lib.load.cjs | 199 +++ index.html | 5 + package.json | 2 +- pnpm-lock.yaml | 327 +---- public/extensions/asr.aliyun.short.js | 910 +++++++++++++ public/extensions/buffer_stream.player.js | 887 +++++++++++++ public/extensions/create-audio.nmn2pcm.js | 372 ++++++ public/extensions/dtmf.decode.js | 268 ++++ public/extensions/dtmf.encode.js | 196 +++ public/extensions/frequency.histogram.view.js | 377 ++++++ public/extensions/lib.fft.js | 118 ++ public/extensions/sonic.js | 1155 +++++++++++++++++ public/extensions/wavesurfer.view.js | 278 ++++ public/extensions/waveview.js | 229 ++++ public/i18n/Template.js | 935 +++++++++++++ public/i18n/en-US.js | 782 +++++++++++ public/i18n/es.js | 935 +++++++++++++ public/i18n/fr.js | 935 +++++++++++++ public/i18n/zh-CN.js | 41 + public/recorder.mp3.min.d.ts | 2 + public/recorder.mp3.min.js | 6 + public/recorder.wav.min.d.ts | 2 + public/recorder.wav.min.js | 6 + src/app.ts | 7 + src/main.tsx | 10 +- src/pages/record/index.tsx | 82 ++ src/pages/record/module/AliAsr.ts | 95 ++ src/pages/record/module/MyRecorder.ts | 111 ++ vite.config.mjs | 7 + 34 files changed, 9681 insertions(+), 328 deletions(-) create mode 100644 backend/demo/index.html create mode 100644 backend/demo/index.js create mode 100644 backend/demo/recorder.mp3.min.js create mode 100644 backend/package.json create mode 100644 backend/src/NodeJsServer_asr.aliyun.short.cjs create mode 100644 backend/src/lib.load.cjs create mode 100644 public/extensions/asr.aliyun.short.js create mode 100644 public/extensions/buffer_stream.player.js create mode 100644 public/extensions/create-audio.nmn2pcm.js create mode 100644 public/extensions/dtmf.decode.js create mode 100644 public/extensions/dtmf.encode.js create mode 100644 public/extensions/frequency.histogram.view.js create mode 100644 public/extensions/lib.fft.js create mode 100644 public/extensions/sonic.js create mode 100644 public/extensions/wavesurfer.view.js create mode 100644 public/extensions/waveview.js create mode 100644 public/i18n/Template.js create mode 100644 public/i18n/en-US.js create mode 100644 public/i18n/es.js create mode 100644 public/i18n/fr.js create mode 100644 public/i18n/zh-CN.js create mode 100644 public/recorder.mp3.min.d.ts create mode 100644 public/recorder.mp3.min.js create mode 100644 public/recorder.wav.min.d.ts create mode 100644 public/recorder.wav.min.js create mode 100644 src/pages/record/index.tsx create mode 100644 src/pages/record/module/AliAsr.ts create mode 100644 src/pages/record/module/MyRecorder.ts diff --git a/backend/demo/index.html b/backend/demo/index.html new file mode 100644 index 0000000..c786ad9 --- /dev/null +++ b/backend/demo/index.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/backend/demo/index.js b/backend/demo/index.js new file mode 100644 index 0000000..f0c86db --- /dev/null +++ b/backend/demo/index.js @@ -0,0 +1,393 @@ +/****************** +《【教程】【ASR】实时语音识别、音频文件转文字-阿里云版》 +作者:高坚果 +时间:2020-7-22 22:37:09 + +通过阿里云语音识别(语音转文字)插件 /src/extensions/asr.aliyun.short.js,可实现实时语音识别、单个语音文件转文字。 + +只需要后端提供一个Token生成接口,就能进行语音识别,可直接参考或本地运行此NodeJs后端测试程序:/assets/demo-asr/NodeJsServer_asr.aliyun.short.js,配置好代码里的阿里云账号后,在目录内直接命令行执行`node NodeJsServer_asr.aliyun.short.js`即可运行提供本地测试接口。 + +目前暂未提供其他版本的语音识别插件,比如腾讯云、讯飞等,搭配使用Recorder的onProcess实时处理,可根据自己的业务需求选择对应厂家自行对接即可,如需定制开发请联系作者。 +******************/ + +var asr; + +/*************单个语音文件转文字例子,你也可以录完音后再一次性进行识别***************/ +//将录音文件进行语音识别,支持的录音格式取决于浏览器的支持,兼容性mp3最好,wav次之,其他格式不一定能够解码 +var fileToText=function(audioBlob,fileName){ + if(asr){ + Runtime.Log("上次asr未关闭",1); + return; + }; + Runtime.Log("开始识别文件:《"+fileName+"》,asrProcess中已限制最多识别前60*3-5*(3-1)=170秒 ..."); + $(".recAsrTxt").text(""); + $(".recAsrTime").html(""); + + var url=$(".asrTokenApi").val(); + var urlReq=null; + if(/^\s*\{.*\}\s*$/.test(url)){ + //这里是输入框里面填的json数据,直接success回调即可 + urlReq=function(url,args,success,fail){ + var data; try{ data=JSON.parse(url); }catch(e){}; + if(!data || !data.appkey || !data.token){ + fail("填写的json数据"+(!data?"解析失败":"中缺少appkey或token")); + }else{ + success({ appkey:data.appkey, token:data.token }); + } + } + }; + + var asr2=asr=Recorder.ASR_Aliyun_Short({ + tokenApi:url + ,apiArgs:{ + lang:$("[name=arsLang]:checked").val() + ,xxx:"其他请求参数" + } + ,apiRequest:urlReq //如果提供了token数据,可不发起api请求 + ,asrProcess:function(text,nextDuration,abortMsg){ + /***识别中间结果实回调,必须返回true才能继续识别,否则立即超时停止识别***/ + if(abortMsg){ + //语音识别中途出错,单个文件识别无需任何处理,会自动回调结果 + Runtime.Log("[asrProcess回调]被终止:"+abortMsg,1); + return false; + }; + + $(".recAsrTxt").text(text); + $(".recAsrTime").html("识别时长: "+formatTime(asr2.asrDuration()) + +" 已发送数据时长: "+formatTime(asr2.sendDuration())); + return nextDuration<=3*60*1000;//允许识别3分钟的识别时长(比音频时长小5*2秒) + } + ,log:function(msg,color){ + Runtime.Log(''+msg+'',color); + } + }); + Runtime.Log("语言:"+asr.set.apiArgs.lang); + //语音文件识别只需调用audioToText即可完成识别,简单快速 + asr.audioToText(audioBlob,function(text,abortMsg){ + asr=null; + if(abortMsg){ + Runtime.Log("发现识别中途被终止(一般无需特别处理):"+abortMsg,"#fb8"); + }; + Runtime.Log("文件识别最终结果:"+text, 2); + },function(errMsg){ + asr=null; + Runtime.Log("文件识别结束失败:"+errMsg, 1); + }); +}; +/*************单个语音文件转文字例子 END***************/ + + + +/*************实时语音识别例子*************************/ +/******界面交互处理、打开录音权限******/ +//使用长按录音的方式,可有效控制转换时长,避免不必要的资源浪费 +//长按按钮功能已经封装好了,直接调用 BindTouchButton 即可快速实现长按 +var bindTouchButton=function(){ + DemoFragment.BindTouchButton( + "recTouchBtn" + ,"按住进行录音+识别" + ,"松开结束" + ,{} + ,asrOnTouchStart + ,asrOnTouchEnd + ); +}; + +var rec; +/**打开录音,先得到录音权限**/ +function recOpenClick(){ + $(".recOpenBtn").hide(); + $(".recCloseBtn").show(); + var end=function(isOk){ + if(isOk){ + $(".asrStartBtns").show(); + $(".asrStopBtn").show(); + }; + }; + + rec=Recorder({ + type:"wav" + ,sampleRate:16000 + ,bitRate:16 + ,onProcess:function(buffers,powerLevel,bufferDuration,bufferSampleRate,newBufferIdx,asyncEnd){ + Runtime.Process.apply(null,arguments); + + //实时推入asr处理。asr.input随时都可以调用,就算asr并未start,会缓冲到asr.start完成然后将已input的数据进行识别 + if(asr){ + //buffers是从录音开头到现在的缓冲,因此需要提供 buffersOffset=newBufferIdx + asr.input(buffers, bufferSampleRate, newBufferIdx); + }; + } + }); + var t=setTimeout(function(){ + recAsrStatus("无法录音:权限请求被忽略(超时假装手动点击了确认对话框)",1); + rec=null; + end(false); + },8000); + + recAsrStatus("正在打开录音权限,请稍后..."); + rec.open(function(){//打开麦克风授权获得相关资源 + clearTimeout(t); + recAsrStatus("录音已打开,可以长按录音+识别了",2); + end(true); + },function(msg,isUserNotAllow){//用户拒绝未授权或不支持 + clearTimeout(t); + recAsrStatus((isUserNotAllow?"UserNotAllow,":"")+"无法录音:"+msg, 1); + rec=null; + end(false); + }); +}; +var recCloseClick=function(){ + $(".recOpenBtn").show(); + $(".recCloseBtn").hide(); + $(".asrStartBtns").hide(); + if(rec){ + Runtime.Log("已关闭录音"); + rec.close(); + rec=null; + }else{ + Runtime.Log("未打开录音",1); + } +}; + + +//免长按,这里就是调用的长按时的两个状态方法 功能是一样的 +var asrStartClick_NoTouch=function(){ + asrOnTouchStart(function(){}); +}; +var asrStopClick_NoTouch=function(){ + if(!asr){ + Runtime.Log("未开始识别",1); + return; + }; + asrOnTouchEnd(false,true); +}; + + + + +/******核心的长按录音识别******/ +/**长按开始录音**/ +var asrOnTouchStart=function(cancel){ + if(!rec){ + cancel("未打开录音"); + recAsrStatus("未打开录音",1); + return; + }; + rec.s_isStart=false; + if(asr){ + cancel("上次asr未关闭"); + recAsrStatus("上次asr未关闭",1); + return; + }; + $(".recAsrTxt").text(""); + $(".recAsrTime").html(""); + + var url=$(".asrTokenApi").val(); + var urlReq=null; + if(/^\s*\{.*\}\s*$/.test(url)){ + //这里是输入框里面填的json数据,直接success回调即可 + urlReq=function(url,args,success,fail){ + var data; try{ data=JSON.parse(url); }catch(e){}; + if(!data || !data.appkey || !data.token){ + fail("填写的json数据"+(!data?"解析失败":"中缺少appkey或token")); + }else{ + success({ appkey:data.appkey, token:data.token }); + } + } + }; + + //创建语音识别对象,每次识别都要新建,asr不能共用 + var asr2=asr=Recorder.ASR_Aliyun_Short({ + tokenApi:url + ,apiArgs:{ + lang:$("[name=arsLang]:checked").val() + ,xxx:"其他请求参数" + } + ,apiRequest:urlReq //如果提供了token数据,可不发起api请求 + ,asrProcess:function(text,nextDuration,abortMsg){ + /***实时识别结果,必须返回true才能继续识别,否则立即超时停止识别***/ + if(abortMsg){ + //语音识别中途出错 + recAsrStatus("[asrProcess回调]被终止:"+abortMsg,1); + cancel("语音识别出错");//立即结束录音,就算继续录音也不会识别 + return false; + }; + + $(".recAsrTxt").text(text); + $(".recAsrTime").html("识别时长: "+formatTime(asr2.asrDuration()) + +" 已发送数据时长: "+formatTime(asr2.sendDuration())); + return nextDuration<=2*60*1000;//允许识别2分钟的识别时长(比录音时长小5秒) + } + ,log:function(msg,color){ + Runtime.Log(''+msg+'',color); + } + }); + Runtime.Log("语言:"+asr.set.apiArgs.lang); + recAsrStatus("连接服务器中,请稍后..."); + //打开语音识别,建议先打开asr,成功后再开始录音 + asr.start(function(){//无需特殊处理start和stop的关系,只要调用了stop,会阻止未完成的start,不会执行回调 + //开始录音 + Runtime.Log("开始录音..."); + rec.start(); + rec.s_isStart=true; + + recAsrStatus("滴~~ 已开始语音识别,请讲话(asrProcess中已限制最多识别60*2-5*(2-1)=115秒)...",2); + },function(errMsg){ + recAsrStatus("语音识别开始失败,请重试:"+errMsg,1); + + cancel("语音识别开始失败"); + }); +}; + +/**松开停止录音**/ +var asrOnTouchEnd=function(isCancel,isUser){ + recAsrStatus(isCancel?"已取消":isUser?"已松开":"长按被取消",isUser?0:1); + + var asr2=asr;asr=null;//先干掉asr,防止重复stop + if(!asr2){ + Runtime.Log("未开始识别",1); + }else{ + //asr.stop 和 rec.stop 无需区分先后,同时执行就ok了 + asr2.stop(function(text,abortMsg){ + if(abortMsg){ + abortMsg="发现识别中途被终止(一般无需特别处理):"+abortMsg; + }; + recAsrStatus("语音识别完成"+(abortMsg?","+abortMsg:""),abortMsg?"#f60":2); + Runtime.Log("识别最终结果:"+text, 2); + },function(errMsg){ + recAsrStatus("语音识别"+(!isUser?"被取消":"结束失败")+":"+errMsg, 1); + }); + }; + + var rec2=rec; + if(rec2.s_isStart){ + rec2.s_isStart=false; + rec2.stop(function(blob,duration){ + Runtime.LogAudio(blob,duration,rec2); + },function(errMsg){ + Runtime.Log("录音失败:"+errMsg, 1); + }); + }; +}; + +/**更新状态**/ +var recAsrStatus=function(html,color){ + var elem=document.querySelector(".recAsrStatus"); + elem.style.color=color==1?"red":color==2?"#0b1":(color||null); + elem.innerHTML=html; + + Runtime.Log(html,color); +}; +/*************实时语音识别例子 END***************/ + + + +//破坏环境,测试错误是否被正确处理 +var killToken=function(){ + if(!asr){ + Runtime.Log("未开始语音识别",1); + return; + } + asr.set.apiRequest=function(url,args,success,fail){ + fail("不让获取Token"); + } + Runtime.Log("已设置ASR的apiRequest,下一分钟将无法获得Token"); +}; +var killWs=function(){ + if(!asr || !asr.wsCur){ + Runtime.Log("未开始语音识别",1); + return; + } + asr.wsCur.close(); + Runtime.Log("已强制关闭了ASR的WebSocket连接"); +}; + + + + + +//=====以下代码无关紧要,音频数据源和界面================== +//加载录音框架 +Runtime.Import([ + {url:RootFolder+"/src/recorder-core.js",check:function(){return !window.Recorder}} + ,{url:RootFolder+"/src/engine/wav.js",check:function(){return !Recorder.prototype.wav}} + ,{url:RootFolder+"/src/extensions/asr.aliyun.short.js",check:function(){return !Recorder.ASR_Aliyun_Short}} + + ,{url:RootFolder+"/assets/runtime-codes/fragment.touch_button.js",check:function(){return !window.DemoFragment||!DemoFragment.BindTouchButton}}//引入BindTouchButton +]); + + +//显示控制按钮 +Runtime.Ctrls([ + {html:'\ +
识别语言模型:\ + \ + \ + \ + \ + \ +
\ +
Token Api:\ + \ +
\ +
你可以下载Recorder仓库/assets/demo-asr内的nodejs服务器端脚本到电脑上,配置好代码里的阿里云账号,然后运行此服务器端脚本即可提供本地测试接口
\ +
如果无法访问此api地址,比如手机上,你可以根据服务器脚本中的提示在电脑上打http地址,手动复制或自行提供 {appkey:"...",token:"..."} ,先删掉上面输入框中的url再粘贴json进去即可使用
\ +
\ +
\ +'} + ,{html:'
\ +
\ + \ + \ + \ + \ + \ + \ + \ +
\ +\ +
\ + \ +
\ +\ +
\ +\ +
\ +
实时识别结果:
\ +
\ +'} + + ,{name:"破坏ASR配置,下一分钟得不到Token",click:"killToken"} + ,{name:"强制断开ASR的WebSocket连接",click:"killWs"} + ,{choiceFile:{ + multiple:false + ,name:"音频(已限制最多前3分钟内转成文字)" + ,mime:"audio/*" + ,process:function(fileName,arrayBuffer,filesCount,fileIdx,endCall){ + fileToText(new Blob([arrayBuffer]),fileName); + endCall(); + } + }} +]); + +bindTouchButton(); + +var formatTime=function(n){//格式化毫秒成 分:秒 + n=Math.round(n/1000); + var s=n%60; + var m=(n-s)/60; + return m+":"+("0"+s).substr(-2); +}; + + +function localTokenApi(useSet){ + var url="http://127.0.0.1:9527/token"; + if(useSet){ + url=localStorage["ASR_Aliyun_Short_TokenApi"]||url; + } + return url; +}; +$(".asrTokenApi").bind("change",function(){ + localStorage["ASR_Aliyun_Short_TokenApi"]=this.value==localTokenApi()?"":this.value; +}); diff --git a/backend/demo/recorder.mp3.min.js b/backend/demo/recorder.mp3.min.js new file mode 100644 index 0000000..eaa2708 --- /dev/null +++ b/backend/demo/recorder.mp3.min.js @@ -0,0 +1,6 @@ +/* +录音 +https://github.com/xiangyuecn/Recorder +src: recorder-core.js,engine/mp3.js,engine/mp3-engine.js +*/ +!function(e){var t="object"==typeof window&&!!window.document,a=t?window:Object;!function(e,y){"use strict";var A=function(){},f=function(e){return"number"==typeof e},B=function(e){return JSON.stringify(e)},W=function(e){return new _(e)},k=W.LM="2025-01-11 09:28",R="https://github.com/xiangyuecn/Recorder",T="Recorder",x="getUserMedia",N="srcSampleRate",V="sampleRate",i="bitRate",E="catch",t=e[T];if(t&&t.LM==k)return t.CLog(t.i18n.$T("K8zP::重复导入{1}",0,T),3);W.IsOpen=function(){var e=W.Stream;if(e){var t=j(e),a=t[0];if(a){var n=a.readyState;return"live"==n||n==a.LIVE}}return!1},W.BufferSize=4096,W.Destroy=function(){for(var e in Q(T+" Destroy"),F(),a)a[e]()};var a={};W.BindDestroy=function(e,t){a[e]=t},W.Support=function(){if(!y)return!1;var e=navigator.mediaDevices||{};return e[x]||(e=navigator)[x]||(e[x]=e.webkitGetUserMedia||e.mozGetUserMedia||e.msGetUserMedia),!!e[x]&&(W.Scope=e,!!W.GetContext())},W.GetContext=function(e){if(!y)return null;var t=window.AudioContext;if(t||(t=window.webkitAudioContext),!t)return null;var a=W.Ctx,n=0;return a||(a=W.Ctx=new t,n=1,W.NewCtxs=W.NewCtxs||[],W.BindDestroy("Ctx",function(){var e=W.Ctx;e&&e.close&&(s(e),W.Ctx=0);var t=W.NewCtxs;W.NewCtxs=[];for(var a=0;a"+m),3);for(var v=0,d=i;d"+v.length,Date.now()-u)),setTimeout(function(){u=Date.now(),h[b.type](v,function(e,t){s(e,t,l)},function(e){m(e)})})}else m($("xkKd::音频buffers被释放"))}else m($("xGuI::未加载{1}编码器,请尝试到{2}的src/engine内找到{1}的编码器并加载",0,b.type,T));else m($("Ltz3::未采集到录音"))}};var X=function(e,t){t.pos||(t.pos=[0],t.tracks={},t.bytes=[]);var a=t.tracks,n=[t.pos[0]],s=function(){t.pos[0]=n[0]},r=t.bytes.length,i=new Uint8Array(r+e.length);if(i.set(t.bytes),i.set(e,r),t.bytes=i,!t._ht){if(q(i,n),G(i,n),!Y(q(i,n),[24,83,128,103]))return;for(q(i,n);n[0]32 bit",3)),k<8e3||32!=A.bitDepth||A.channels<1||!/(\b|_)PCM\b/i.test(A.codec))return t.bytes=[],t.bad||Q("WebM Track Unexpected",3,t),-(t.bad=1);for(var R=[],x=0;n[0]=e.length)){var s=e[n],r=("0000000"+s.toString(2)).substr(-8),i=/^(0*1)(\d*)$/.exec(r);if(i){var o=i[1].length,_=[];if(!(n+o>e.length)){for(var l=0;le.length)return;for(var i=0;is.length)&&(e="{?}",Q("i18n["+n+"] no {"+t+"}: "+r,3)),a?"":e})):"en"==e?U.v_G(n,s,"zh"):U.v_G(n,s,"en")},$T:function(){return U.v_T.apply(null,arguments)},v_T:function(){for(var e,t=arguments,a="",n=[],s=0,r=T+".i18n.$T:",i=/^([\w\-]*):/,o=0;oc.length){var a=new Int8Array(c.length+Math.max(5e5,t));a.set(c.subarray(0,u)),c=a}c.set(e,u),u+=t}if(hr.memory.length){var a=new Int8Array(r.memory.length+Math.max(5e5,t));a.set(r.memory.subarray(0,r.mOffset)),r.memory=a}r.memory.set(e,r.mOffset),r.mOffset+=t};switch(t.action){case"stop":if(!r.isCp)try{r.encObj.flush()}catch(e){console.error(e)}r.encObj=null,delete a[t.id];break;case"encode":if(r.isCp)break;r.pcmSize+=t.pcm.length;try{var o=r.encObj.encodeBuffer(t.pcm)}catch(e){r.err=e,console.error(e)}o&&0=c.byteLength?(o-=c.byteLength,l.push(c),e.splice(f,1),f--):(e[f]=c.slice(o),_=c,o=0)}var u=this.rm(e,t);if(!u){_&&(e[0]=_);for(var f=0;f "+n.duration+"ms",2>=1;0!=e--;)s[r++]=i>a[n++]?0:1,s[r++]=i>a[n++]?0:1}function y(e,t,a,n,s,r){var i=(e>>=1)%2;for(e>>=1;0!=e--;){var o,_,l,f,c,u,h,b;o=a[n++]*t,_=a[n++]*t,c=0|o,l=a[n++]*t,u=0|_,f=a[n++]*t,h=0|l,o+=w.adj43[c],b=0|f,_+=w.adj43[u],s[r++]=0|o,l+=w.adj43[h],s[r++]=0|_,f+=w.adj43[b],s[r++]=0|l,s[r++]=0|f}0!=i&&(o=a[n++]*t,_=a[n++]*t,c=0|o,u=0|_,o+=w.adj43[c],_+=w.adj43[u],s[r++]=0|o,s[r++]=0|_)}var o=[1,2,5,7,7,10,10,13,13,13,13,13,13,13,13];function d(e,t,a,n){var s=function(e,t,a){var n=0,s=0;do{var r=e[t++],i=e[t++];n>=16)&&(o=r,n++),s.bits+=o,n}(e,t,a,o[s-1],n);case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13:case 14:case 15:return function(e,t,a,n,s){var r=0,i=0,o=0,_=k.ht[n].xlen,l=k.ht[n].hlen,f=k.ht[n+1].hlen,c=k.ht[n+2].hlen;do{var u=e[t+0]*_+e[t+1];t+=2,r+=l[u],i+=f[u],o+=c[u]}while(t=s);r++);for(i=r-8;i<24&&!(k.ht[i].linmax>=s);i++);return function(e,t,a,n,s,r){var i,o=65536*k.ht[n].xlen+k.ht[s].xlen,_=0;do{var l=e[t++],f=e[t++];0!=l&&(14>=16)&&(_=i,n=s),r.bits+=_,n}(e,t,a,i,r,n)}}function h(e,t,a,n,s,r,i,o){for(var _=t.big_values,l=2;l>1<<1);for(null!=a&&(a.sfb_count1=0);1t.big_values&&(r=t.big_values),i=t.big_values;else if(t.block_type==Ae.NORM_TYPE){if(r=t.region0_count=e.bv_scf[s-2],i=t.region1_count=e.bv_scf[s-1],i=e.scalefac_band.l[r+i+2],r=e.scalefac_band.l[r+1],ir?T.LARGE_BITS:(function(e,t,a,n,s){var r,i,o,_=0,l=0,f=0,c=0,u=t,h=0,b=u,p=0,m=e,v=0;for(o=null!=s&&n.global_gain==s.global_gain,i=n.block_type==Ae.SHORT_TYPE?38:21,r=0;r<=i;r++){var d=-1;if((o||n.block_type==Ae.NORM_TYPE)&&(d=n.global_gain-(n.scalefac[r]+(0!=n.preflag?w.pretab[r]:0)<n.max_nonzero_coeff&&(g=n.max_nonzero_coeff-_+1,Se.fill(t,n.max_nonzero_coeff,576,0),(S=g)<0&&(S=0),r=i+1),0==l&&0==f&&(b=u,p=h,m=e,v=c),null!=s&&0=s.sfb_count1&&0=s.step[r]?(0!=l&&(y(l,a,m,v,b,p),l=0,b=u,p=h,m=e,v=c),f+=S):(0!=f&&(M(f,a,m,v,b,p),f=0,b=u,p=h,m=e,v=c),l+=S),S<=0){0!=f&&me(),0!=l&&me();break}}r<=i&&(h+=n.width[r],c+=n.width[r],_+=n.width[r])}0!=l&&(y(l,a,m,v,b,p),l=0),0!=f&&me()}(t,s,w.IPOW20(a.global_gain),a,n),0!=(2&e.substep_shaping)&&me(),this.noquant_count_bits(e,a,n))},this.best_huffman_divide=function(e,t){var a=new B,n=t.l3_enc,s=ve(23),r=ve(23),i=ve(23),o=ve(23);if(t.block_type!=Ae.SHORT_TYPE||1!=e.mode_gr){a.assign(t),t.block_type==Ae.NORM_TYPE&&(function(e,t,a,n,s,r,i){for(var o=t.big_values,_=0;_<=22;_++)n[_]=T.LARGE_BITS;for(var _=0;_<16;_++){var l=e.scalefac_band.l[_+1];if(o<=l)break;var f=0,c=new v(f),u=d(a,0,l,c);f=c.bits;for(var h=0;h<8;h++){var b=e.scalefac_band.l[_+h+2];if(o<=b)break;var p=f;c=new v(p);var m=d(a,l,b,c);p=c.bits,n[_+h]>p&&(n[_+h]=p,s[_+h]=_,r[_+h]=u,i[_+h]=m)}}}(e,t,n,s,r,i,o),h(e,a,t,n,s,r,i,o));var _=a.big_values;if(!(0==_||1<(n[_-2]|n[_-1])||576<(_=t.count1+2))){a.assign(t),a.count1=_;for(var l=0,f=0;_>a.big_values;_-=4){var c=2*(2*(2*n[_-4]+n[_-3])+n[_-2])+n[_-1];l+=k.t32l[c],f+=k.t33l[c]}if(a.big_values=_,a.count1table_select=0,fa.part2_3_length&&t.assign(a)}}}};var u=[1,1,1,1,8,2,2,2,4,4,4,8,8,8,16,16],b=[1,2,4,8,1,2,4,8,2,4,8,2,4,8,4,8],p=[0,0,0,0,3,1,1,1,2,2,2,3,3,3,4,4],m=[0,1,2,3,0,1,2,3,1,2,3,1,2,3,2,3];A.slen1_tab=p,A.slen2_tab=m,this.best_scalefac_store=function(e,t,a,n){var s,r,i,o,_=n.tt[t][a],l=0;for(s=i=0;s<_.sfbmax;s++){var f=_.width[s];for(i+=f,o=-f;o<0&&0==_.l3_enc[o+i];o++);0==o&&(_.scalefac[s]=l=-2)}if(0==_.scalefac_scale&&0==_.preflag){var c=0;for(s=0;s<_.sfbmax;s++)0<_.scalefac[s]&&(c|=_.scalefac[s]);if(0==(1&c)&&0!=c){for(s=0;s<_.sfbmax;s++)0<_.scalefac[s]&&(_.scalefac[s]>>=1);_.scalefac_scale=l=1}}if(0==_.preflag&&_.block_type!=Ae.SHORT_TYPE&&2==e.mode_gr){for(s=11;sf&&(n.part2_length=f,n.scalefac_compress=r)}}(a,n),l=0),s=0;s<_.sfbmax;s++)-2==_.scalefac[s]&&(_.scalefac[s]=0);0!=l&&(2==e.mode_gr?this.scale_bitcount(_):this.scale_bitcount_lsf(e,_))};var _=[0,18,36,54,54,36,54,72,54,72,90,72,90,108,108,126],l=[0,18,36,54,51,35,53,71,52,70,88,69,87,105,104,122],f=[0,10,20,30,33,21,31,41,32,42,52,43,53,63,64,74];this.scale_bitcount=function(e){var t,a,n,s=0,r=0,i=e.scalefac;if(e.block_type==Ae.SHORT_TYPE)n=_,0!=e.mixed_block_flag&&(n=l);else if(n=f,0==e.preflag){for(a=11;an[t]&&(e.part2_length=n[t],e.scalefac_compress=t);return e.part2_length==T.LARGE_BITS};var g=[[15,15,7,7],[15,15,7,0],[7,3,0,0],[15,31,31,0],[7,7,7,0],[3,3,0,0]];this.scale_bitcount_lsf=function(e,t){var a,n,s,r,i,o,_,l,f=ve(4),c=t.scalefac;for(a=0!=t.preflag?2:0,_=0;_<4;_++)f[_]=0;if(t.block_type==Ae.SHORT_TYPE){n=1;var u=w.nr_of_sfb_block[a][n];for(s=l=0;s<4;s++)for(r=u[s]/3,_=0;_f[s]&&(f[s]=c[3*l+i])}else{n=0;var u=w.nr_of_sfb_block[a][n];for(s=l=0;s<4;s++)for(r=u[s],_=0;_f[s]&&(f[s]=c[l])}for(o=!1,s=0;s<4;s++)f[s]>g[a][s]&&(o=!0);if(!o){var h,b,p,m;for(t.sfb_partition_table=w.nr_of_sfb_block[a][n],s=0;s<4;s++)t.slen[s]=S[f[s]];switch(h=t.slen[0],b=t.slen[1],p=t.slen[2],m=t.slen[3],a){case 0:t.scalefac_compress=(5*h+b<<4)+(p<<2)+m;break;case 1:t.scalefac_compress=400+(5*h+b<<2)+p;break;case 2:t.scalefac_compress=500+3*h+b}}if(!o)for(t.part2_length=0,s=0;s<4;s++)t.part2_length+=t.slen[s]*t.sfb_partition_table[s];return o};var S=[0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4];this.huffman_init=function(e){for(var t=2;t<=576;t+=2){for(var a,n=0;e.scalefac_band.l[++n]t;)a--;for(a<0&&(a=s[n][0]),e.bv_scf[t-2]=a,a=s[n][1];e.scalefac_band.l[a+e.bv_scf[t-2]+2]>t;)a--;a<0&&(a=s[n][1]),e.bv_scf[t-1]=a}}}function O(){}function y(){this.setModules=function(e,t,a){};var o=[0,49345,49537,320,49921,960,640,49729,50689,1728,1920,51009,1280,50625,50305,1088,52225,3264,3456,52545,3840,53185,52865,3648,2560,51905,52097,2880,51457,2496,2176,51265,55297,6336,6528,55617,6912,56257,55937,6720,7680,57025,57217,8e3,56577,7616,7296,56385,5120,54465,54657,5440,55041,6080,5760,54849,53761,4800,4992,54081,4352,53697,53377,4160,61441,12480,12672,61761,13056,62401,62081,12864,13824,63169,63361,14144,62721,13760,13440,62529,15360,64705,64897,15680,65281,16320,16e3,65089,64001,15040,15232,64321,14592,63937,63617,14400,10240,59585,59777,10560,60161,11200,10880,59969,60929,11968,12160,61249,11520,60865,60545,11328,58369,9408,9600,58689,9984,59329,59009,9792,8704,58049,58241,9024,57601,8640,8320,57409,40961,24768,24960,41281,25344,41921,41601,25152,26112,42689,42881,26432,42241,26048,25728,42049,27648,44225,44417,27968,44801,28608,28288,44609,43521,27328,27520,43841,26880,43457,43137,26688,30720,47297,47489,31040,47873,31680,31360,47681,48641,32448,32640,48961,32e3,48577,48257,31808,46081,29888,30080,46401,30464,47041,46721,30272,29184,45761,45953,29504,45313,29120,28800,45121,20480,37057,37249,20800,37633,21440,21120,37441,38401,22208,22400,38721,21760,38337,38017,21568,39937,23744,23936,40257,24320,40897,40577,24128,23040,39617,39809,23360,39169,22976,22656,38977,34817,18624,18816,35137,19200,35777,35457,19008,19968,36545,36737,20288,36097,19904,19584,35905,17408,33985,34177,17728,34561,18368,18048,34369,33281,17088,17280,33601,16640,33217,32897,16448];this.updateMusicCRC=function(e,t,a,n){for(var s=0;s>8^o[255&(i^r)]);var r,i}}function N(){var i=this,r=null,o=null;this.setModules=function(e,t,a,n){r=a,o=n};var _=null,l=0,f=0,c=0;function v(e,t,a){for(;0>a<>3]|=t>>a<<8-(7&n)-s,n+=s}e.header[e.h_ptr].ptr=n}function m(e,t){var a,n=k.ht[t.count1table_select+32],s=0,r=t.big_values,i=t.big_values;for(a=(t.count1-t.big_values)/4;0t.big_values&&(a=t.big_values);var n=b(e,t.table_select[0],0,a,t);return n+=b(e,t.table_select[1],a,t.big_values,t)}function g(e,t){var a,n,s,r;a=t.big_values;var i=t.region0_count+1;return s=e.scalefac_band.l[i],i+=t.region1_count+1,r=e.scalefac_band.l[i],aMath.abs(t)?Math.abs(e-t)<=1e-6*Math.abs(e):Math.abs(e-t)<=1e-6*Math.abs(t)},N.NEQ=function(e,t){return!N.EQ(e,t)};var k={};function R(e){this.bits=e}function x(){this.over_noise=0,this.tot_noise=0,this.max_noise=0,this.over_count=0,this.over_SSD=0,this.bits=0}function r(e,t,a,n){this.l=ve(1+Ae.SBMAX_l),this.s=ve(1+Ae.SBMAX_s),this.psfb21=ve(1+Ae.PSFB21),this.psfb12=ve(1+Ae.PSFB12);var s=this.l,r=this.s;4==arguments.length&&(this.arrL=e,this.arrS=t,this.arr21=a,this.arr12=n,I.arraycopy(this.arrL,0,s,0,Math.min(this.arrL.length,this.l.length)),I.arraycopy(this.arrS,0,r,0,Math.min(this.arrS.length,this.s.length)),I.arraycopy(this.arr21,0,this.psfb21,0,Math.min(this.arr21.length,this.psfb21.length)),I.arraycopy(this.arr12,0,this.psfb12,0,Math.min(this.arr12.length,this.psfb12.length)))}function T(){var l=null,b=null,n=null;this.setModules=function(e,t,a){l=e,b=t,n=a},this.IPOW20=function(e){return h[e]};var B=2.220446049250313e-16,e=T.IXMAX_VAL,f=e+2,c=T.Q_MAX,u=T.Q_MAX2,s=100;this.nr_of_sfb_block=[[[6,5,5,5],[9,9,9,9],[6,9,9,9]],[[6,5,7,3],[9,9,12,6],[6,9,12,6]],[[11,10,0,0],[18,18,0,0],[15,18,0,0]],[[7,7,7,0],[12,12,12,0],[6,15,12,0]],[[6,6,6,3],[12,9,9,6],[6,12,9,6]],[[8,8,5,0],[15,12,9,0],[6,18,9,0]]];var M=[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0];this.pretab=M,this.sfBandIndex=[new r([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,24,32,42,56,74,100,132,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576],[0,4,8,12,18,26,36,48,62,80,104,136,180,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576],[0,4,8,12,16,22,30,40,52,66,84,106,136,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576],[0,4,8,12,16,22,28,38,50,64,80,100,126,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576],[0,4,8,12,16,22,30,42,58,78,104,138,180,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576],[0,4,8,12,18,26,36,48,62,80,104,134,174,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]),new r([0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576],[0,8,16,24,36,52,72,96,124,160,162,164,166,192],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0])];var y=de(c+u+1),h=de(c),p=de(f),m=de(f);function v(e,t){var a=n.ATHformula(t,e);return a-=s,a=Math.pow(10,a/10+e.ATHlower)}function A(e){this.s=e}this.adj43=m,this.iteration_init=function(e){var t,a=e.internal_flags,n=a.l3_side;if(0==a.iteration_init_init){for(a.iteration_init_init=1,n.main_data_begin=0,function(e){for(var t=e.internal_flags.ATH.l,a=e.internal_flags.ATH.psfb21,n=e.internal_flags.ATH.s,s=e.internal_flags.ATH.psfb12,r=e.internal_flags,i=e.out_samplerate,o=0;o>2&63)&&(t-=64),s=Math.pow(10,t/4/10),32<=(t=e.exp_nspsytune>>8&63)&&(t-=64),r=Math.pow(10,t/4/10),32<=(t=e.exp_nspsytune>>14&63)&&(t-=64),i=Math.pow(10,t/4/10),32<=(t=e.exp_nspsytune>>20&63)&&(t-=64),o=i*Math.pow(10,t/4/10),t=0;t3*n/4&&(f[o]=3*n/4),f[o]<0&&(f[o]=0),f[o]+a[o]>j.MAX_BITS_PER_CHANNEL&&(f[o]=Math.max(0,j.MAX_BITS_PER_CHANNEL-a[o])),i+=f[o];if(u>1,y=0;k=f[o]*f[o],y+=k,M+=k>1;w=g/v,M=B;do{var k,R;k=f[o]*f[o],y+=k,M+=kn[r-3+1]&&(n[r-3+1]+=(n[r-3]-n[r-3+1])*i.decay),n[r-3+1]>n[r-3+2]&&(n[r-3+2]+=(n[r-3+1]-n[r-3+2])*i.decay))}return _},this.calc_noise_core=function(e,t,a,n){var s=0,r=t.s,i=e.l3_enc;if(r>e.count1)for(;0!=a--;)_=e.xr[r],r++,s+=_*_,_=e.xr[r],r++,s+=_*_;else if(r>e.big_values){var o=de(2);for(o[0]=0,o[1]=n;0!=a--;)_=Math.abs(e.xr[r])-o[i[r]],r++,s+=_*_,_=Math.abs(e.xr[r])-o[i[r]],r++,s+=_*_}else for(;0!=a--;){var _;_=Math.abs(e.xr[r])-p[i[r]]*n,r++,s+=_*_,_=Math.abs(e.xr[r])-p[i[r]]*n,r++,s+=_*_}return t.s=r,s},this.calc_noise=function(e,t,a,n,s){var r,i,o=0,_=0,l=0,f=0,c=0,u=-20,h=0,b=e.scalefac,p=0;for(n.over_SSD=0,r=0;r>1,h+e.width[r]>e.max_nonzero_coeff&&(g=e.max_nonzero_coeff-h+1,i=0>1:0);var w=new A(h);d=this.calc_noise_core(e,w,i,S),h=w.s,null!=s&&(s.step[r]=v,s.noise[r]=d),d=a[o++]=d/t[_++],d=V.FAST_LOG10(Math.max(d,1e-20)),null!=s&&(s.noise_log[r]=d)}null!=s&&(s.global_gain=e.global_gain),c+=d,0a.max_noise-.2&&a.tot_noisea.max_noise-.2&&a.tot_noisea.max_noise-.1&&a.tot_noise+a.over_noisea.max_noise-.15&&a.tot_noise+a.over_noise+a.over_noiset.xrpow_max&&(t.xrpow_max=n[f+c]);if(2==i.noise_shaping_amp)return}}}(e,t,a,n);var i=o(t);return!(i||(i=2==r.mode_gr?S.scale_bitcount(t):S.scale_bitcount_lsf(r,t))&&(1e.xrpow_max&&(e.xrpow_max=t[a+i])}e.scalefac[n]=r>>1}e.preflag=0,e.scalefac_scale=1}(t,n),i=!1):t.block_type==Ae.SHORT_TYPE&&0>t.scalefac_scale))s[n]=f,_+=3*l;else{s[n]=0;var c=210+(f<t.xrpow_max&&(t.xrpow_max=a[_+u]);_+=l*(3-r-1)}}var h=g.IPOW20(202);_+=t.width[n]*(r+1);for(var u=-t.width[n];u<0;u++)a[_+u]*=h,a[_+u]>t.xrpow_max&&(t.xrpow_max=a[_+u])}}return!1}(r,t,n)||o(t))),i||(i=2==r.mode_gr?S.scale_bitcount(t):S.scale_bitcount_lsf(r,t)),i))}this.setModules=function(e,t,a,n){r=t,this.rv=t,g=a,this.qupvt=a,S=n,s.setModules(g,S)},this.init_xrpow=function(e,t,a){var n=0,s=0|t.max_nonzero_coeff;if(t.xrpow_max=0,Se.fill(a,s,576,0),1e-20<(n=function(e,t,a,n){for(var s=n=0;s<=a;++s){var r=Math.abs(e.xr[s]);n+=r,t[s]=Math.sqrt(r*Math.sqrt(r)),t[s]>e.xrpow_max&&(e.xrpow_max=t[s])}return n}(t,a,s,n))){var r=0;0!=(2&e.substep_shaping)&&(r=1);for(var i=0;id&&o.global_gain<=v;)o.global_gain++;if(o.global_gain>v)break;if(0==f.over_count){for(;(o.part2_3_length=S.count_bits(i,n,o,c))>u&&o.global_gain<=v;)o.global_gain++;if(o.global_gain>v)break}if(g.calc_noise(o,a,l,m,c),m.bits=o.part2_3_length,0!=(M(t.block_type!=Ae.SHORT_TYPE?e.quant_comp:e.quant_comp_short,f,m)?1:0))u=t.part2_3_length,f=m,t.assign(o),b=0,I.arraycopy(n,0,_,0,576);else if(0==i.full_outer_loop){if(++b>p&&0==f.over_count)break;i.noise_shaping_amp,i.noise_shaping_amp}}while(o.global_gain+o.scalefac_scale<255);3==i.noise_shaping_amp?me():h=!0}return e.VBR==Me.vbr_rh||e.VBR==Me.vbr_mtrh?I.arraycopy(_,0,n,0,576):0!=(1&i.substep_shaping)&&me(),f.over_count},this.iteration_finish_one=function(e,t,a){var n=e.l3_side,s=n.tt[t][a];S.best_scalefac_store(e,t,a,n),1==e.use_best_huffman&&S.best_huffman_divide(e,s),r.ResvAdjust(e,s)}}function L(){this.thm=new i,this.en=new i}function Ae(){var k=Ae.MPG_MD_MS_LR,R=null,x=this.psy=null,B=null;this.setModules=function(e,t,a,n){R=e,this.psy=t,x=t,B=n};var T=new function(){var u=[-.1482523854003001,32.308141959636465,296.40344946382766,883.1344870032432,11113.947376231741,1057.2713659324597,305.7402417275812,30.825928907280012,3.8533188138216365,59.42900443849514,709.5899960123345,5281.91112291017,-5829.66483675846,-817.6293103748613,-76.91656988279972,-4.594269939176596,.9063471690191471,.1960342806591213,-.15466694054279598,34.324387823855965,301.8067566458425,817.599602898885,11573.795901679885,1181.2520595540152,321.59731579894424,31.232021761053772,3.7107095756221318,53.650946155329365,684.167428119626,5224.56624370173,-6366.391851890084,-908.9766368219582,-89.83068876699639,-5.411397422890401,.8206787908286602,.3901806440322567,-.16070888947830023,36.147034243915876,304.11815768187864,732.7429163887613,11989.60988270091,1300.012278487897,335.28490093152146,31.48816102859945,3.373875931311736,47.232241542899175,652.7371796173471,5132.414255594984,-6909.087078780055,-1001.9990371107289,-103.62185754286375,-6.104916304710272,.7416505462720353,.5805693545089249,-.16636367662261495,37.751650073343995,303.01103387567713,627.9747488785183,12358.763425278165,1412.2779918482834,346.7496836825721,31.598286663170416,3.1598635433980946,40.57878626349686,616.1671130880391,5007.833007176154,-7454.040671756168,-1095.7960341867115,-118.24411666465777,-6.818469345853504,.6681786379192989,.7653668647301797,-.1716176790982088,39.11551877123304,298.3413246578966,503.5259106886539,12679.589408408976,1516.5821921214542,355.9850766329023,31.395241710249053,2.9164211881972335,33.79716964664243,574.8943997801362,4853.234992253242,-7997.57021486075,-1189.7624067269965,-133.6444792601766,-7.7202770609839915,.5993769336819237,.9427934736519954,-.17645823955292173,40.21879108166477,289.9982036694474,359.3226160751053,12950.259102786438,1612.1013903507662,362.85067106591504,31.045922092242872,2.822222032597987,26.988862316190684,529.8996541764288,4671.371946949588,-8535.899136645805,-1282.5898586244496,-149.58553632943463,-8.643494270763135,.5345111359507916,1.111140466039205,-.36174739330527045,41.04429910497807,277.5463268268618,195.6386023135583,13169.43812144731,1697.6433561479398,367.40983966190305,30.557037410382826,2.531473372857427,20.070154905927314,481.50208566532336,4464.970341588308,-9065.36882077239,-1373.62841526722,-166.1660487028118,-9.58289321133207,.4729647758913199,1.268786568327291,-.36970682634889585,41.393213350082036,261.2935935556502,12.935476055240873,13336.131683328815,1772.508612059496,369.76534388639965,29.751323653701338,2.4023193045459172,13.304795348228817,430.5615775526625,4237.0568611071185,-9581.931701634761,-1461.6913552409758,-183.12733958476446,-10.718010163869403,.41421356237309503,1.414213562373095,-.37677560326535325,41.619486213528496,241.05423794991074,-187.94665032361226,13450.063605744153,1836.153896465782,369.4908799925761,29.001847876923147,2.0714759319987186,6.779591200894186,377.7767837205709,3990.386575512536,-10081.709459700915,-1545.947424837898,-200.3762958015653,-11.864482073055006,.3578057213145241,1.546020906725474,-.3829366947518991,41.1516456456653,216.47684307105183,-406.1569483347166,13511.136535077321,1887.8076599260432,367.3025214564151,28.136213436723654,1.913880671464418,.3829366947518991,323.85365704338597,3728.1472257487526,-10561.233882199509,-1625.2025997821418,-217.62525175416,-13.015432208941645,.3033466836073424,1.66293922460509,-.5822628872992417,40.35639251440489,188.20071124269245,-640.2706748618148,13519.21490106562,1927.6022433578062,362.8197642637487,26.968821921868447,1.7463817695935329,-5.62650678237171,269.3016715297017,3453.386536448852,-11016.145278780888,-1698.6569643425091,-234.7658734267683,-14.16351421663124,.2504869601913055,1.76384252869671,-.5887180101749253,39.23429103868072,155.76096234403798,-889.2492977967378,13475.470561874661,1955.0535223723712,356.4450994756727,25.894952980042156,1.5695032905781554,-11.181939564328772,214.80884394039484,3169.1640829158237,-11443.321309975563,-1765.1588461316153,-251.68908574481912,-15.49755935939164,.198912367379658,1.847759065022573,-.7912582233652842,37.39369355329111,119.699486012458,-1151.0956593239027,13380.446257078214,1970.3952110853447,348.01959814116185,24.731487364283044,1.3850130831637748,-16.421408865300393,161.05030052864092,2878.3322807850063,-11838.991423510031,-1823.985884688674,-268.2854986386903,-16.81724543849939,.1483359875383474,1.913880671464418,-.7960642926861912,35.2322109610459,80.01928065061526,-1424.0212633405113,13235.794061869668,1973.804052543835,337.9908651258184,23.289159354463873,1.3934255946442087,-21.099669467133474,108.48348407242611,2583.700758091299,-12199.726194855148,-1874.2780658979746,-284.2467154529415,-18.11369784385905,.09849140335716425,1.961570560806461,-.998795456205172,32.56307803611191,36.958364584370486,-1706.075448829146,13043.287458812016,1965.3831106103316,326.43182772364605,22.175018750622293,1.198638339011324,-25.371248002043963,57.53505923036915,2288.41886619975,-12522.674544337233,-1914.8400385312243,-299.26241273417224,-19.37805630698734,.04912684976946725,1.990369453344394,.035780907*V.SQRT2*.5/2384e-9,.017876148*V.SQRT2*.5/2384e-9,.003134727*V.SQRT2*.5/2384e-9,.002457142*V.SQRT2*.5/2384e-9,971317e-9*V.SQRT2*.5/2384e-9,218868e-9*V.SQRT2*.5/2384e-9,101566e-9*V.SQRT2*.5/2384e-9,13828e-9*V.SQRT2*.5/2384e-9,12804.797818791945,1945.5515939597317,313.4244966442953,49591e-9/2384e-9,1995.1556208053692,21458e-9/2384e-9,-69618e-9/2384e-9],A=[[2.382191739347913e-13,6.423305872147834e-13,9.400849094049688e-13,1.122435026096556e-12,1.183840321267481e-12,1.122435026096556e-12,9.40084909404969e-13,6.423305872147839e-13,2.382191739347918e-13,5.456116108943412e-12,4.878985199565852e-12,4.240448995017367e-12,3.559909094758252e-12,2.858043359288075e-12,2.156177623817898e-12,1.475637723558783e-12,8.371015190102974e-13,2.599706096327376e-13,-5.456116108943412e-12,-4.878985199565852e-12,-4.240448995017367e-12,-3.559909094758252e-12,-2.858043359288076e-12,-2.156177623817898e-12,-1.475637723558783e-12,-8.371015190102975e-13,-2.599706096327376e-13,-2.382191739347923e-13,-6.423305872147843e-13,-9.400849094049696e-13,-1.122435026096556e-12,-1.183840321267481e-12,-1.122435026096556e-12,-9.400849094049694e-13,-6.42330587214784e-13,-2.382191739347918e-13],[2.382191739347913e-13,6.423305872147834e-13,9.400849094049688e-13,1.122435026096556e-12,1.183840321267481e-12,1.122435026096556e-12,9.400849094049688e-13,6.423305872147841e-13,2.382191739347918e-13,5.456116108943413e-12,4.878985199565852e-12,4.240448995017367e-12,3.559909094758253e-12,2.858043359288075e-12,2.156177623817898e-12,1.475637723558782e-12,8.371015190102975e-13,2.599706096327376e-13,-5.461314069809755e-12,-4.921085770524055e-12,-4.343405037091838e-12,-3.732668368707687e-12,-3.093523840190885e-12,-2.430835727329465e-12,-1.734679010007751e-12,-9.74825365660928e-13,-2.797435120168326e-13,0,0,0,0,0,0,-2.283748241799531e-13,-4.037858874020686e-13,-2.146547464825323e-13],[.1316524975873958,.414213562373095,.7673269879789602,1.091308501069271,1.303225372841206,1.56968557711749,1.920982126971166,2.414213562373094,3.171594802363212,4.510708503662055,7.595754112725146,22.90376554843115,.984807753012208,.6427876096865394,.3420201433256688,.9396926207859084,-.1736481776669303,-.7660444431189779,.8660254037844387,.5,-.5144957554275265,-.4717319685649723,-.3133774542039019,-.1819131996109812,-.09457419252642064,-.04096558288530405,-.01419856857247115,-.003699974673760037,.8574929257125442,.8817419973177052,.9496286491027329,.9833145924917901,.9955178160675857,.9991605581781475,.999899195244447,.9999931550702802],[0,0,0,0,0,0,2.283748241799531e-13,4.037858874020686e-13,2.146547464825323e-13,5.461314069809755e-12,4.921085770524055e-12,4.343405037091838e-12,3.732668368707687e-12,3.093523840190885e-12,2.430835727329466e-12,1.734679010007751e-12,9.74825365660928e-13,2.797435120168326e-13,-5.456116108943413e-12,-4.878985199565852e-12,-4.240448995017367e-12,-3.559909094758253e-12,-2.858043359288075e-12,-2.156177623817898e-12,-1.475637723558782e-12,-8.371015190102975e-13,-2.599706096327376e-13,-2.382191739347913e-13,-6.423305872147834e-13,-9.400849094049688e-13,-1.122435026096556e-12,-1.183840321267481e-12,-1.122435026096556e-12,-9.400849094049688e-13,-6.423305872147841e-13,-2.382191739347918e-13]],k=A[Ae.SHORT_TYPE],w=A[Ae.SHORT_TYPE],R=A[Ae.SHORT_TYPE],x=A[Ae.SHORT_TYPE],B=[0,1,16,17,8,9,24,25,4,5,20,21,12,13,28,29,2,3,18,19,10,11,26,27,6,7,22,23,14,15,30,31];function T(e,t,a){for(var n,s,r,i=10,o=t+238-14-286,_=-15;_<0;_++){var l,f,c;l=u[i+-10],f=e[o+-224]*l,c=e[t+224]*l,l=u[i+-9],f+=e[o+-160]*l,c+=e[t+160]*l,l=u[i+-8],f+=e[o+-96]*l,c+=e[t+96]*l,l=u[i+-7],f+=e[o+-32]*l,c+=e[t+32]*l,l=u[i+-6],f+=e[o+32]*l,c+=e[t+-32]*l,l=u[i+-5],f+=e[o+96]*l,c+=e[t+-96]*l,l=u[i+-4],f+=e[o+160]*l,c+=e[t+-160]*l,l=u[i+-3],f+=e[o+224]*l,c+=e[t+-224]*l,l=u[i+-2],f+=e[t+-256]*l,c-=e[o+256]*l,l=u[i+-1],f+=e[t+-192]*l,c-=e[o+192]*l,l=u[i+0],f+=e[t+-128]*l,c-=e[o+128]*l,l=u[i+1],f+=e[t+-64]*l,c-=e[o+64]*l,l=u[i+2],f+=e[t+0]*l,c-=e[o+0]*l,l=u[i+3],f+=e[t+64]*l,c-=e[o+-64]*l,l=u[i+4],f+=e[t+128]*l,c-=e[o+-128]*l,l=u[i+5],f+=e[t+192]*l,c-=e[o+-192]*l,f*=u[i+6],l=c-f,a[30+2*_]=c+f,a[31+2*_]=u[i+7]*l,i+=18,t--,o++}c=e[t+-16]*u[i+-10],f=e[t+-32]*u[i+-2],c+=(e[t+-48]-e[t+16])*u[i+-9],f+=e[t+-96]*u[i+-1],c+=(e[t+-80]+e[t+48])*u[i+-8],f+=e[t+-160]*u[i+0],c+=(e[t+-112]-e[t+80])*u[i+-7],f+=e[t+-224]*u[i+1],c+=(e[t+-144]+e[t+112])*u[i+-6],f-=e[t+32]*u[i+2],c+=(e[t+-176]-e[t+144])*u[i+-5],f-=e[t+96]*u[i+3],c+=(e[t+-208]+e[t+176])*u[i+-4],f-=e[t+160]*u[i+4],c+=(e[t+-240]-e[t+208])*u[i+-3],f-=e[t+224],n=f-c,s=f+c,c=a[14],f=a[15]-c,a[31]=s+c,a[30]=n+f,a[15]=n-f,a[14]=s-c,r=a[28]-a[0],a[0]+=a[28],a[28]=r*u[i+-36+7],r=a[29]-a[1],a[1]+=a[29],a[29]=r*u[i+-36+7],r=a[26]-a[2],a[2]+=a[26],a[26]=r*u[i+-72+7],r=a[27]-a[3],a[3]+=a[27],a[27]=r*u[i+-72+7],r=a[24]-a[4],a[4]+=a[24],a[24]=r*u[i+-108+7],r=a[25]-a[5],a[5]+=a[25],a[25]=r*u[i+-108+7],r=a[22]-a[6],a[6]+=a[22],a[22]=r*V.SQRT2,r=a[23]-a[7],a[7]+=a[23],a[23]=r*V.SQRT2-a[7],a[7]-=a[6],a[22]-=a[7],a[23]-=a[22],r=a[6],a[6]=a[31]-r,a[31]=a[31]+r,r=a[7],a[7]=a[30]-r,a[30]=a[30]+r,r=a[22],a[22]=a[15]-r,a[15]=a[15]+r,r=a[23],a[23]=a[14]-r,a[14]=a[14]+r,r=a[20]-a[8],a[8]+=a[20],a[20]=r*u[i+-180+7],r=a[21]-a[9],a[9]+=a[21],a[21]=r*u[i+-180+7],r=a[18]-a[10],a[10]+=a[18],a[18]=r*u[i+-216+7],r=a[19]-a[11],a[11]+=a[19],a[19]=r*u[i+-216+7],r=a[16]-a[12],a[12]+=a[16],a[16]=r*u[i+-252+7],r=a[17]-a[13],a[13]+=a[17],a[17]=r*u[i+-252+7],r=-a[20]+a[24],a[20]+=a[24],a[24]=r*u[i+-216+7],r=-a[21]+a[25],a[21]+=a[25],a[25]=r*u[i+-216+7],r=a[4]-a[8],a[4]+=a[8],a[8]=r*u[i+-216+7],r=a[5]-a[9],a[5]+=a[9],a[9]=r*u[i+-216+7],r=a[0]-a[12],a[0]+=a[12],a[12]=r*u[i+-72+7],r=a[1]-a[13],a[1]+=a[13],a[13]=r*u[i+-72+7],r=a[16]-a[28],a[16]+=a[28],a[28]=r*u[i+-72+7],r=-a[17]+a[29],a[17]+=a[29],a[29]=r*u[i+-72+7],r=V.SQRT2*(a[2]-a[10]),a[2]+=a[10],a[10]=r,r=V.SQRT2*(a[3]-a[11]),a[3]+=a[11],a[11]=r,r=V.SQRT2*(-a[18]+a[26]),a[18]+=a[26],a[26]=r-a[18],r=V.SQRT2*(-a[19]+a[27]),a[19]+=a[27],a[27]=r-a[19],r=a[2],a[19]-=a[3],a[3]-=r,a[2]=a[31]-r,a[31]+=r,r=a[3],a[11]-=a[19],a[18]-=r,a[3]=a[30]-r,a[30]+=r,r=a[18],a[27]-=a[11],a[19]-=r,a[18]=a[15]-r,a[15]+=r,r=a[19],a[10]-=r,a[19]=a[14]-r,a[14]+=r,r=a[10],a[11]-=r,a[10]=a[23]-r,a[23]+=r,r=a[11],a[26]-=r,a[11]=a[22]-r,a[22]+=r,r=a[26],a[27]-=r,a[26]=a[7]-r,a[7]+=r,r=a[27],a[27]=a[6]-r,a[6]+=r,r=V.SQRT2*(a[0]-a[4]),a[0]+=a[4],a[4]=r,r=V.SQRT2*(a[1]-a[5]),a[1]+=a[5],a[5]=r,r=V.SQRT2*(a[16]-a[20]),a[16]+=a[20],a[20]=r,r=V.SQRT2*(a[17]-a[21]),a[17]+=a[21],a[21]=r,r=-V.SQRT2*(a[8]-a[12]),a[8]+=a[12],a[12]=r-a[8],r=-V.SQRT2*(a[9]-a[13]),a[9]+=a[13],a[13]=r-a[9],r=-V.SQRT2*(a[25]-a[29]),a[25]+=a[29],a[29]=r-a[25],r=-V.SQRT2*(a[24]+a[28]),a[24]-=a[28],a[28]=r-a[24],r=a[24]-a[16],a[24]=r,r=a[20]-r,a[20]=r,r=a[28]-r,a[28]=r,r=a[25]-a[17],a[25]=r,r=a[21]-r,a[21]=r,r=a[29]-r,a[29]=r,r=a[17]-a[1],a[17]=r,r=a[9]-r,a[9]=r,r=a[25]-r,a[25]=r,r=a[5]-r,a[5]=r,r=a[21]-r,a[21]=r,r=a[13]-r,a[13]=r,r=a[29]-r,a[29]=r,r=a[1]-a[0],a[1]=r,r=a[16]-r,a[16]=r,r=a[17]-r,a[17]=r,r=a[8]-r,a[8]=r,r=a[9]-r,a[9]=r,r=a[24]-r,a[24]=r,r=a[25]-r,a[25]=r,r=a[4]-r,a[4]=r,r=a[5]-r,a[5]=r,r=a[20]-r,a[20]=r,r=a[21]-r,a[21]=r,r=a[12]-r,a[12]=r,r=a[13]-r,a[13]=r,r=a[28]-r,a[28]=r,r=a[29]-r,a[29]=r,r=a[0],a[0]+=a[31],a[31]-=r,r=a[1],a[1]+=a[30],a[30]-=r,r=a[16],a[16]+=a[15],a[15]-=r,r=a[17],a[17]+=a[14],a[14]-=r,r=a[8],a[8]+=a[23],a[23]-=r,r=a[9],a[9]+=a[22],a[22]-=r,r=a[24],a[24]+=a[7],a[7]-=r,r=a[25],a[25]+=a[6],a[6]-=r,r=a[4],a[4]+=a[27],a[27]-=r,r=a[5],a[5]+=a[26],a[26]-=r,r=a[20],a[20]+=a[11],a[11]-=r,r=a[21],a[21]+=a[10],a[10]-=r,r=a[12],a[12]+=a[19],a[19]-=r,r=a[13],a[13]+=a[18],a[18]-=r,r=a[28],a[28]+=a[3],a[3]-=r,r=a[29],a[29]+=a[2],a[2]-=r}function E(e,t){for(var a=0;a<3;a++){var n,s,r,i,o,_;i=e[t+6]*A[Ae.SHORT_TYPE][0]-e[t+15],n=e[t+0]*A[Ae.SHORT_TYPE][2]-e[t+9],s=i+n,r=i-n,i=e[t+15]*A[Ae.SHORT_TYPE][0]+e[t+6],n=e[t+9]*A[Ae.SHORT_TYPE][2]+e[t+0],o=i+n,_=-i+n,n=2.069978111953089e-11*(e[t+3]*A[Ae.SHORT_TYPE][1]-e[t+12]),i=2.069978111953089e-11*(e[t+12]*A[Ae.SHORT_TYPE][1]+e[t+3]),e[t+0]=1.90752519173728e-11*s+n,e[t+15]=1.90752519173728e-11*-o+i,r=.8660254037844387*r*1.907525191737281e-11,o=.5*o*1.907525191737281e-11+i,e[t+3]=r-o,e[t+6]=r+o,s=.5*s*1.907525191737281e-11-n,_=.8660254037844387*_*1.907525191737281e-11,e[t+9]=s+_,e[t+12]=s-_,t++}}function C(e,t,a){var n,s,r,i,o,_,l,f,c,u,h,b,p,m,v,d,g,S;r=a[17]-a[9],o=a[15]-a[11],_=a[14]-a[12],l=a[0]+a[8],f=a[1]+a[7],c=a[2]+a[6],u=a[3]+a[5],e[t+17]=l+c-u-(f-a[4]),s=(l+c-u)*w[19]+(f-a[4]),n=(r-o-_)*w[18],e[t+5]=n+s,e[t+6]=n-s,i=(a[16]-a[10])*w[18],f=f*w[19]+a[4],n=r*w[12]+i+o*w[13]+_*w[14],s=-l*w[16]+f-c*w[17]+u*w[15],e[t+1]=n+s,e[t+2]=n-s,n=r*w[13]-i-o*w[14]+_*w[12],s=-l*w[17]+f-c*w[15]+u*w[16],e[t+9]=n+s,e[t+10]=n-s,n=r*w[14]-i+o*w[12]-_*w[13],s=l*w[15]-f+c*w[16]-u*w[17],e[t+13]=n+s,e[t+14]=n-s,h=a[8]-a[0],p=a[6]-a[2],m=a[5]-a[3],v=a[17]+a[9],d=a[16]+a[10],g=a[15]+a[11],S=a[14]+a[12],e[t+0]=v+g+S+(d+a[13]),n=(v+g+S)*w[19]-(d+a[13]),s=(h-p+m)*w[18],e[t+11]=n+s,e[t+12]=n-s,b=(a[7]-a[1])*w[18],d=a[13]-d*w[19],n=v*w[15]-d+g*w[16]+S*w[17],s=h*w[14]+b+p*w[12]+m*w[13],e[t+3]=n+s,e[t+4]=n-s,n=-v*w[17]+d-g*w[15]-S*w[16],s=h*w[13]+b-p*w[14]-m*w[12],e[t+7]=n+s,e[t+8]=n-s,n=-v*w[16]+d-g*w[17]-S*w[15],s=h*w[12]-b+p*w[13]-m*w[14],e[t+15]=n+s,e[t+16]=n-s}this.mdct_sub48=function(e,t,a){for(var n=t,s=286,r=0;r=n?(e.ATH.adjust*=.075*n+.925,e.ATH.adjust=n?e.ATH.adjust=n:e.ATH.adjust>1,h=(u=(c=n)<<1)+c,n=u<<1,r=(s=t)+b;w=e[s+0]-e[s+c],S=e[s+0]+e[s+c],k=e[s+u]-e[s+h],y=e[s+u]+e[s+h],e[s+u]=S-y,e[s+0]=S+y,e[s+h]=w-k,e[s+c]=w+k,w=e[r+0]-e[r+c],S=e[r+0]+e[r+c],k=V.SQRT2*e[r+h],y=V.SQRT2*e[r+u],e[r+u]=S-y,e[r+0]=S+y,e[r+h]=w-k,e[r+c]=w+k,r+=n,(s+=n)H[h+3-2]?U/=H[h+3-2]:U=H[h+3-2]>10*U?H[h+3-2]/(10*U):0,N[h+3]=U}for(e.analysis&&me(),P=3==c?g.nsPsy.attackthre_s:g.nsPsy.attackthre,h=0;h<12;h++)0==j[h/3]&&N[h]>P&&(j[h/3]=h%3+1);for(h=1;h<4;h++)(O[h-1]>O[h]?O[h-1]/O[h]:O[h]/O[h-1])<1.7&&(j[h]=0,1==h&&(j[0]=0));for(0!=j[0]&&0!=g.nsPsy.lastAttacks[c]&&(j[0]=0),3!=g.nsPsy.lastAttacks[c]&&j[0]+j[1]+j[2]+j[3]==0||((V=0)!=j[1]&&0!=j[0]&&(j[1]=0),0!=j[2]&&0!=j[1]&&(j[2]=0),0!=j[3]&&0!=j[2]&&(j[3]=0)),c<2?R[c]=V:me(),_[c]=g.tot_ener[c],se(e,X,Y,S,1&c,w,1&c,n,c,t,a),he(g,X,M,D,F),be(g,D,F,B),v=0;v<3;v++){var K,Z;for(le(e,Y,y,A,c,v),oe(g,y,A,c,v),m=0;m=s&&(p=i*(l[t]-s)/(24-s)+r*(24-l[t])/(24-s)),c[t]=Math.pow(10,p/10),0=s&&(p=_*(l[t]-s)/(24-s)+o*(24-l[t])/(24-s)),c[t]=Math.pow(10,p/10),g=D.MAX_VALUE;for(var v=0;va.npart_l-1&&(a.s3ind[w][1]=a.npart_l-1);var M=576*a.mode_gr/u;if(a.ATH.decay=Math.pow(10,-1.2*M),a.ATH.adjust=.01,-(a.ATH.adjustLimit=1)!=e.ATHtype){var y=e.out_samplerate/Ae.BLKSIZE,A=0;for(t=d=0;t=a.lowpass2&&(n=Math.min(n,r)),a.lowpass1a.highpass1?me():o=1,_=a.lowpass2>a.lowpass1?1<(t=(i-a.lowpass1)/(a.lowpass2-a.lowpass1+1e-20))?0:t<=0?1:Math.cos(Math.PI/2*t):1,a.amp_filter[r]=o*_}}(e),n.samplerate_index=function(e,t){switch(e){case 44100:return t.version=1,0;case 48e3:return t.version=1;case 32e3:return t.version=1,2;case 22050:return t.version=0;case 24e3:return t.version=0,1;case 16e3:return t.version=0,2;case 11025:return t.version=0;case 12e3:return t.version=0,1;case 8e3:return t.version=0,2;default:return t.version=0,-1}}(e.out_samplerate,e),n.samplerate_index<0&&me(),e.VBR==Me.vbr_off?e.free_format?n.bitrate_index=0:(e.brate=function(e,t,a){a<16e3&&(t=2);for(var n=k.bitrate_table[t][1],s=2;s<=14;s++)0=f){var B=i-h;if(0==i&&(B=0),m=e,v=b[0],d=b[1],g=s,S=r,w=B,void 0,M=C.enc.lame_encode_mp3_frame(m,v,d,g,S,w),m.frameNum++,(o=M)<0)return o;for(r+=o,h+=o,u.mf_size-=e.framesize,u.mf_samples_to_encode-=e.framesize,l=0;li&&(n.ResvMax=i),(n.ResvMax<0||e.disable_reservoir)&&(n.ResvMax=0);var o=t.bits*n.mode_gr+Math.min(n.ResvSize,n.ResvMax);return ad&&(d=e.length,S=w(g=0|1.25*d+7200));var a=s.lame_encode_buffer(v,e,t,e.length,S,0,g);return new Int8Array(S.subarray(0,a))},this.flush=function(){var e=s.lame_encode_flush(v,S,0,g);return new Int8Array(S.subarray(0,e))}}}t(),e.lamejs=t}(("object"==typeof window&&window.document?window:Object).Recorder); \ No newline at end of file diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..0dcac50 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,14 @@ +{ + "name": "backend", + "version": "0.0.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "abearxiong (https://www.xiongxiao.me)", + "license": "MIT", + "packageManager": "pnpm@10.7.1", + "type": "module" +} diff --git a/backend/src/NodeJsServer_asr.aliyun.short.cjs b/backend/src/NodeJsServer_asr.aliyun.short.cjs new file mode 100644 index 0000000..ab033c8 --- /dev/null +++ b/backend/src/NodeJsServer_asr.aliyun.short.cjs @@ -0,0 +1,312 @@ +/******************************************* +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: 'LTAI5tDazeiB3pYYUwnMuLAt', //【必填】根据文档创建RAM用户,分配好权限,生成访问密钥 + Secret: '2UnGJO6GLZIVXS249B4wgi9uTKknLY', //【必填】 + + //请到阿里云智能语音交互控制台创建相应的语音识别项目,每个项目可以设置一种语言模型,要支持多种语言就创建多个项目,然后填写每个项目对应的Appkey到这里,前端调用本接口的时候传入lang参数来获取到对应的Appkey + Langs: { + 普通话: 'xGuvvqhseLDauN2r', //【必填】至少创建一个普通话语言模型的项目用于测试,填对应的Appkey + 粤语: '', + 英语: '', + 日语: '', + //...... 按需提供语言对应的项目Appkey + }, +}; + +global.Port = 9527; //http服务端口 +global.SSL = { + CertFile: '', //cert.pem 证书路径,不为空将开启https + KeyFile: '', //cert.key 密钥路径 +}; +const Config = global.Config; + +//如果提供了这个本地文件,就加载过来,可覆盖global下挂载的对象 +var fs = require('fs'); +var localFile = 'NodeJsServer_asr.aliyun.short__local.cjs'; +fs.existsSync(localFile) && require('./' + localFile); + +var GetLangKeys = function () { + var keys = []; + for (var k in Config.Langs) if (Config.Langs[k]) keys.push(k); + return keys; +}; + +/***************一句话识别Token生成***************/ +var GetAsrToken = async function (ctx, args) { + var lang = args.lang; //unsafe + var rtv = {}; + ctx.setValue(rtv); + var errTag = '[GetAsrToken]'; + + if (!Config.AccessKey || !Config.Secret) { + return ctx.error(errTag + '未配置AccessKey'); + } + console.log('Config', lang); + + //根据前端需要的语言获得appkey,一种语言模型对应一个项目 + var appkey = Config.Langs[lang]; + if (!appkey) { + var errMsg = 'lang[' + lang + ']未配置Appkey'; + if (!lang) errMsg = '请求需要提供lang参数'; + return ctx.error(errTag + errMsg + ',已配置的可用lang值' + JSON.stringify(GetLangKeys())); + } + 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.endLog = function () { + console.log( + ' \x1B[32m' + + lang + + 'token:' + + JSON.stringify(rtv) + + '\x1B[0m' + + '\n 此token可重复使用,有效期到:' + + new Date(cache.ExpireTime * 1000).toLocaleString(), + ); + }; + 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.cjs'); +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 < len; i++) { + r = Math.floor(Math.random() * 16); + if (r < 10) { + s.push(String.fromCharCode(r + 48)); + } else { + s.push(String.fromCharCode(r - 10 + 97)); + } + } + return s.join(''); +}; +var HMAC = function (hash, key, data, resType) { + var hmac = Crypto.createHmac(hash, key); + hmac.update(data); + return hmac.digest(resType === null ? null : resType || 'hex'); +}; + +/***************提供接口***************/ +var Api = {}; //async method_path0(ctx,args) + +//内容回显 +Api.GET_ = Api.GET_echo = async function (ctx, args) { + ctx.setValue('

阿里云一句话识别TokenApi服务正在运行...

', 'html'); +}; +Api.POST_ = Api.POST_echo = async function (ctx, args) { + ctx.setValue({ url: ctx.req.url, method: ctx.req.method, headers: ctx.req.headers, args: args }); +}; + +//token接口 +Api.GET_token = Api.POST_token = async function (ctx, args) { + await GetAsrToken(ctx, args); +}; + +/***开启http服务***/ +var http = require('http'); +var https = require('https'); +var querystring = require('querystring'); +var reqProcess = function (req, rep) { + var ctx = { + req: req, + rep: req, + data: { c: 0, m: '', v: '' }, + status: 200, + setCT: false, + contentType: 'text/json; charset=utf-8', + }; + ctx.setValue = function (val, contentType) { + if (contentType != null) { + ctx.setCT = true; + ctx.contentType = !contentType || contentType == 'html' ? 'text/html; charset=utf-8' : contentType; + } + ctx.data.v = val; + }; + ctx.error = function (msg) { + ctx.data.c = 1; + ctx.data.m = msg; + return ctx; + }; + ctx.isError = function () { + return ctx.data.c != 0; + }; + ctx.getMsg = function () { + return ctx.data.m; + }; + ctx.endLog = function () {}; + + var post = Buffer.alloc(0); + req.on('data', function (chunk) { + post = Buffer.concat([post, chunk], post.length + chunk.length); + }); + req.on('end', function () { + (async function () { + if (req.method != 'GET' && req.method != 'POST') { + ctx.setValue('Method: ' + req.method, 'html'); + } else + try { + //解析url查询参数 和 post表单 + var params = querystring.parse((/\?(.+)/.exec(req.url) || [])[1] || ''); + params = Object.assign(params, querystring.parse(post.toString())); + + var path0 = (/^\/([^\/\?]+)/.exec(req.url) || [])[1] || ''; + var fn = Api[req.method + '_' + path0]; + if (fn) { + await fn(ctx, params); + } else { + ctx.status = 404; + ctx.error(req.method + '路径不存在:' + req.url); + } + } catch (e) { + ctx.error('执行出错:' + e.stack); + } + if (!ctx.setCT) { + try { + var sendData = JSON.stringify(ctx.data); + } catch (e) { + sendData = JSON.stringify({ c: 1, m: '返回数据失败:' + e.stack }); + } + } else { + var sendData = ctx.data.v; + } + + rep.writeHead(ctx.status, { + 'Content-Type': ctx.contentType, + 'Access-Control-Allow-Origin': '*', + }); + rep.end(sendData); + + console.log( + '[' + + new Date().toLocaleString() + + ']:' + + Port + + ' ' + + req.method + + ' ' + + ctx.status + + ' ' + + Buffer.byteLength(sendData) + + ' ' + + post.length + + ' ' + + req.url, + ); + if (ctx.isError()) { + console.log(' \x1B[31m' + ctx.getMsg() + '\x1B[0m'); + } + ctx.endLog(); + })(); + }); +}; + +var UrlProtocol = 'http'; +var UrlPort = Port == 80 ? '' : ':' + Port; +if (SSL.CertFile) { + UrlProtocol = 'https'; + UrlPort = Port == 443 ? '' : ':' + Port; +} + +console.log('正在创建' + UrlProtocol + '服务(port:' + Port + ')...'); +if (SSL.CertFile) { + https + .createServer( + { + cert: fs.readFileSync(SSL.CertFile), + key: fs.readFileSync(SSL.KeyFile), + }, + reqProcess, + ) + .listen(Port); +} else { + http.createServer(reqProcess).listen(Port); +} + +console.log('\x1B[32m%s\x1B[0m', UrlProtocol.toUpperCase() + '服务正在运行...'); +console.log(` +请在语音识别测试页面填写接口地址: \x1B[33m + ${UrlProtocol}://127.0.0.1${UrlPort}/token + ${UrlProtocol}://localhost${UrlPort}/token + ${UrlProtocol}://你的局域网IP${UrlPort}/token + ${UrlProtocol}://你的域名${UrlPort}/token +\x1B[0m +如果你的测试页面\x1B[35m无法访问http地址\x1B[0m或\x1B[35m存在跨域问题\x1B[0m时,请在本电脑上直接访问 \x1B[33m${UrlProtocol}://127.0.0.1${UrlPort}/token?lang=你需要lang语言\x1B[0m +然后手动复制 \x1B[33m{appkey:'...',token:'...'}\x1B[0m json到页面中使用,复制的token可以重复使用,本控制台中会显示有效期 + 已配置的可用lang语言\x1B[33m${JSON.stringify(GetLangKeys())}\x1B[0m +`); diff --git a/backend/src/lib.load.cjs b/backend/src/lib.load.cjs new file mode 100644 index 0000000..976f921 --- /dev/null +++ b/backend/src/lib.load.cjs @@ -0,0 +1,199 @@ +//请求数据封装 +var LoadFn=module.exports=function(url){ + return new Load(url); +}; + +var QueryString = require('querystring'); +var Http=require('http'); +var Https=require('https'); + +var Load=function(url){ + this.response={//响应数据 + url:"" //最终响应的url,如果发生了30x跳转为跳转后的地址 + ,status:0 + ,statusDesc:"" //Not Found + ,headers:[] //["k: v",...] k大小写未知 + ,data:null //string或buffer + }; + + this.params={};//表单参数 GET或POST表单 + this.rawPost=null;//POST数据 string或buffer + this.headers={}; + this.contentType="application/x-www-form-urlencoded"; + this.timeout=15019;//默认GET的,POST为30000 + this.redirect=true;//是否允许重定向 + this.debug=false;//调试模式,会忽略证书的校验 + + this._url=url; + var m=/((\w+:)?\/\/([^\/:]+)(\:\d+)?)(.*)/.exec(url)||[]; + this._url_left=m[1]; + this._url_protocol=(m[2]||"http:").toLowerCase(); + this._url_isHttps=this._url_protocol=="https:"; + this._url_host=m[3]||""; + this._url_port=+(m[4]||":"+(this._url_isHttps?443:80)).substr(1); + this._url_pq=m[5]||""; +}; +Load.prototype={ + +_redirect:async function(url,checkSuccessStatus,method,encode){ + if(/(^https?:\/\/)|(^\/)/i.test(url)){ + if(RegExp.$2){ + url=this._url_left+url; + }; + }else{ + throw new Error("未支持的重定向地址格式:"+url); + }; + + var redirectCount=this.redirectCount||0; + if(redirectCount>=10){ + throw new Error("重定向超过次数"); + }; + var load=new Load(url); + + load.params=this.params; + load.rawPost=this.rawPost; + load.headers=this.headers; + load.contentType=this.contentType; + load.timeout=this.timeout; + load.redirect=this.redirect; + load.debug=this.debug; + + + load.redirectCount=redirectCount+1; + await load.send(checkSuccessStatus,method,encode); + return load; +} + + + + +,set:function(k,v){ + this[k]=v; + return this; +} + +,send:async function(checkSuccessStatus,method,encode){ + var This=this; + return await new Promise(function(resolve, reject){ + var isGET=method=="GET"; + var url=This._url_pq; + var params=QueryString.stringify(This.params); + if(isGET && params){ + if(url.indexOf("?")+1){ + url+="&"+params; + }else{ + url+="?"+params; + }; + }; + if(!isGET){ + This.headers["Content-Length"]=Buffer.byteLength(This.rawPost||params); + if(!This.headers["Content-Type"]){ + This.headers["Content-Type"]=This.contentType; + }; + }; + + var scope=This._url_isHttps?Https:Http; + var obj={ + method:method + ,headers:This.headers + ,timeout:This.timeout!=15019?This.timeout:isGET?15000:30000 + ,rejectUnauthorized:This.debug?false:true + + ,protocol:This._url_protocol + ,host:This._url_host + ,port:This._url_port + ,path:url + }; + var req=scope.request(obj,function(resp){ + var status=resp.statusCode; + var headers=[],location=""; + var arr=resp.rawHeaders; + for(var i=0;i=200 && status<300 )){ + reject(new Error("请求失败["+status+"]")); + return; + }; + }; + + This.response.data=Buffer.concat(buffers); + if(encode!=null){ + var enc=(encode=="json"?"":encode)||'utf8'; + var val=This.response.data.toString(enc); + if(encode=="json"){ + try{ + val=JSON.parse(val); + }catch(e){ + reject(new Error("请求结果解析失败")); + return; + }; + }; + This.response.data=val; + }; + + resolve(This.response.data); + }); + }); + req.on("error",function(e){ + reject(new Error("请求错误:"+e.message)); + }); + + if(!isGET){ + if(This.rawPost){ + req.write(This.rawPost); + }else if(params){ + req.write(params); + }; + }; + req.end(); + }); +} + +,getBytes:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"GET"); +} +,getString:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"GET",""); +} +,getJson:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"GET","json"); +} + +,postBytes:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"POST"); +} +,postString:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"POST",""); +} +,postJson:async function(checkSuccessStatus){ + return await this.send(checkSuccessStatus,"POST","json"); +} + +}; \ No newline at end of file diff --git a/index.html b/index.html index d196ad3..b15b6b9 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,11 @@ Vite + React + TS + + + + +