g-ai-robot3 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,30 +11,2239 @@
11
11
  return /******/ (function() { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
14
- /***/ 5425:
15
- /***/ (function(module) {
16
-
17
- /*!
18
- *
19
- * js-audio-recorder - js audio recorder plugin
20
- *
21
- * @version v1.0.7
22
- * @homepage https://github.com/2fps/recorder
23
- * @author 2fps <echoweb@126.com> (https://www.zhuyuntao.cn)
24
- * @license MIT
25
- *
26
- */
27
- !function(t,e){ true?module.exports=e():0}(this,function(){return function(t){var e={};function n(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return t[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(i,o,function(e){return t[e]}.bind(null,o));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=1)}([function(t,e,n){"use strict";function i(t,e,n){for(var i=0;i<n.length;i++)t.setUint8(e+i,n.charCodeAt(i))}Object.defineProperty(e,"__esModule",{value:!0}),e.compress=function(t,e,n){for(var i=e/n,o=Math.max(i,1),r=t.left,a=t.right,s=Math.floor((r.length+a.length)/i),u=new Float32Array(s),c=0,l=0;c<s;){var f=Math.floor(l);u[c]=r[f],c++,a.length&&(u[c]=a[f],c++),l+=o}return u},e.encodePCM=function(t,e,n){void 0===n&&(n=!0);var i=0,o=t.length*(e/8),r=new ArrayBuffer(o),a=new DataView(r);if(8===e)for(var s=0;s<t.length;s++,i++){var u=(c=Math.max(-1,Math.min(1,t[s])))<0?128*c:127*c;u=+u+128,a.setInt8(i,u)}else for(s=0;s<t.length;s++,i+=2){var c=Math.max(-1,Math.min(1,t[s]));a.setInt16(i,c<0?32768*c:32767*c,n)}return a},e.encodeWAV=function(t,e,n,o,r,a){void 0===a&&(a=!0);var s=n>e?e:n,u=r,c=new ArrayBuffer(44+t.byteLength),l=new DataView(c),f=o,p=0;i(l,p,"RIFF"),p+=4,l.setUint32(p,36+t.byteLength,a),i(l,p+=4,"WAVE"),i(l,p+=4,"fmt "),p+=4,l.setUint32(p,16,a),p+=4,l.setUint16(p,1,a),p+=2,l.setUint16(p,f,a),p+=2,l.setUint32(p,s,a),p+=4,l.setUint32(p,f*s*(u/8),a),p+=4,l.setUint16(p,f*(u/8),a),p+=2,l.setUint16(p,u,a),i(l,p+=2,"data"),p+=4,l.setUint32(p,t.byteLength,a),p+=4;for(var d=0;d<t.byteLength;)l.setUint8(p,t.getUint8(d)),p++,d++;return l}},function(t,e,n){"use strict";var i,o=this&&this.__extends||(i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)},function(t,e){function n(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)});Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),a=n(0),s=n(3),u=function(t){function e(e){void 0===e&&(e={});var n=t.call(this,e)||this;return n.isrecording=!1,n.ispause=!1,n.isplaying=!1,n}return o(e,t),e.prototype.setOption=function(t){void 0===t&&(t={}),this.setNewOption(t)},e.prototype.start=function(){return this.isrecording?Promise.reject():(this.isrecording=!0,this.startRecord())},e.prototype.pause=function(){this.isrecording&&!this.ispause&&(this.ispause=!0,this.pauseRecord())},e.prototype.resume=function(){this.isrecording&&this.ispause&&(this.ispause=!1,this.resumeRecord())},e.prototype.stop=function(){this.isrecording&&(this.isrecording=!1,this.ispause=!1,this.stopRecord())},e.prototype.play=function(){this.stop(),this.isplaying=!0,this.onplay&&this.onplay(),s.default.addPlayEnd(this.onplayend);var t=this.getWAV();t.byteLength>44&&s.default.play(t.buffer)},e.prototype.getPlayTime=function(){return s.default.getPlayTime()},e.prototype.pausePlay=function(){!this.isrecording&&this.isplaying&&(this.isplaying=!1,this.onpauseplay&&this.onpauseplay(),s.default.pausePlay())},e.prototype.resumePlay=function(){this.isrecording||this.isplaying||(this.isplaying=!0,this.onresumeplay&&this.onresumeplay(),s.default.resumePlay())},e.prototype.stopPlay=function(){this.isrecording||(this.isplaying=!1,this.onstopplay&&this.onstopplay(),s.default.stopPlay())},e.prototype.destroy=function(){return s.default.destroyPlay(),this.destroyRecord()},e.prototype.getRecordAnalyseData=function(){return this.getAnalyseData()},e.prototype.getPlayAnalyseData=function(){return s.default.getAnalyseData()},e.prototype.getPCM=function(){this.stop();var t=this.getData();return t=a.compress(t,this.inputSampleRate,this.outputSampleRate),a.encodePCM(t,this.oututSampleBits,this.littleEdian)},e.prototype.getPCMBlob=function(){return new Blob([this.getPCM()])},e.prototype.downloadPCM=function(t){void 0===t&&(t="recorder");var e=this.getPCMBlob();r.downloadPCM(e,t)},e.prototype.getWAV=function(){var t=this.getPCM();return a.encodeWAV(t,this.inputSampleRate,this.outputSampleRate,this.config.numChannels,this.oututSampleBits,this.littleEdian)},e.prototype.getWAVBlob=function(){return new Blob([this.getWAV()],{type:"audio/wav"})},e.prototype.downloadWAV=function(t){void 0===t&&(t="recorder");var e=this.getWAVBlob();r.downloadWAV(e,t)},e.prototype.download=function(t,e,n){r.download(t,e,n)},e.prototype.getChannelData=function(){var t=this.getPCM(),e=t.byteLength,n=this.littleEdian,i={left:null,right:null};if(2===this.config.numChannels){var o=new DataView(new ArrayBuffer(e/2)),r=new DataView(new ArrayBuffer(e/2));if(16===this.config.sampleBits)for(var a=0;a<e/2;a+=2)o.setInt16(a,t.getInt16(2*a,n),n),r.setInt16(a,t.getInt16(2*a+2,n),n);else for(a=0;a<e/2;a+=2)o.setInt8(a,t.getInt8(2*a)),r.setInt8(a,t.getInt8(2*a+1));i.left=o,i.right=r}else i.left=t;return i},e}(n(5).default);e.default=u},function(t,e,n){"use strict";function i(t,e,n){var i=document.createElement("a");i.href=window.URL.createObjectURL(t),i.download=e+"."+n,i.click()}Object.defineProperty(e,"__esModule",{value:!0}),e.downloadWAV=function(t,e){void 0===e&&(e="recorder"),i(t,e,"wav")},e.downloadPCM=function(t,e){void 0===e&&(e="recorder"),i(t,e,"pcm")},e.download=function(t,e,n){return i(t,e,n)}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(4),o=null,r=0,a=0,s=null,u=null,c=null,l=!1,f=0,p=function(){};function d(){return l=!1,s.decodeAudioData(c.slice(0),function(t){(o=s.createBufferSource()).onended=function(){l||(f=s.currentTime-a+r,p())},o.buffer=t,o.connect(u),u.connect(s.destination),o.start(0,r),a=s.currentTime},function(t){i.throwError(t)})}function h(){o&&(o.stop(),o=null)}var y=function(){function t(){}return t.play=function(t){return s||(s=new(window.AudioContext||window.webkitAudioContext),(u=s.createAnalyser()).fftSize=2048),this.stopPlay(),c=t,f=0,d()},t.pausePlay=function(){h(),r+=s.currentTime-a,l=!0},t.resumePlay=function(){return d()},t.stopPlay=function(){r=0,c=null,h()},t.destroyPlay=function(){this.stopPlay()},t.getAnalyseData=function(){var t=new Uint8Array(u.frequencyBinCount);return u.getByteTimeDomainData(t),t},t.addPlayEnd=function(t){void 0===t&&(t=function(){}),p=t},t.getPlayTime=function(){var t=l?r:s.currentTime-a+r;return f||t},t}();e.default=y},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.throwError=function(t){throw new Error(t)}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n(0),o=function(){function t(e){void 0===e&&(e={}),this.size=0,this.lBuffer=[],this.rBuffer=[],this.tempPCM=[],this.inputSampleBits=16,this.fileSize=0,this.duration=0,this.needRecord=!0;var n,i=new(window.AudioContext||window.webkitAudioContext);this.inputSampleRate=i.sampleRate,this.setNewOption(e),this.littleEdian=(n=new ArrayBuffer(2),new DataView(n).setInt16(0,256,!0),256===new Int16Array(n)[0]),t.initUserMedia()}return t.prototype.setNewOption=function(t){void 0===t&&(t={}),this.config={sampleBits:~[8,16].indexOf(t.sampleBits)?t.sampleBits:16,sampleRate:~[8e3,11025,16e3,22050,24e3,44100,48e3].indexOf(t.sampleRate)?t.sampleRate:this.inputSampleRate,numChannels:~[1,2].indexOf(t.numChannels)?t.numChannels:1},this.outputSampleRate=this.config.sampleRate,this.oututSampleBits=this.config.sampleBits},t.prototype.startRecord=function(){var t=this;return this.context&&this.destroyRecord(),this.initRecorder(),navigator.mediaDevices.getUserMedia({audio:!0}).then(function(e){t.audioInput=t.context.createMediaStreamSource(e),t.stream=e}).then(function(){t.audioInput.connect(t.analyser),t.analyser.connect(t.recorder),t.recorder.connect(t.context.destination)})},t.prototype.pauseRecord=function(){this.needRecord=!1},t.prototype.resumeRecord=function(){this.needRecord=!0},t.prototype.stopRecord=function(){this.audioInput&&this.audioInput.disconnect(),this.source&&this.source.stop(),this.recorder.disconnect(),this.analyser.disconnect(),this.needRecord=!0},t.prototype.destroyRecord=function(){return this.clearRecordStatus(),this.stopStream(),this.closeAudioContext()},t.prototype.getAnalyseData=function(){var t=new Uint8Array(this.analyser.frequencyBinCount);return this.analyser.getByteTimeDomainData(t),t},t.prototype.getData=function(){return this.flat()},t.prototype.clearRecordStatus=function(){this.lBuffer.length=0,this.rBuffer.length=0,this.size=0,this.fileSize=0,this.PCM=null,this.audioInput=null,this.duration=0},t.prototype.flat=function(){var t=null,e=new Float32Array(0);1===this.config.numChannels?t=new Float32Array(this.size):(t=new Float32Array(this.size/2),e=new Float32Array(this.size/2));for(var n=0,i=0;i<this.lBuffer.length;i++)t.set(this.lBuffer[i],n),n+=this.lBuffer[i].length;n=0;for(i=0;i<this.rBuffer.length;i++)e.set(this.rBuffer[i],n),n+=this.rBuffer[i].length;return{left:t,right:e}},t.prototype.initRecorder=function(){var t=this;this.clearRecordStatus(),this.context=new(window.AudioContext||window.webkitAudioContext),this.analyser=this.context.createAnalyser(),this.analyser.fftSize=2048;var e=this.context.createScriptProcessor||this.context.createJavaScriptNode;this.recorder=e.apply(this.context,[4096,this.config.numChannels,this.config.numChannels]),this.recorder.onaudioprocess=function(e){if(t.needRecord){var n,i=e.inputBuffer.getChannelData(0),o=null;t.lBuffer.push(new Float32Array(i)),t.size+=i.length,2===t.config.numChannels&&(o=e.inputBuffer.getChannelData(1),t.rBuffer.push(new Float32Array(o)),t.size+=o.length),t.fileSize=Math.floor(t.size/Math.max(t.inputSampleRate/t.outputSampleRate,1))*(t.oututSampleBits/8),n=100*Math.max.apply(Math,i),t.duration+=4096/t.inputSampleRate,t.onprocess&&t.onprocess(t.duration),t.onprogress&&t.onprogress({duration:t.duration,fileSize:t.fileSize,vol:n})}}},t.prototype.stopStream=function(){this.stream&&this.stream.getTracks&&(this.stream.getTracks().forEach(function(t){return t.stop()}),this.stream=null)},t.prototype.closeAudioContext=function(){return this.context&&this.context.close&&"closed"!==this.context.state?this.context.close():new Promise(function(t){t()})},t.initUserMedia=function(){void 0===navigator.mediaDevices&&(navigator.mediaDevices={}),void 0===navigator.mediaDevices.getUserMedia&&(navigator.mediaDevices.getUserMedia=function(t){var e=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return e?new Promise(function(n,i){e.call(navigator,t,n,i)}):Promise.reject(new Error("浏览器不支持 getUserMedia !"))})},t.prototype.transformIntoPCM=function(t,e){var n=new Float32Array(t),o=new Float32Array(e),r=i.compress({left:n,right:o},this.inputSampleRate,this.outputSampleRate);return i.encodePCM(r,this.oututSampleBits,this.littleEdian)},t.getPermission=function(){return this.initUserMedia(),navigator.mediaDevices.getUserMedia({audio:!0}).then(function(t){t&&t.getTracks().forEach(function(t){return t.stop()})})},t}();e.default=o}]).default});
28
- //# sourceMappingURL=recorder.js.map
14
+ /***/ 9243:
15
+ /***/ (function() {
16
+
17
+ /*
18
+ 录音 Recorder扩展,动态波形显示
19
+ https://github.com/xiangyuecn/Recorder
20
+ */
21
+ (function(factory){
22
+ var browser=typeof window=="object" && !!window.document;
23
+ var win=browser?window:Object; //非浏览器环境,Recorder挂载在Object下面
24
+ var rec=win.Recorder,ni=rec.i18n;
25
+ factory(rec,ni,ni.$T,browser);
26
+ }(function(Recorder,i18n,$T,isBrowser){
27
+ "use strict";
28
+
29
+ var WaveView=function(set){
30
+ return new fn(set);
31
+ };
32
+ var ViewTxt="WaveView";
33
+ var fn=function(set){
34
+ var This=this;
35
+ var o={
36
+ /*
37
+ elem:"css selector" //自动显示到dom,并以此dom大小为显示大小
38
+ //或者配置显示大小,手动把waveviewObj.elem显示到别的地方
39
+ ,width:0 //显示宽度
40
+ ,height:0 //显示高度
41
+
42
+ H5环境以上配置二选一
43
+
44
+ compatibleCanvas: CanvasObject //提供一个兼容H5的canvas对象,需支持getContext("2d"),支持设置width、height,支持drawImage(canvas,...)
45
+ ,width:0 //canvas显示宽度
46
+ ,height:0 //canvas显示高度
47
+ 非H5环境使用以上配置
48
+ */
49
+
50
+ scale:2 //缩放系数,应为正整数,使用2(3? no!)倍宽高进行绘制,避免移动端绘制模糊
51
+ ,speed:9 //移动速度系数,越大越快
52
+ ,phase:21.8 //相位,调整了速度后,调整这个值得到一个看起来舒服的波形
53
+
54
+ ,fps:20 //绘制帧率,调整后也需调整phase值
55
+ ,keep:true //当停止了input输入时,是否保持波形,设为false停止后将变成一条线
56
+
57
+ ,lineWidth:3 //线条基础粗细
58
+
59
+ //渐变色配置:[位置,css颜色,...] 位置: 取值0.0-1.0之间
60
+ ,linear1:[0,"rgba(150,96,238,1)",0.2,"rgba(170,79,249,1)",1,"rgba(53,199,253,1)"] //线条渐变色1,从左到右
61
+ ,linear2:[0,"rgba(209,130,255,0.6)",1,"rgba(53,199,255,0.6)"] //线条渐变色2,从左到右
62
+ ,linearBg:[0,"rgba(255,255,255,0.2)",1,"rgba(54,197,252,0.2)"] //背景渐变色,从上到下
63
+ };
64
+ for(var k in set){
65
+ o[k]=set[k];
66
+ };
67
+ This.set=set=o;
68
+
69
+ var cCanvas="compatibleCanvas";
70
+ if(set[cCanvas]){
71
+ var canvas=This.canvas=set[cCanvas];
72
+ }else{
73
+ if(!isBrowser)throw new Error($T.G("NonBrowser-1",[ViewTxt]));
74
+ var elem=set.elem;
75
+ if(elem){
76
+ if(typeof(elem)=="string"){
77
+ elem=document.querySelector(elem);
78
+ }else if(elem.length){
79
+ elem=elem[0];
80
+ };
81
+ };
82
+ if(elem){
83
+ set.width=elem.offsetWidth;
84
+ set.height=elem.offsetHeight;
85
+ };
86
+
87
+ var thisElem=This.elem=document.createElement("div");
88
+ thisElem.style.fontSize=0;
89
+ thisElem.innerHTML='<canvas style="width:100%;height:100%;"/>';
90
+
91
+ var canvas=This.canvas=thisElem.querySelector("canvas");
92
+
93
+ if(elem){
94
+ elem.innerHTML="";
95
+ elem.appendChild(thisElem);
96
+ };
97
+ };
98
+ var scale=set.scale;
99
+ var width=set.width*scale;
100
+ var height=set.height*scale;
101
+ if(!width || !height){
102
+ throw new Error($T.G("IllegalArgs-1",[ViewTxt+" width=0 height=0"]));
103
+ };
104
+
105
+ canvas.width=width;
106
+ canvas.height=height;
107
+ var ctx=This.ctx=canvas.getContext("2d");
108
+
109
+ This.linear1=This.genLinear(ctx,width,set.linear1);
110
+ This.linear2=This.genLinear(ctx,width,set.linear2);
111
+ This.linearBg=This.genLinear(ctx,height,set.linearBg,true);
112
+
113
+ This._phase=0;
114
+ };
115
+ fn.prototype=WaveView.prototype={
116
+ genLinear:function(ctx,size,colors,top){
117
+ var rtv=ctx.createLinearGradient(0,0,top?0:size,top?size:0);
118
+ for(var i=0;i<colors.length;){
119
+ rtv.addColorStop(colors[i++],colors[i++]);
120
+ };
121
+ return rtv;
122
+ }
123
+ ,genPath:function(frequency,amplitude,phase){
124
+ //曲线生成算法参考 https://github.com/HaloMartin/MCVoiceWave/blob/f6dc28975fbe0f7fc6cc4dbc2e61b0aa5574e9bc/MCVoiceWave/MCVoiceWaveView.m#L268
125
+ var rtv=[];
126
+ var This=this,set=This.set;
127
+ var scale=set.scale;
128
+ var width=set.width*scale;
129
+ var maxAmplitude=set.height*scale/2;
130
+
131
+ for(var x=0;x<=width;x+=scale) {
132
+ var scaling=(1+Math.cos(Math.PI+(x/width)*2*Math.PI))/2;
133
+ var y=scaling*maxAmplitude*amplitude*Math.sin(2*Math.PI*(x/width)*frequency+phase)+maxAmplitude;
134
+ rtv.push(y);
135
+ }
136
+ return rtv;
137
+ }
138
+ ,input:function(pcmData,powerLevel,sampleRate){
139
+ var This=this;
140
+ This.sampleRate=sampleRate;
141
+ This.pcmData=pcmData;
142
+ This.pcmPos=0;
143
+
144
+ This.inputTime=Date.now();
145
+ This.schedule();
146
+ }
147
+ ,schedule:function(){
148
+ var This=this,set=This.set;
149
+ var interval=Math.floor(1000/set.fps);
150
+ if(!This.timer){
151
+ This.timer=setInterval(function(){
152
+ This.schedule();
153
+ },interval);
154
+ };
155
+
156
+ var now=Date.now();
157
+ var drawTime=This.drawTime||0;
158
+ if(now-drawTime<interval){
159
+ //没到间隔时间,不绘制
160
+ return;
161
+ };
162
+ This.drawTime=now;
163
+
164
+ //切分当前需要的绘制数据
165
+ var bufferSize=This.sampleRate/set.fps;
166
+ var pcm=This.pcmData;
167
+ var pos=This.pcmPos;
168
+ var len=Math.max(0, Math.min(bufferSize,pcm.length-pos));
169
+ var sum=0;
170
+ for(var i=0;i<len;i++,pos++){
171
+ sum+=Math.abs(pcm[pos]);
172
+ };
173
+ This.pcmPos=pos;
174
+
175
+ //推入绘制
176
+ if(len || !set.keep){
177
+ This.draw(Recorder.PowerLevel(sum, len));
178
+ }
179
+ if(!len && now-This.inputTime>1300){
180
+ //超时没有输入,干掉定时器
181
+ clearInterval(This.timer);
182
+ This.timer=0;
183
+ }
184
+ }
185
+ ,draw:function(powerLevel){
186
+ var This=this,set=This.set;
187
+ var ctx=This.ctx;
188
+ var scale=set.scale;
189
+ var width=set.width*scale;
190
+ var height=set.height*scale;
191
+
192
+ var speedx=set.speed/set.fps;
193
+ var phase=This._phase-=speedx;//位移速度
194
+ var phase2=phase+speedx*set.phase;
195
+ var amplitude=powerLevel/100;
196
+ var path1=This.genPath(2,amplitude,phase);
197
+ var path2=This.genPath(1.8,amplitude,phase2);
198
+
199
+ //开始绘制图形
200
+ ctx.clearRect(0,0,width,height);
201
+
202
+ //绘制包围背景
203
+ ctx.beginPath();
204
+ for(var i=0,x=0;x<=width;i++,x+=scale) {
205
+ if (x==0) {
206
+ ctx.moveTo(x,path1[i]);
207
+ }else {
208
+ ctx.lineTo(x,path1[i]);
209
+ };
210
+ };
211
+ i--;
212
+ for(var x=width-1;x>=0;i--,x-=scale) {
213
+ ctx.lineTo(x,path2[i]);
214
+ };
215
+ ctx.closePath();
216
+ ctx.fillStyle=This.linearBg;
217
+ ctx.fill();
218
+
219
+ //绘制线
220
+ This.drawPath(path2,This.linear2);
221
+ This.drawPath(path1,This.linear1);
222
+ }
223
+ ,drawPath:function(path,linear){
224
+ var This=this,set=This.set;
225
+ var ctx=This.ctx;
226
+ var scale=set.scale;
227
+ var width=set.width*scale;
228
+
229
+ ctx.beginPath();
230
+ for(var i=0,x=0;x<=width;i++,x+=scale) {
231
+ if (x==0) {
232
+ ctx.moveTo(x,path[i]);
233
+ }else {
234
+ ctx.lineTo(x,path[i]);
235
+ };
236
+ };
237
+ ctx.lineWidth=set.lineWidth*scale;
238
+ ctx.strokeStyle=linear;
239
+ ctx.stroke();
240
+ }
241
+ };
242
+ Recorder[ViewTxt]=WaveView;
243
+
244
+
245
+ }));
29
246
 
30
247
  /***/ }),
31
248
 
32
- /***/ 7478:
33
- /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
249
+ /***/ 2346:
250
+ /***/ (function(module, exports, __webpack_require__) {
251
+
252
+ var __WEBPACK_AMD_DEFINE_RESULT__;/*
253
+ 录音
254
+ https://github.com/xiangyuecn/Recorder
255
+ */
256
+ (function(factory){
257
+ var browser=typeof window=="object" && !!window.document;
258
+ var win=browser?window:Object; //非浏览器环境,Recorder挂载在Object下面
259
+ factory(win,browser);
260
+ //umd returnExports.js
261
+ if(true){
262
+ !(__WEBPACK_AMD_DEFINE_RESULT__ = (function(){
263
+ return win.Recorder;
264
+ }).call(exports, __webpack_require__, exports, module),
265
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
266
+ };
267
+ if( true && module.exports){
268
+ module.exports=win.Recorder;
269
+ };
270
+ }(function(Export,isBrowser){
271
+ "use strict";
272
+
273
+ var NOOP=function(){};
274
+ var IsNum=function(v){return typeof v=="number"};
275
+ var ToJson=function(v){return JSON.stringify(v)};
276
+
277
+ var Recorder=function(set){
278
+ return new initFn(set);
279
+ };
280
+ var LM=Recorder.LM="2024-10-20 22:15";
281
+ var GitUrl="https://github.com/xiangyuecn/Recorder";
282
+ var RecTxt="Recorder";
283
+ var getUserMediaTxt="getUserMedia";
284
+ var srcSampleRateTxt="srcSampleRate";
285
+ var sampleRateTxt="sampleRate";
286
+ var bitRateTxt="bitRate";
287
+ var CatchTxt="catch";
288
+
289
+ var WRec2=Export[RecTxt];//重复加载js
290
+ if(WRec2&&WRec2.LM==LM){
291
+ WRec2.CLog(WRec2.i18n.$T("K8zP::重复导入{1}",0,RecTxt),3);
292
+ return;
293
+ };
294
+
295
+
296
+ //是否已经打开了全局的麦克风录音,所有工作都已经准备好了,就等接收音频数据了
297
+ Recorder.IsOpen=function(){
298
+ var stream=Recorder.Stream;
299
+ if(stream){
300
+ var tracks=Tracks_(stream), track=tracks[0];
301
+ if(track){
302
+ var state=track.readyState;
303
+ return state=="live"||state==track.LIVE;
304
+ };
305
+ };
306
+ return false;
307
+ };
308
+ /*H5录音时的AudioContext缓冲大小。会影响H5录音时的onProcess调用速率,相对于AudioContext.sampleRate=48000时,4096接近12帧/s,调节此参数可生成比较流畅的回调动画。
309
+ 取值256, 512, 1024, 2048, 4096, 8192, or 16384
310
+ 注意,取值不能过低,2048开始不同浏览器可能回调速率跟不上造成音质问题。
311
+ 一般无需调整,调整后需要先close掉已打开的录音,再open时才会生效。
312
+ */
313
+ Recorder.BufferSize=4096;
314
+ //销毁已持有的所有全局资源,当要彻底移除Recorder时需要显式的调用此方法
315
+ Recorder.Destroy=function(){
316
+ CLog(RecTxt+" Destroy");
317
+ Disconnect();//断开可能存在的全局Stream、资源
318
+
319
+ for(var k in DestroyList){
320
+ DestroyList[k]();
321
+ };
322
+ };
323
+ var DestroyList={};
324
+ //登记一个需要销毁全局资源的处理方法
325
+ Recorder.BindDestroy=function(key,call){
326
+ DestroyList[key]=call;
327
+ };
328
+ //判断浏览器是否支持录音,随时可以调用。注意:仅仅是检测浏览器支持情况,不会判断和调起用户授权,不会判断是否支持特定格式录音。
329
+ Recorder.Support=function(){
330
+ if(!isBrowser) return false;
331
+ var scope=navigator.mediaDevices||{};
332
+ if(!scope[getUserMediaTxt]){
333
+ scope=navigator;
334
+ scope[getUserMediaTxt]||(scope[getUserMediaTxt]=scope.webkitGetUserMedia||scope.mozGetUserMedia||scope.msGetUserMedia);
335
+ };
336
+ if(!scope[getUserMediaTxt]){
337
+ return false;
338
+ };
339
+ Recorder.Scope=scope;
340
+
341
+ if(!Recorder.GetContext()){
342
+ return false;
343
+ };
344
+ return true;
345
+ };
346
+ //获取AudioContext对象,如果浏览器不支持将返回null。tryNew=false时返回全局的Recorder.Ctx,Ctx.state可能是closed,仅限用于解码等操作。tryNew=true时会尝试创建新的ctx(不支持close的老浏览器依旧返回全局的),注意用完必须自己调用CloseNewCtx(ctx)关闭;注意:非用户操作(触摸、点击等)时调用返回的ctx.state可能是suspended状态,需要在用户操作时调用ctx.resume恢复成running状态,参考rec的runningContext配置
347
+ Recorder.GetContext=function(tryNew){
348
+ if(!isBrowser) return null;
349
+ var AC=window.AudioContext;
350
+ if(!AC){
351
+ AC=window.webkitAudioContext;
352
+ };
353
+ if(!AC){
354
+ return null;
355
+ };
356
+
357
+ var ctx=Recorder.Ctx, isNew=0;
358
+ if(!ctx){ //241020版本后不再保留打开状态的ctx,原因是iOS不全部关闭时新的ctx有可能不正常
359
+ //不能反复构造,低版本number of hardware contexts reached maximum (6)
360
+ ctx=Recorder.Ctx=new AC(); isNew=1;
361
+ Recorder.NewCtxs=Recorder.NewCtxs||[];
362
+
363
+ Recorder.BindDestroy("Ctx",function(){
364
+ var ctx=Recorder.Ctx;
365
+ if(ctx&&ctx.close){//能关掉就关掉,关不掉就保留着
366
+ CloseCtx(ctx);
367
+ Recorder.Ctx=0;
368
+ };
369
+ var arr=Recorder.NewCtxs; Recorder.NewCtxs=[];
370
+ for(var i=0;i<arr.length;i++)CloseCtx(arr[i]);
371
+ });
372
+ };
373
+ if(tryNew && ctx.close){//没法关闭的不允许再创建
374
+ if(!isNew){
375
+ if(!ctx._useC) CloseCtx(ctx); //关闭全局的,不再保留打开状态
376
+ ctx=new AC(); //如果是上面新建的就用上面的,不然就用全新的
377
+ };
378
+ ctx._useC=1;
379
+ Recorder.NewCtxs.push(ctx);
380
+ };
381
+ return ctx;
382
+ };
383
+ //关闭新创建的AudioContext(之前老版本如果是全局的不关闭,241020版本后全部关闭)
384
+ Recorder.CloseNewCtx=function(ctx){
385
+ if(ctx && ctx.close){
386
+ CloseCtx(ctx);
387
+ var arr=Recorder.NewCtxs||[],L=arr.length;
388
+ for(var i=0;i<arr.length;i++){
389
+ if(arr[i]==ctx){ arr.splice(i,1); break; }
390
+ }
391
+ CLog($T("mSxV::剩{1}个GetContext未close",0,L+"-1="+arr.length),arr.length?3:0);
392
+ }
393
+ };
394
+ var CloseCtx=function(ctx){
395
+ if(ctx && ctx.close && !ctx._isC){
396
+ ctx._isC=1;
397
+ if(ctx.state!="closed"){
398
+ try{ ctx.close() }catch(e){ CLog("ctx close err",1,e) }
399
+ }
400
+ }
401
+ };
402
+ //当AudioContext的状态是suspended时,调用resume恢复状态,但如果没有用户操作resume可能没有回调,封装解决此回调问题;check(count)返回true继续尝试resume,返回false终止任务(不回调False)
403
+ var ResumeCtx=Recorder.ResumeCtx=function(ctx,check,True,False){
404
+ var isEnd=0,isBind=0,isLsSC=0,runC=0,EL="EventListener",Tag="ResumeCtx ";
405
+ var end=function(err,ok){
406
+ if(isBind){ bind() }
407
+ if(!isEnd){ isEnd=1; //回调结果
408
+ err&&False(err,runC);
409
+ ok&&True(runC);
410
+ }
411
+ if(ok){ //监听后续状态变化
412
+ if(!ctx._LsSC && ctx["add"+EL]) ctx["add"+EL]("statechange",run);
413
+ ctx._LsSC=1; isLsSC=1;
414
+ }
415
+ };
416
+ var bind=function(add){
417
+ if(add && isBind) return; isBind=add?1:0;
418
+ var types=["focus","mousedown","mouseup","touchstart","touchend"];
419
+ for(var i=0;i<types.length;i++)
420
+ window[(add?"add":"remove")+EL](types[i],run,true);
421
+ };
422
+ var run=function(){
423
+ var sVal=ctx.state,spEnd=CtxSpEnd(sVal);
424
+ if(!isEnd && !check(spEnd?++runC:runC))return end(); //终止,不回调
425
+ if(spEnd){
426
+ if(isLsSC)CLog(Tag+"sc "+sVal,3);
427
+ bind(1); //绑定用户事件尝试恢复
428
+ ctx.resume().then(function(){ //resume回调不可靠
429
+ if(isLsSC)CLog(Tag+"sc "+ctx.state);
430
+ end(0,1);
431
+ })[CatchTxt](function(e){ //出错且无法恢复
432
+ CLog(Tag+"error",1,e);
433
+ if(!CtxSpEnd(ctx.state)){
434
+ end(e.message||"error");
435
+ }
436
+ });
437
+ }else if(sVal=="closed"){
438
+ if(isLsSC && !ctx._isC)CLog(Tag+"sc "+sVal,1); //无法恢复,打个日志
439
+ end("ctx closed");
440
+ }else{ end(0,1) }; //running 或老的无state
441
+ };
442
+ run();
443
+ };
444
+ var CtxSpEnd=Recorder.CtxSpEnd=function(v){
445
+ return v=="suspended"||v=="interrupted"; //后面这个仅iOS有
446
+ };
447
+ var CtxState=function(ctx){
448
+ var v=ctx.state,msg="ctx.state="+v;
449
+ if(CtxSpEnd(v))msg+=$T("nMIy::(注意:ctx不是running状态,rec.open和start至少要有一个在用户操作(触摸、点击等)时进行调用,否则将在rec.start时尝试进行ctx.resume,可能会产生兼容性问题(仅iOS),请参阅文档中runningContext配置)");
450
+ return msg;
451
+ };
452
+
453
+
454
+ /*是否启用MediaRecorder.WebM.PCM来进行音频采集连接(如果浏览器支持的话),默认启用,禁用或者不支持时将使用AudioWorklet或ScriptProcessor来连接;MediaRecorder采集到的音频数据比其他方式更好,几乎不存在丢帧现象,所以音质明显会好很多,建议保持开启*/
455
+ var ConnectEnableWebM="ConnectEnableWebM";
456
+ Recorder[ConnectEnableWebM]=true;
457
+
458
+ /*是否启用AudioWorklet特性来进行音频采集连接(如果浏览器支持的话),默认禁用,禁用或不支持时将使用过时的ScriptProcessor来连接(如果方法还在的话),当前AudioWorklet的实现在移动端没有ScriptProcessor稳健;ConnectEnableWebM如果启用并且有效时,本参数将不起作用*/
459
+ var ConnectEnableWorklet="ConnectEnableWorklet";
460
+ Recorder[ConnectEnableWorklet]=false;
461
+
462
+ /*初始化H5音频采集连接。如果自行提供了sourceStream将只进行一次简单的连接处理。如果是普通麦克风录音,此时的Stream是全局的,Safari上断开后就无法再次进行连接使用,表现为静音,因此使用全部使用全局处理避免调用到disconnect;全局处理也有利于屏蔽底层细节,start时无需再调用底层接口,提升兼容、可靠性。*/
463
+ var Connect=function(streamStore){
464
+ var bufferSize=streamStore.BufferSize||Recorder.BufferSize;
465
+
466
+ var stream=streamStore.Stream;
467
+ var ctx=stream._c, ctxSR=ctx[sampleRateTxt], srChunk={};
468
+
469
+ //获取音频流信息
470
+ var tracks=Tracks_(stream),track=tracks[0],trackSet=null,tsMsg="";
471
+ if(track && track.getSettings){
472
+ trackSet=track.getSettings();
473
+ var trackSR=trackSet[sampleRateTxt];
474
+ if(trackSR && trackSR!=ctxSR){
475
+ tsMsg=$T("eS8i::Stream的采样率{1}不等于{2},将进行采样率转换(注意:音质不会变好甚至可能变差),主要在移动端未禁用回声消除时会产生此现象,浏览器有回声消除时可能只会返回16k采样率的音频数据,",0,trackSR,ctxSR);
476
+ }
477
+ }
478
+ stream._ts=trackSet;
479
+ CLog(tsMsg+"Stream TrackSet: "+ToJson(trackSet), tsMsg?3:0);
480
+
481
+ var mediaConn=function(node){
482
+ var media=stream._m=ctx.createMediaStreamSource(stream);
483
+ var ctxDest=ctx.destination,cmsdTxt="createMediaStreamDestination";
484
+ if(ctx[cmsdTxt]){
485
+ ctxDest=stream._d=ctx[cmsdTxt]();
486
+ };
487
+ media.connect(node);
488
+ node.connect(ctxDest);
489
+ }
490
+ var isWebM,isWorklet,badInt,webMTips="";
491
+ var calls=stream._call;
492
+
493
+ //浏览器回传的音频数据处理
494
+ var onReceive=function(float32Arr, arrSR){
495
+ for(var k0 in calls){//has item
496
+ if(arrSR!=ctxSR){ //MediaRecorder录制的采样率可能和ctx的采样率不同(16k),转换采样率方便统一处理代码也更简单,但音质不会变好,甚至可能会变差一点
497
+ srChunk.index=0;
498
+ srChunk=Recorder.SampleData([float32Arr],arrSR,ctxSR,srChunk,{_sum:1});
499
+ var pcm=srChunk.data;
500
+ var sum=srChunk._sum;
501
+ }else{ //采样率相同,不需要转换采样率
502
+ srChunk={};
503
+ var size=float32Arr.length;
504
+
505
+ var pcm=new Int16Array(size);
506
+ var sum=0;
507
+ for(var j=0;j<size;j++){//floatTo16BitPCM
508
+ var s=Math.max(-1,Math.min(1,float32Arr[j]));
509
+ s=s<0?s*0x8000:s*0x7FFF;
510
+ pcm[j]=s;
511
+ sum+=Math.abs(s);
512
+ };
513
+ };
514
+
515
+ for(var k in calls){
516
+ calls[k](pcm,sum);
517
+ };
518
+
519
+ return;
520
+ };
521
+ };
522
+
523
+ var scriptProcessor="ScriptProcessor";//一堆字符串名字,有利于压缩js
524
+ var audioWorklet="audioWorklet";
525
+ var recAudioWorklet=RecTxt+" "+audioWorklet;
526
+ var RecProc="RecProc";
527
+ var MediaRecorderTxt="MediaRecorder";
528
+ var MRWebMPCM=MediaRecorderTxt+".WebM.PCM";
529
+
530
+
531
+ //===================连接方式三=========================
532
+ //古董级别的 ScriptProcessor 处理,目前所有浏览器均兼容,虽然是过时的方法,但更稳健,移动端性能比AudioWorklet强
533
+ var oldFn=ctx.createScriptProcessor||ctx.createJavaScriptNode;
534
+ var oldIsBest=$T("ZGlf::。由于{1}内部1秒375次回调,在移动端可能会有性能问题导致回调丢失录音变短,PC端无影响,暂不建议开启{1}。",0,audioWorklet);
535
+ var oldScript=function(){
536
+ isWorklet=stream.isWorklet=false;
537
+ _Disconn_n(stream);
538
+ CLog($T("7TU0::Connect采用老的{1},",0,scriptProcessor)
539
+ +i18n.get(Recorder[ConnectEnableWorklet]?
540
+ $T("JwCL::但已设置{1}尝试启用{2}",2)
541
+ :$T("VGjB::可设置{1}尝试启用{2}",2)
542
+ ,[RecTxt+"."+ConnectEnableWorklet+"=true",audioWorklet]
543
+ )+webMTips+oldIsBest,3);
544
+
545
+ var process=stream._p=oldFn.call(ctx,bufferSize,1,1);//单声道,省的数据处理复杂
546
+ mediaConn(process);
547
+
548
+ process.onaudioprocess=function(e){
549
+ var arr=e.inputBuffer.getChannelData(0);
550
+ onReceive(arr, ctxSR);
551
+ };
552
+ };
553
+
554
+
555
+ //===================连接方式二=========================
556
+ var connWorklet=function(){
557
+ //尝试开启AudioWorklet处理
558
+ isWebM=stream.isWebM=false;
559
+ _Disconn_r(stream);
560
+
561
+ isWorklet=stream.isWorklet=!oldFn || Recorder[ConnectEnableWorklet];
562
+ var AwNode=window.AudioWorkletNode;
563
+ if(!(isWorklet && ctx[audioWorklet] && AwNode)){
564
+ oldScript();//被禁用 或 不支持,直接使用老的
565
+ return;
566
+ };
567
+ var clazzUrl=function(){
568
+ var xf=function(f){return f.toString().replace(/^function|DEL_/g,"").replace(/\$RA/g,recAudioWorklet)};
569
+ var clazz='class '+RecProc+' extends AudioWorkletProcessor{';
570
+ clazz+="constructor "+xf(function(option){
571
+ DEL_super(option);
572
+ var This=this,bufferSize=option.processorOptions.bufferSize;
573
+ This.bufferSize=bufferSize;
574
+ This.buffer=new Float32Array(bufferSize*2);//乱给size搞乱缓冲区不管
575
+ This.pos=0;
576
+ This.port.onmessage=function(e){
577
+ if(e.data.kill){
578
+ This.kill=true;
579
+ $C.log("$RA kill call");
580
+ }
581
+ };
582
+ $C.log("$RA .ctor call", option);
583
+ });
584
+
585
+ //https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process 每次回调128个采样数据,1秒375次回调,高频导致移动端性能问题,结果就是回调次数缺斤少两,进而导致丢失数据,PC端似乎没有性能问题
586
+ clazz+="process "+xf(function(input,b,c){//需要等到ctx激活后才会有回调
587
+ var This=this,bufferSize=This.bufferSize;
588
+ var buffer=This.buffer,pos=This.pos;
589
+ input=(input[0]||[])[0]||[];
590
+ if(input.length){
591
+ buffer.set(input,pos);
592
+ pos+=input.length;
593
+
594
+ var len=~~(pos/bufferSize)*bufferSize;
595
+ if(len){
596
+ this.port.postMessage({ val: buffer.slice(0,len) });
597
+
598
+ var more=buffer.subarray(len,pos);
599
+ buffer=new Float32Array(bufferSize*2);
600
+ buffer.set(more);
601
+ pos=more.length;
602
+ This.buffer=buffer;
603
+ }
604
+ This.pos=pos;
605
+ }
606
+ return !This.kill;
607
+ });
608
+ clazz+='}'
609
+ +'try{'
610
+ +'registerProcessor("'+RecProc+'", '+RecProc+')'
611
+ +'}catch(e){$C.error("'+recAudioWorklet+' Reg Error",e)}';
612
+ clazz=clazz.replace(/\$C\./g,"console.");//一些编译器会文本替换日志函数
613
+ //URL.createObjectURL 本地有些浏览器会报 Not allowed to load local resource,直接用dataurl
614
+ return "data:text/javascript;base64,"+btoa(unescape(encodeURIComponent(clazz)));
615
+ };
616
+
617
+ var awNext=function(){//可以继续,没有调用断开
618
+ return isWorklet && stream._na;
619
+ };
620
+ var nodeAlive=stream._na=function(){
621
+ //start时会调用,只要没有收到数据就断定AudioWorklet有问题,恢复用老的
622
+ if(badInt!==""){//没有回调过数据
623
+ clearTimeout(badInt);
624
+ badInt=setTimeout(function(){
625
+ badInt=0;
626
+ if(awNext()){
627
+ CLog($T("MxX1::{1}未返回任何音频,恢复使用{2}",0,audioWorklet,scriptProcessor),3);
628
+ oldFn&&oldScript();//未来没有老的,可能是误判
629
+ };
630
+ },500);
631
+ };
632
+ };
633
+ var createNode=function(){
634
+ if(!awNext())return;
635
+ var node=stream._n=new AwNode(ctx, RecProc, {
636
+ processorOptions:{bufferSize:bufferSize}
637
+ });
638
+ mediaConn(node);
639
+ node.port.onmessage=function(e){
640
+ if(badInt){
641
+ clearTimeout(badInt);badInt="";
642
+ };
643
+ if(awNext()){
644
+ onReceive(e.data.val, ctxSR);
645
+ }else if(!isWorklet){
646
+ CLog($T("XUap::{1}多余回调",0,audioWorklet),3);
647
+ };
648
+ };
649
+ CLog($T("yOta::Connect采用{1},设置{2}可恢复老式{3}",0,audioWorklet,RecTxt+"."+ConnectEnableWorklet+"=false",scriptProcessor)+webMTips+oldIsBest,3);
650
+ };
651
+
652
+ //如果start时的resume和下面的构造node同时进行,将会导致部分浏览器崩溃 (STATUS_ACCESS_VIOLATION),源码assets中 ztest_chrome_bug_AudioWorkletNode.html 可测试。所以,将所有代码套到resume里面(不管catch),避免出现这个问题
653
+ var ctxOK=function(){
654
+ if(!awNext())return;
655
+ if(ctx[RecProc]){
656
+ createNode();
657
+ return;
658
+ };
659
+ var url=clazzUrl();
660
+ ctx[audioWorklet].addModule(url).then(function(e){
661
+ if(!awNext())return;
662
+ ctx[RecProc]=1;
663
+ createNode();
664
+ if(badInt){//重新计时
665
+ nodeAlive();
666
+ };
667
+ })[CatchTxt](function(e){ //fix 关键字,保证catch压缩时保持字符串形式
668
+ CLog(audioWorklet+".addModule Error",1,e);
669
+ awNext()&&oldScript();
670
+ });
671
+ };
672
+ ResumeCtx(ctx,function(){ return awNext() } ,ctxOK,ctxOK);
673
+ };
674
+
675
+
676
+ //===================连接方式一=========================
677
+ var connWebM=function(){
678
+ //尝试开启MediaRecorder录制webm+pcm处理
679
+ var MR=window[MediaRecorderTxt];
680
+ var onData="ondataavailable";
681
+ var webmType="audio/webm; codecs=pcm";
682
+ isWebM=stream.isWebM=Recorder[ConnectEnableWebM];
683
+
684
+ var supportMR=MR && (onData in MR.prototype) && MR.isTypeSupported(webmType);
685
+ webMTips=supportMR?"":$T("VwPd::(此浏览器不支持{1})",0,MRWebMPCM);
686
+ if(!isWebM || !supportMR){
687
+ connWorklet(); //被禁用 或 不支持MediaRecorder 或 不支持webm+pcm
688
+ return;
689
+ }
690
+
691
+ var mrNext=function(){//可以继续,没有调用断开
692
+ return isWebM && stream._ra;
693
+ };
694
+ stream._ra=function(){
695
+ //start时会调用,只要没有收到数据就断定MediaRecorder有问题,降级处理
696
+ if(badInt!==""){//没有回调过数据
697
+ clearTimeout(badInt);
698
+ badInt=setTimeout(function(){
699
+ //badInt=0; 保留给nodeAlive继续判断
700
+ if(mrNext()){
701
+ CLog($T("vHnb::{1}未返回任何音频,降级使用{2}",0,MediaRecorderTxt,audioWorklet),3);
702
+ connWorklet();
703
+ };
704
+ },500);
705
+ };
706
+ };
707
+
708
+ var mrSet=Object.assign({mimeType:webmType}, Recorder.ConnectWebMOptions);
709
+ var mr=stream._r=new MR(stream, mrSet);
710
+ var webmData=stream._rd={};
711
+ mr[onData]=function(e){
712
+ //提取webm中的pcm数据,提取失败就等着badInt超时降级处理
713
+ var reader=new FileReader();
714
+ reader.onloadend=function(){
715
+ if(mrNext()){
716
+ var f32arr=WebM_Extract(new Uint8Array(reader.result),webmData);
717
+ if(!f32arr)return;
718
+ if(f32arr==-1){//无法提取,立即降级
719
+ connWorklet();
720
+ return;
721
+ };
722
+
723
+ if(badInt){
724
+ clearTimeout(badInt);badInt="";
725
+ };
726
+ onReceive(f32arr, webmData.webmSR);
727
+ }else if(!isWebM){
728
+ CLog($T("O9P7::{1}多余回调",0,MediaRecorderTxt),3);
729
+ };
730
+ };
731
+ reader.readAsArrayBuffer(e.data);
732
+ };
733
+ mr.start(~~(bufferSize/48));//按48k时的回调间隔
734
+ CLog($T("LMEm::Connect采用{1},设置{2}可恢复使用{3}或老式{4}",0,MRWebMPCM,RecTxt+"."+ConnectEnableWebM+"=false",audioWorklet,scriptProcessor));
735
+ };
736
+
737
+ connWebM();
738
+ };
739
+ var ConnAlive=function(stream){
740
+ if(stream._na) stream._na(); //检查AudioWorklet连接是否有效,无效就回滚到老的ScriptProcessor
741
+ if(stream._ra) stream._ra(); //检查MediaRecorder连接是否有效,无效就降级处理
742
+ };
743
+ var _Disconn_n=function(stream){
744
+ stream._na=null;
745
+ if(stream._n){
746
+ stream._n.port.postMessage({kill:true});
747
+ stream._n.disconnect();
748
+ stream._n=null;
749
+ };
750
+ };
751
+ var _Disconn_r=function(stream){
752
+ stream._ra=null;
753
+ if(stream._r){
754
+ try{ stream._r.stop() }catch(e){ CLog("mr stop err",1,e) }
755
+ stream._r=null;
756
+ };
757
+ };
758
+ var Disconnect=function(streamStore){
759
+ streamStore=streamStore||Recorder;
760
+ var isGlobal=streamStore==Recorder;
761
+
762
+ var stream=streamStore.Stream;
763
+ if(stream){
764
+ if(stream._m){
765
+ stream._m.disconnect();
766
+ stream._m=null;
767
+ };
768
+ if(!stream._RC && stream._c){//提供的runningContext不处理
769
+ Recorder.CloseNewCtx(stream._c);
770
+ };
771
+ stream._RC=null; stream._c=null;
772
+ if(stream._d){
773
+ StopS_(stream._d.stream);
774
+ stream._d=null;
775
+ };
776
+ if(stream._p){
777
+ stream._p.disconnect();
778
+ stream._p.onaudioprocess=stream._p=null;
779
+ };
780
+ _Disconn_n(stream);
781
+ _Disconn_r(stream);
782
+
783
+ if(isGlobal){//全局的时候,要把流关掉(麦克风),直接提供的流不处理
784
+ StopS_(stream);
785
+ };
786
+ };
787
+ streamStore.Stream=0;
788
+ };
789
+ //关闭一个音频流
790
+ var StopS_=Recorder.StopS_=function(stream){
791
+ var tracks=Tracks_(stream);
792
+ for(var i=0;i<tracks.length;i++){
793
+ var track=tracks[i];
794
+ track.stop&&track.stop();
795
+ };
796
+ stream.stop&&stream.stop();
797
+ };
798
+ //获取流中的所有轨道
799
+ var Tracks_=function(stream){
800
+ var arr1=0,arr2=0,arr=[];
801
+ //stream.getTracks() 得到的sourceStream还得去排序 不然第一个可能是video
802
+ if(stream.getAudioTracks){ arr1=stream.getAudioTracks(); arr2=stream.getVideoTracks(); }
803
+ if(!arr1){ arr1=stream.audioTracks; arr2=stream.videoTracks; }
804
+ for(var i=0,L=arr1?arr1.length:0;i<L;i++)arr.push(arr1[i]); //音频放前面,方便取[0]
805
+ for(var i=0,L=arr2?arr2.length:0;i<L;i++)arr.push(arr2[i]);
806
+ return arr;
807
+ };
808
+
809
+ /*对pcm数据的采样率进行转换
810
+ pcmDatas: [[Int16,...]] pcm片段列表,二维数组里面是Int16Array,也可传Float32Array(会转成Int16Array)
811
+ pcmSampleRate:48000 pcm数据的采样率
812
+ newSampleRate:16000 需要转换成的采样率,241020版本后支持转成任意采样率,之前老版本newSampleRate>=pcmSampleRate时不会进行任何处理,小于时会进行重新采样
813
+ prevChunkInfo:{} 可选,上次调用时的返回值,用于连续转换,本次调用将从上次结束位置开始进行处理。或可自行定义一个ChunkInfo从pcmDatas指定的位置开始进行转换
814
+ option:{ 可选,配置项
815
+ frameSize:123456 帧大小,每帧的PCM Int16的数量,采样率转换后的pcm长度为frameSize的整数倍,用于连续转换。目前仅在mp3格式时才有用,frameSize取值为1152,这样编码出来的mp3时长和pcm的时长完全一致,否则会因为mp3最后一帧录音不够填满时添加填充数据导致mp3的时长变长。
816
+ frameType:"" 帧类型,一般为rec.set.type,提供此参数时无需提供frameSize,会自动使用最佳的值给frameSize赋值,目前仅支持mp3=1152(MPEG1 Layer3的每帧采采样数),其他类型=1。
817
+ 以上两个参数用于连续转换时使用,最多使用一个,不提供时不进行帧的特殊处理,提供时必须同时提供prevChunkInfo才有作用。最后一段数据处理时无需提供帧大小以便输出最后一丁点残留数据。
818
+ }
819
+
820
+ 返回ChunkInfo:{
821
+ //可定义,从指定位置开始转换到结尾
822
+ index:0 pcmDatas已处理到的索引;比如每次都是单个pcm需要连续处理时,可每次调用前重置成0,pcmDatas仅需传入`[pcm]`固定一个元素
823
+ offset:0.0 已处理到的index对应的pcm中的偏移的下一个位置(提升采样率时为结果的pcm)
824
+ raisePrev:null 提升采样率时的前一个pcm结果采样值
825
+
826
+ //可定义,指定的一个滤波配置:默认使用Recorder.IIRFilter低通滤波(可有效抑制混叠产生的杂音,小采样率大于高采样率的75%时不默认滤波),如果提供了配置但fn为null时将不滤波;sr、srn为此滤波函数对应的初始化采样率,当采样率和参数的不一致时将重新设为默认函数
827
+ filter:null||{fn:fn(sample),sr:pcmSampleRate,srn:newSampleRate}
828
+
829
+ //仅作为返回值
830
+ frameNext:null||[Int16,...] 下一帧的部分数据,frameSize设置了的时候才可能会有
831
+ sampleRate:16000 结果的采样率=newSampleRate,老版本<=newSampleRate
832
+ data:[Int16,...] 转换后的PCM结果;如果是连续转换,并且pcmDatas中并没有新数据时,data的长度可能为0
833
+ }
834
+ */
835
+ Recorder.SampleData=function(pcmDatas,pcmSampleRate,newSampleRate,prevChunkInfo,option){
836
+ var Txt="SampleData";
837
+ prevChunkInfo||(prevChunkInfo={});
838
+ var index=prevChunkInfo.index||0;
839
+ var offset=prevChunkInfo.offset||0;
840
+ var raisePrev=prevChunkInfo.raisePrev||0;
841
+
842
+ var filter=prevChunkInfo.filter;
843
+ if(filter&&filter.fn&&(filter.sr&&filter.sr!=pcmSampleRate || filter.srn&&filter.srn!=newSampleRate)){
844
+ filter=null; CLog($T("d48C::{1}的filter采样率变了,重设滤波",0,Txt),3);
845
+ };
846
+ if(!filter){ //采样率差距比较大才开启低通滤波
847
+ if(newSampleRate<=pcmSampleRate){ //降低采样率或不变,最高频率用新采样率频率的3/4
848
+ var freq=newSampleRate>pcmSampleRate*3/4?0: newSampleRate/2 *3/4;
849
+ filter={fn:freq?Recorder.IIRFilter(true,pcmSampleRate,freq):0};
850
+ }else{ //提升采样率,最高频率用原始采样率频率的3/4
851
+ var freq=pcmSampleRate>newSampleRate*3/4?0: pcmSampleRate/2 *3/4;
852
+ filter={fn:freq?Recorder.IIRFilter(true,newSampleRate,freq):0};
853
+ };
854
+ };
855
+ filter.sr=pcmSampleRate;
856
+ filter.srn=newSampleRate;
857
+ var filterFn=filter.fn;
858
+
859
+ var frameNext=prevChunkInfo.frameNext||[];
860
+ option||(option={});
861
+ var frameSize=option.frameSize||1;
862
+ if(option.frameType){
863
+ frameSize=option.frameType=="mp3"?1152:1;
864
+ };
865
+ var useSum=option._sum, _sum=0; //内部用的,sum不考虑配置了frame
866
+
867
+ var nLen=pcmDatas.length;
868
+ if(index>nLen+1){
869
+ CLog($T("tlbC::{1}似乎传入了未重置chunk {2}",0,Txt,index+">"+nLen),3);
870
+ };
871
+ var size=0;
872
+ for(var i=index;i<nLen;i++){
873
+ size+=pcmDatas[i].length;
874
+ };
875
+
876
+ //采样 https://www.cnblogs.com/blqw/p/3782420.html
877
+ var step=pcmSampleRate/newSampleRate;
878
+ if(step>1){//新采样低于录音采样,进行抽样
879
+ size=Math.max(0,size-Math.floor(offset));
880
+ size=Math.floor(size/step);
881
+ }else if(step<1){//新采样高于录音采样,插值处理
882
+ var raiseStep=1/step;
883
+ size=Math.floor(size*raiseStep);
884
+ };
885
+
886
+ size+=frameNext.length;
887
+ var res=new Int16Array(size);
888
+ var idx=0;
889
+ //添加上一次不够一帧的剩余数据
890
+ for(var i=0;i<frameNext.length;i++){
891
+ res[idx]=frameNext[i];
892
+ idx++;
893
+ };
894
+ //处理数据
895
+ for (;index<nLen;index++) {
896
+ var o=pcmDatas[index], isF32=o instanceof Float32Array;
897
+ var i=offset,il=o.length;
898
+ var F=filterFn&&filterFn.Embed,F1=0,F2=0,Fx=0,Fy=0;//低通滤波后的数据
899
+
900
+ if(step<1){ //提升采样率
901
+ var idx1=idx+i, prev=raisePrev;
902
+ for(var i0=0;i0<il;i0++){
903
+ var oVal=o[i0];
904
+ if(isF32){//floatTo16BitPCM
905
+ oVal=Math.max(-1,Math.min(1,oVal));
906
+ oVal=oVal<0?oVal*0x8000:oVal*0x7FFF;
907
+ }
908
+
909
+ var pos=Math.floor(idx1);
910
+ idx1+=raiseStep;
911
+ var end=Math.floor(idx1);
912
+
913
+ //简单的从prev平滑填充到cur,有效减少转换引入的杂音
914
+ var n=(oVal-prev)/(end-pos);
915
+ for(var j=1;pos<end;pos++,j++){
916
+ var s=Math.floor(prev+(j*n));
917
+ if(F){//IIRFilter代码内置,比函数调用快4倍
918
+ Fx=s;
919
+ Fy=F.b0 * Fx + F.b1 * F.x1 + F.b0 * F.x2 - F.a1 * F.y1 - F.a2 * F.y2;
920
+ F.x2 = F.x1; F.x1 = Fx; F.y2 = F.y1; F.y1 = Fy;
921
+ s=Fy;
922
+ }else{ s=filterFn?filterFn(s):s; }
923
+
924
+ if(s>0x7FFF) s=0x7FFF; else if(s<-0x8000) s=-0x8000; //Int16越界处理
925
+ if(useSum) _sum+=Math.abs(s);
926
+ res[pos]=s;
927
+ idx++;
928
+ };
929
+
930
+ prev=raisePrev=oVal;
931
+ i+=raiseStep;//插值
932
+ }
933
+ offset=i%1;
934
+ continue;
935
+ };
936
+ //降低采样率或不变
937
+ for(var i0=0,i2=0;i0<il;i0++,i2++){
938
+ if(i2<il){
939
+ var oVal=o[i2];
940
+ if(isF32){//floatTo16BitPCM
941
+ oVal=Math.max(-1,Math.min(1,oVal));
942
+ oVal=oVal<0?oVal*0x8000:oVal*0x7FFF;
943
+ }
944
+ if(F){//IIRFilter代码内置,比函数调用快4倍
945
+ Fx=oVal;
946
+ Fy=F.b0 * Fx + F.b1 * F.x1 + F.b0 * F.x2 - F.a1 * F.y1 - F.a2 * F.y2;
947
+ F.x2 = F.x1; F.x1 = Fx; F.y2 = F.y1; F.y1 = Fy;
948
+ }else{ Fy=filterFn?filterFn(oVal):oVal; }
949
+ }
950
+ F1=F2; F2=Fy;
951
+ if(i2==0){ i0--; continue; } //首次只计算o[0]
952
+
953
+ //https://www.cnblogs.com/xiaoqi/p/6993912.html
954
+ //当前点=当前点+到后面一个点之间的增量,音质比直接简单抽样好些
955
+ var before = Math.floor(i);
956
+ if(i0!=before)continue;
957
+ var after = Math.ceil(i);
958
+ var atPoint = i - before;
959
+
960
+ var beforeVal=F1;
961
+ var afterVal=after<il ? F2 : beforeVal; //后个点越界了,忽略不计
962
+ var val=beforeVal+(afterVal-beforeVal)*atPoint;
963
+
964
+ if(val>0x7FFF) val=0x7FFF; else if(val<-0x8000) val=-0x8000; //Int16越界处理
965
+ if(useSum) _sum+=Math.abs(val);
966
+ res[idx]=val;
967
+
968
+ idx++;
969
+ i+=step;//抽样
970
+ };
971
+ offset=Math.max(0, i-il); //不太可能出现负数
972
+ };
973
+ if(step<1 && idx+1==size){ //提升采样率时可能缺1个,直接删除结尾1个
974
+ size--; res=new Int16Array(res.buffer.slice(0, size*2));
975
+ };
976
+ if(idx-1!=size && idx!=size)CLog(Txt+" idx:"+idx+" != size:"+size,3); //越界1个
977
+
978
+ //帧处理
979
+ frameNext=null;
980
+ var frameNextSize=size%frameSize;
981
+ if(frameNextSize>0){
982
+ var u8Pos=(size-frameNextSize)*2;
983
+ frameNext=new Int16Array(res.buffer.slice(u8Pos));
984
+ res=new Int16Array(res.buffer.slice(0,u8Pos));
985
+ };
986
+
987
+ var obj={
988
+ index:index
989
+ ,offset:offset
990
+ ,raisePrev:raisePrev
991
+ ,filter:filter
992
+
993
+ ,frameNext:frameNext
994
+ ,sampleRate:newSampleRate
995
+ ,data:res
996
+ };
997
+ if(useSum) obj._sum=_sum;
998
+ return obj;
999
+ };
1000
+
1001
+ /*IIR低通、高通滤波,移植自:https://gitee.com/52jian/digital-audio-filter AudioFilter.java
1002
+ useLowPass: true或false,true为低通滤波,false为高通滤波
1003
+ sampleRate: 待处理pcm的采样率
1004
+ freq: 截止频率Hz,最大频率为sampleRate/2,低通时会切掉高于此频率的声音,高通时会切掉低于此频率的声音,注意滤波并非100%的切掉不需要的声音,而是减弱频率对应的声音,离截止频率越远对应声音减弱越厉害,离截止频率越近声音就几乎无衰减
1005
+ 返回的是一个函数,用此函数对pcm的每个采样值按顺序进行处理即可(不同pcm不可共用);注意此函数返回值可能会越界超过Int16范围,自行限制一下即可:Math.min(Math.max(val,-0x8000),0x7FFF)
1006
+ 可重新赋值一个函数,来改变Recorder的默认行为,比如SampleData中的低通滤波*/
1007
+ Recorder.IIRFilter=function(useLowPass, sampleRate, freq){
1008
+ var ov = 2 * Math.PI * freq / sampleRate;
1009
+ var sn = Math.sin(ov);
1010
+ var cs = Math.cos(ov);
1011
+ var alpha = sn / 2;
1012
+
1013
+ var a0 = 1 + alpha;
1014
+ var a1 = (-2 * cs) / a0;
1015
+ var a2 = (1 - alpha) / a0;
1016
+ if(useLowPass){
1017
+ var b0 = (1 - cs) / 2 / a0;
1018
+ var b1 = (1 - cs) / a0;
1019
+ }else{
1020
+ var b0 = (1 + cs) / 2 / a0;
1021
+ var b1 = -(1 + cs) / a0;
1022
+ }
1023
+
1024
+ var x1=0,x2=0,y=0,y1=0,y2=0;
1025
+ var fn=function(x){
1026
+ y = b0 * x + b1 * x1 + b0 * x2 - a1 * y1 - a2 * y2;
1027
+ x2 = x1; x1 = x;
1028
+ y2 = y1; y1 = y;
1029
+ return y;
1030
+ };
1031
+ fn.Embed={x1:0,x2:0,y1:0,y2:0,b0:b0,b1:b1,a1:a1,a2:a2};
1032
+ return fn;
1033
+ };
1034
+
1035
+
1036
+ /*计算音量百分比的一个方法
1037
+ pcmAbsSum: pcm Int16所有采样的绝对值的和
1038
+ pcmLength: pcm长度
1039
+ 返回值:0-100,主要当做百分比用
1040
+ 注意:这个不是分贝,因此没用volume当做名称*/
1041
+ Recorder.PowerLevel=function(pcmAbsSum,pcmLength){
1042
+ /*计算音量 https://blog.csdn.net/jody1989/article/details/73480259
1043
+ 更高灵敏度算法:
1044
+ 限定最大感应值10000
1045
+ 线性曲线:低音量不友好
1046
+ power/10000*100
1047
+ 对数曲线:低音量友好,但需限定最低感应值
1048
+ (1+Math.log10(power/10000))*100
1049
+ */
1050
+ var power=(pcmAbsSum/pcmLength) || 0;//NaN
1051
+ var level;
1052
+ if(power<1251){//1250的结果10%,更小的音量采用线性取值
1053
+ level=Math.round(power/1250*10);
1054
+ }else{
1055
+ level=Math.round(Math.min(100,Math.max(0,(1+Math.log(power/10000)/Math.log(10))*100)));
1056
+ };
1057
+ return level;
1058
+ };
1059
+
1060
+ /*计算音量,单位dBFS(满刻度相对电平)
1061
+ maxSample: 为16位pcm采样的绝对值中最大的一个(计算峰值音量),或者为pcm中所有采样的绝对值的平局值
1062
+ 返回值:-100~0 (最大值0dB,最小值-100代替-∞)
1063
+ */
1064
+ Recorder.PowerDBFS=function(maxSample){
1065
+ var val=Math.max(0.1, maxSample||0),Pref=0x7FFF;
1066
+ val=Math.min(val,Pref);
1067
+ //https://www.logiclocmusic.com/can-you-tell-the-decibel/
1068
+ //https://blog.csdn.net/qq_17256689/article/details/120442510
1069
+ val=20*Math.log(val/Pref)/Math.log(10);
1070
+ return Math.max(-100,Math.round(val));
1071
+ };
1072
+
1073
+
1074
+
1075
+
1076
+ //带时间的日志输出,可设为一个空函数来屏蔽日志输出
1077
+ //CLog(msg,errOrLogMsg, logMsg...) err为数字时代表日志类型1:error 2:log默认 3:warn,否则当做内容输出,第一个参数不能是对象因为要拼接时间,后面可以接无数个输出参数
1078
+ Recorder.CLog=function(msg,err){
1079
+ if(typeof console!="object")return;
1080
+ var now=new Date();
1081
+ var t=("0"+now.getMinutes()).substr(-2)
1082
+ +":"+("0"+now.getSeconds()).substr(-2)
1083
+ +"."+("00"+now.getMilliseconds()).substr(-3);
1084
+ var recID=this&&this.envIn&&this.envCheck&&this.id;
1085
+ var arr=["["+t+" "+RecTxt+(recID?":"+recID:"")+"]"+msg];
1086
+ var a=arguments,cwe=Recorder.CLog;
1087
+ var i=2,fn=cwe.log||console.log;
1088
+ if(IsNum(err)){
1089
+ fn=err==1?cwe.error||console.error:err==3?cwe.warn||console.warn:fn;
1090
+ }else{
1091
+ i=1;
1092
+ };
1093
+ for(;i<a.length;i++){
1094
+ arr.push(a[i]);
1095
+ };
1096
+ if(IsLoser){//古董浏览器,仅保证基本的可执行不代码异常
1097
+ fn&&fn("[IsLoser]"+arr[0],arr.length>1?arr:"");
1098
+ }else{
1099
+ fn.apply(console,arr);
1100
+ };
1101
+ };
1102
+ var CLog=function(){ Recorder.CLog.apply(this,arguments); };
1103
+ var IsLoser=true;try{IsLoser=!console.log.apply;}catch(e){};
1104
+
1105
+
1106
+
1107
+
1108
+ var ID=0;
1109
+ function initFn(set){
1110
+ var This=this; This.id=++ID;
1111
+
1112
+ //如果开启了流量统计,这里将发送一个图片请求
1113
+ Traffic();
1114
+
1115
+
1116
+ var o={
1117
+ type:"mp3" //输出类型:mp3,wav,wav输出文件尺寸超大不推荐使用,但mp3编码支持会导致js文件超大,如果不需支持mp3可以使js文件大幅减小
1118
+ //,bitRate:16 //比特率 wav:16或8位,MP3:8kbps 1k/s,8kbps 2k/s 录音文件很小
1119
+
1120
+ //,sampleRate:16000 //采样率,wav格式大小=sampleRate*时间;mp3此项对低比特率有影响,高比特率几乎无影响。
1121
+ //wav任意值,mp3取值范围:48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000
1122
+ //采样率参考https://www.cnblogs.com/devin87/p/mp3-recorder.html
1123
+
1124
+ ,onProcess:NOOP //fn(buffers,powerLevel,bufferDuration,bufferSampleRate,newBufferIdx,asyncEnd) buffers=[[Int16,...],...]:缓冲的PCM数据,为从开始录音到现在的所有pcm片段;powerLevel:当前缓冲的音量级别0-100,bufferDuration:已缓冲时长,bufferSampleRate:缓冲使用的采样率(当type支持边录边转码(Worker)时,此采样率和设置的采样率相同,否则不一定相同);newBufferIdx:本次回调新增的buffer起始索引;asyncEnd:fn() 如果onProcess是异步的(返回值为true时),处理完成时需要调用此回调,如果不是异步的请忽略此参数,此方法回调时必须是真异步(不能真异步时需用setTimeout包裹)。onProcess返回值:如果返回true代表开启异步模式,在某些大量运算的场合异步是必须的,必须在异步处理完成时调用asyncEnd(不能真异步时需用setTimeout包裹),在onProcess执行后新增的buffer会全部替换成空数组,因此本回调开头应立即将newBufferIdx到本次回调结尾位置的buffer全部保存到另外一个数组内,处理完成后写回buffers中本次回调的结尾位置。
1125
+
1126
+ //*******高级设置******
1127
+ //,sourceStream:MediaStream Object
1128
+ //可选直接提供一个媒体流,从这个流中录制、实时处理音频数据(当前Recorder实例独享此流);不提供时为普通的麦克风录音,由getUserMedia提供音频流(所有Recorder实例共享同一个流)
1129
+ //比如:audio、video标签dom节点的captureStream方法(实验特性,不同浏览器支持程度不高)返回的流;WebRTC中的remote流;自己创建的流等
1130
+ //注意:流内必须至少存在一条音轨(Audio Track),比如audio标签必须等待到可以开始播放后才会有音轨,否则open会失败
1131
+
1132
+ //,runningContext:AudioContext
1133
+ //可选提供一个state为running状态的AudioContext对象(ctx);默认会在rec.open时自动创建一个新的ctx,无用户操作(触摸、点击等)时调用rec.open的ctx.state可能为suspended,会在rec.start时尝试进行ctx.resume,如果也无用户操作ctx.resume可能不会恢复成running状态(目前仅iOS上有此兼容性问题),导致无法去读取媒体流,这时请提前在用户操作时调用Recorder.GetContext(true)来得到一个running状态AudioContext(用完需调用CloseNewCtx(ctx)关闭)
1134
+
1135
+ //,audioTrackSet:{ deviceId:"",groupId:"", autoGainControl:true, echoCancellation:true, noiseSuppression:true }
1136
+ //普通麦克风录音时getUserMedia方法的audio配置参数,比如指定设备id,回声消除、降噪开关;注意:提供的任何配置值都不一定会生效
1137
+ //由于麦克风是全局共享的,所以新配置后需要close掉以前的再重新open
1138
+ //同样可配置videoTrackSet,更多参考: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
1139
+
1140
+ //,disableEnvInFix:false 内部参数,禁用设备卡顿时音频输入丢失补偿功能
1141
+
1142
+ //,takeoffEncodeChunk:NOOP //fn(chunkBytes) chunkBytes=[Uint8,...]:实时编码环境下接管编码器输出,当编码器实时编码出一块有效的二进制音频数据时实时回调此方法;参数为二进制的Uint8Array,就是编码出来的音频数据片段,所有的chunkBytes拼接在一起即为完整音频。本实现的想法最初由QQ2543775048提出
1143
+ //当提供此回调方法时,将接管编码器的数据输出,编码器内部将放弃存储生成的音频数据;如果当前编码器或环境不支持实时编码处理,将在open时直接走fail逻辑
1144
+ //因此提供此回调后调用stop方法将无法获得有效的音频数据,因为编码器内没有音频数据,因此stop时返回的blob将是一个字节长度为0的blob
1145
+ //大部分录音格式编码器都支持实时编码(边录边转码),比如mp3格式:会实时的将编码出来的mp3片段通过此方法回调,所有的chunkBytes拼接到一起即为完整的mp3,此种拼接的结果比mock方法实时生成的音质更加,因为天然避免了首尾的静默
1146
+ //不支持实时编码的录音格式不可以提供此回调(wav格式不支持,因为wav文件头中需要提供文件最终长度),提供了将在open时直接走fail逻辑
1147
+ };
1148
+
1149
+ for(var k in set){
1150
+ o[k]=set[k];
1151
+ };
1152
+ This.set=o;
1153
+
1154
+ var vB=o[bitRateTxt],vS=o[sampleRateTxt]; //校验配置参数
1155
+ if(vB&&!IsNum(vB) || vS&&!IsNum(vS)){
1156
+ This.CLog($T.G("IllegalArgs-1",[$T("VtS4::{1}和{2}必须是数值",0,sampleRateTxt,bitRateTxt)]),1,set);
1157
+ };
1158
+ o[bitRateTxt]=+vB||16;
1159
+ o[sampleRateTxt]=+vS||16000;
1160
+
1161
+ This.state=0;//运行状态,0未录音 1录音中 2暂停 3等待ctx激活
1162
+ This._S=9;//stop同步锁,stop可以阻止open过程中还未运行的start
1163
+ This.Sync={O:9,C:9};//和Recorder.Sync一致,只不过这个是非全局的,仅用来简化代码逻辑,无实际作用
1164
+ };
1165
+ //同步锁,控制对Stream的竞争;用于close时中断异步的open;一个对象open如果变化了都要阻止close,Stream的控制权交个新的对象
1166
+ Recorder.Sync={/*open*/O:9,/*close*/C:9};
1167
+
1168
+ Recorder.prototype=initFn.prototype={
1169
+ CLog:CLog
1170
+
1171
+ //流相关的数据存储在哪个对象里面;如果提供了sourceStream,数据直接存储在当前对象中,否则存储在全局
1172
+ ,_streamStore:function(){
1173
+ if(this.set.sourceStream){
1174
+ return this;
1175
+ }else{
1176
+ return Recorder;
1177
+ }
1178
+ }
1179
+ //当前实例用到的Stream,可能是全局的,也可能是独享的
1180
+ ,_streamGet:function(){
1181
+ return this._streamStore().Stream;
1182
+ }
1183
+ //当前实例用到的AudioContext,可能是全局的,也可能是独享的
1184
+ ,_streamCtx:function(){
1185
+ var m=this._streamGet();
1186
+ return m&&m._c;
1187
+ }
1188
+
1189
+ //打开录音资源True(),False(msg,isUserNotAllow),需要调用close。注意:此方法是异步的;一般使用时打开,用完立即关闭;可重复调用,可用来测试是否能录音;open和start至少有一个应当在用户操作(触摸、点击等)下进行调用,原因参考runningContext配置
1190
+ ,open:function(True,False){
1191
+ var This=this,set=This.set,streamStore=This._streamStore(),newCtx=0;
1192
+ True=True||NOOP;
1193
+ var failCall=function(errMsg,isUserNotAllow){
1194
+ isUserNotAllow=!!isUserNotAllow;
1195
+ This.CLog($T("5tWi::录音open失败:")+errMsg+",isUserNotAllow:"+isUserNotAllow,1);
1196
+ if(newCtx)Recorder.CloseNewCtx(newCtx);
1197
+ False&&False(errMsg,isUserNotAllow);
1198
+ };
1199
+
1200
+ This._streamTag=getUserMediaTxt;
1201
+ var ok=function(){
1202
+ This.CLog("open ok, id:"+This.id+" stream:"+This._streamTag);
1203
+ True();
1204
+
1205
+ This._SO=0;//解除stop对open中的start调用的阻止
1206
+ };
1207
+
1208
+
1209
+ //同步锁
1210
+ var Lock=streamStore.Sync;
1211
+ var lockOpen=++Lock.O,lockClose=Lock.C;
1212
+ This._O=This._O_=lockOpen;//记住当前的open,如果变化了要阻止close,这里假定了新对象已取代当前对象并且不再使用
1213
+ This._SO=This._S;//记住open过程中的stop,中途任何stop调用后都不能继续open中的start
1214
+ var lockFail=function(){
1215
+ //允许多次open,但不允许任何一次close,或者自身已经调用了关闭
1216
+ if(lockClose!=Lock.C || !This._O){
1217
+ var err=$T("dFm8::open被取消");
1218
+ if(lockOpen==Lock.O){
1219
+ //无新的open,已经调用了close进行取消,此处应让上次的close明确生效
1220
+ This.close();
1221
+ }else{
1222
+ err=$T("VtJO::open被中断");
1223
+ };
1224
+ failCall(err);
1225
+ return true;
1226
+ };
1227
+ };
1228
+
1229
+ //环境配置检查
1230
+ if(!isBrowser){
1231
+ failCall($T.G("NonBrowser-1",["open"])+$T("EMJq::,可尝试使用RecordApp解决方案")+"("+GitUrl+"/tree/master/app-support-sample)");
1232
+ return;
1233
+ };
1234
+ var checkMsg=This.envCheck({envName:"H5",canProcess:true});
1235
+ if(checkMsg){
1236
+ failCall($T("A5bm::不能录音:")+checkMsg);
1237
+ return;
1238
+ };
1239
+
1240
+ //尽量先创建好ctx,不然异步下创建可能不是running状态
1241
+ var ctx;
1242
+ var getCtx=function(){
1243
+ ctx=set.runningContext;
1244
+ if(!ctx)ctx=newCtx=Recorder.GetContext(true); //2023-06 尽量创建新的ctx,免得Safari再次连接无回调
1245
+ };
1246
+
1247
+ //***********已直接提供了音频流************
1248
+ if(set.sourceStream){
1249
+ This._streamTag="set.sourceStream";
1250
+ if(!Recorder.GetContext()){
1251
+ failCall($T("1iU7::不支持此浏览器从流中获取录音"));
1252
+ return;
1253
+ };
1254
+ getCtx();
1255
+
1256
+ Disconnect(streamStore);//可能已open过,直接先尝试断开
1257
+ var stream=This.Stream=set.sourceStream;
1258
+ stream._c=ctx;
1259
+ stream._RC=set.runningContext;
1260
+ stream._call={};
1261
+
1262
+ try{
1263
+ Connect(streamStore);
1264
+ }catch(e){
1265
+ Disconnect(streamStore);
1266
+ failCall($T("BTW2::从流中打开录音失败:")+e.message);
1267
+ return;
1268
+ }
1269
+ ok();
1270
+ return;
1271
+ };
1272
+
1273
+
1274
+ //***********打开麦克风得到全局的音频流************
1275
+ var codeFail=function(code,msg){
1276
+ try{//跨域的优先检测一下
1277
+ window.top.a;
1278
+ }catch(e){
1279
+ failCall($T("Nclz::无权录音(跨域,请尝试给iframe添加麦克风访问策略,如{1})",0,'allow="camera;microphone"'));
1280
+ return;
1281
+ };
1282
+
1283
+ if(codeErr1(1,code)){
1284
+ if(/Found/i.test(code)){//可能是非安全环境导致的没有设备
1285
+ failCall(msg+$T("jBa9::,无可用麦克风"));
1286
+ }else{
1287
+ failCall(msg);
1288
+ };
1289
+ };
1290
+ };
1291
+ var codeErr1=function(call,code){ //排除几个明确原因的错误
1292
+ if(/Permission|Allow/i.test(code)){
1293
+ if(call) failCall($T("gyO5::用户拒绝了录音权限"),true);
1294
+ }else if(window.isSecureContext===false){
1295
+ if(call) failCall($T("oWNo::浏览器禁止不安全页面录音,可开启https解决"));
1296
+ }else{
1297
+ return 1;
1298
+ };
1299
+ };
1300
+
1301
+
1302
+ //如果已打开并且有效就不要再打开了
1303
+ if(Recorder.IsOpen()){
1304
+ ok();
1305
+ return;
1306
+ };
1307
+ if(!Recorder.Support()){
1308
+ codeFail("",$T("COxc::此浏览器不支持录音"));
1309
+ return;
1310
+ };
1311
+ getCtx();
1312
+
1313
+ //请求权限,如果从未授权,一般浏览器会弹出权限请求弹框
1314
+ var f1=function(stream){ //请求成功回调
1315
+ //https://github.com/xiangyuecn/Recorder/issues/14 获取到的track.readyState!="live",刚刚回调时可能是正常的,但过一下可能就被关掉了,原因不明。延迟一下保证真异步。对正常浏览器不影响
1316
+ setTimeout(function(){
1317
+ stream._call={};
1318
+ var oldStream=Recorder.Stream;
1319
+ if(oldStream){
1320
+ Disconnect(); //直接断开已存在的,旧的Connect未完成会自动终止
1321
+ stream._call=oldStream._call;
1322
+ };
1323
+ Recorder.Stream=stream;
1324
+ stream._c=ctx;
1325
+ stream._RC=set.runningContext;
1326
+ if(lockFail())return;
1327
+
1328
+ if(Recorder.IsOpen()){
1329
+ if(oldStream)This.CLog($T("upb8::发现同时多次调用open"),1);
1330
+
1331
+ Connect(streamStore);
1332
+ ok(); //只连接,因为AudioContext不一定在运行,无法知道是否有数据回调
1333
+ }else{
1334
+ failCall($T("Q1GA::录音功能无效:无音频流"));
1335
+ };
1336
+ },100);
1337
+ };
1338
+ var f2=function(e){ //请求失败回调
1339
+ var code=e.name||e.message||e.code+":"+e;
1340
+ var tryMsg="";
1341
+ if(callUmCount==1 && codeErr1(0,code)){
1342
+ tryMsg=$T("KxE2::,将尝试禁用回声消除后重试");
1343
+ }
1344
+ This.CLog($T("xEQR::请求录音权限错误")+tryMsg+"|"+e,tryMsg?3:1,e);
1345
+
1346
+ if(tryMsg){//重试
1347
+ callUserMedia(1);
1348
+ }else{
1349
+ codeFail(code,$T("bDOG::无法录音:")+e);
1350
+ };
1351
+ };
1352
+
1353
+ var callUmCount=0;
1354
+ var callUserMedia=function(retry){
1355
+ callUmCount++;
1356
+ var atsTxt="audioTrackSet";
1357
+ var t_AGC="autoGainControl",t_AEC="echoCancellation",t_ANS="noiseSuppression";
1358
+ var atsTxtJs=atsTxt+":{"+t_AEC+","+t_ANS+","+t_AGC+"}";
1359
+ var trackSet=JSON.parse(ToJson(set[atsTxt]||true)); //true 跟 {} 兼容性?
1360
+ This.CLog("open... "+callUmCount+" "+atsTxt+":"+ToJson(trackSet));
1361
+
1362
+ if(retry){ //回声消除有些浏览器可能导致无法打开录音,尝试明确禁用来保证能最基础的录
1363
+ if(typeof(trackSet)!="object")trackSet={}; //默认true
1364
+ trackSet[t_AGC]=false;
1365
+ trackSet[t_AEC]=false;
1366
+ trackSet[t_ANS]=false;
1367
+ };
1368
+ //这里指明采样率,虽然可以解决手机上MediaRecorder采样率16k的问题,是回声消除导致的只能获取到16k的流,禁用回声消除可恢复48k。(issues#230)而且会导致乱用音频输入设备,MediaStreamTrack的applyConstraints也无法修改采样率
1369
+ //trackSet[sampleRateTxt]=ctx[sampleRateTxt];
1370
+ if(trackSet[sampleRateTxt]){
1371
+ This.CLog($T("IjL3::注意:已配置{1}参数,可能会出现浏览器不能正确选用麦克风、移动端无法启用回声消除等现象",0,atsTxt+"."+sampleRateTxt),3);
1372
+ };
1373
+
1374
+ var mSet={audio:trackSet, video:set.videoTrackSet||false};
1375
+ try{
1376
+ var pro=Recorder.Scope[getUserMediaTxt](mSet,f1,f2);
1377
+ }catch(e){//不能设置trackSet就算了
1378
+ This.CLog(getUserMediaTxt,3,e);
1379
+ mSet={audio:true, video:false};
1380
+ pro=Recorder.Scope[getUserMediaTxt](mSet,f1,f2);
1381
+ };
1382
+ This.CLog(getUserMediaTxt+"("+ToJson(mSet)+") "+CtxState(ctx)
1383
+ +$T("RiWe::,未配置 {1} 时浏览器可能会自动启用回声消除,移动端未禁用回声消除时可能会降低系统播放音量(关闭录音后可恢复)和仅提供16k采样率的音频流(不需要回声消除时可明确配置成禁用来获得48k高音质的流),请参阅文档中{2}配置",0,atsTxtJs,atsTxt)
1384
+ +"("+GitUrl+") LM:"+LM+" UA:"+navigator.userAgent);
1385
+ if(pro&&pro.then){
1386
+ pro.then(f1)[CatchTxt](f2); //fix 关键字,保证catch压缩时保持字符串形式
1387
+ };
1388
+ };
1389
+ callUserMedia();
1390
+ }
1391
+ //关闭释放录音资源
1392
+ ,close:function(call){
1393
+ call=call||NOOP;
1394
+
1395
+ var This=this,streamStore=This._streamStore();
1396
+ This._stop();
1397
+ var sTag=" stream:"+This._streamTag;
1398
+
1399
+ var Lock=streamStore.Sync;
1400
+ This._O=0;
1401
+ if(This._O_!=Lock.O){
1402
+ //唯一资源Stream的控制权已交给新对象,这里不能关闭。此处在每次都弹权限的浏览器内可能存在泄漏,新对象被拒绝权限可能不会调用close,忽略这种不处理
1403
+ This.CLog($T("hWVz::close被忽略(因为同时open了多个rec,只有最后一个会真正close)")+sTag,3);
1404
+ call();
1405
+ return;
1406
+ };
1407
+ Lock.C++;//获得控制权
1408
+
1409
+ Disconnect(streamStore);
1410
+
1411
+ This.CLog("close,"+sTag);
1412
+ call();
1413
+ }
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+ /*模拟一段录音数据,后面可以调用stop进行编码,需提供pcm数据[1,2,3...],pcm的采样率*/
1420
+ ,mock:function(pcmData,pcmSampleRate){
1421
+ var This=this;
1422
+ This._stop();//清理掉已有的资源
1423
+
1424
+ This.isMock=1;
1425
+ This.mockEnvInfo=null;
1426
+ This.buffers=[pcmData];
1427
+ This.recSize=pcmData.length;
1428
+ This._setSrcSR(pcmSampleRate);
1429
+ This._streamTag="mock";
1430
+ return This;
1431
+ }
1432
+ ,_setSrcSR:function(sampleRate){
1433
+ var This=this,set=This.set;
1434
+ var setSr=set[sampleRateTxt];
1435
+ if(setSr>sampleRate){
1436
+ set[sampleRateTxt]=sampleRate;
1437
+ }else{ setSr=0 }
1438
+ This[srcSampleRateTxt]=sampleRate;
1439
+ This.CLog(srcSampleRateTxt+": "+sampleRate+" set."+sampleRateTxt+": "+set[sampleRateTxt]+(setSr?" "+$T("UHvm::忽略")+": "+setSr:""), setSr?3:0);
1440
+ }
1441
+ ,envCheck:function(envInfo){//平台环境下的可用性检查,任何时候都可以调用检查,返回errMsg:""正常,"失败原因"
1442
+ //envInfo={envName:"H5",canProcess:true}
1443
+ var errMsg,This=this,set=This.set;
1444
+
1445
+ //检测CPU的数字字节序,TypedArray字节序是个迷,直接拒绝罕见的大端模式,因为找不到这种CPU进行测试
1446
+ var tag="CPU_BE";
1447
+ if(!errMsg && !Recorder[tag] && typeof Int8Array=="function" && !new Int8Array(new Int32Array([1]).buffer)[0]){
1448
+ Traffic(tag); //如果开启了流量统计,这里将发送一个图片请求
1449
+ errMsg=$T("Essp::不支持{1}架构",0,tag);
1450
+ };
1451
+
1452
+ //编码器检查环境下配置是否可用
1453
+ if(!errMsg){
1454
+ var type=set.type,hasFn=This[type+"_envCheck"];
1455
+ if(set.takeoffEncodeChunk){//需要实时编码返回数据,此时需要检查环境是否有实时特性、和是否可实时编码
1456
+ if(!hasFn){
1457
+ errMsg=$T("2XBl::{1}类型不支持设置takeoffEncodeChunk",0,type)+(This[type]?"":$T("LG7e::(未加载编码器)"));
1458
+ }else if(!envInfo.canProcess){
1459
+ errMsg=$T("7uMV::{1}环境不支持实时处理",0,envInfo.envName);
1460
+ };
1461
+ };
1462
+
1463
+ if(!errMsg && hasFn){//编码器已实现环境检查
1464
+ errMsg=This[type+"_envCheck"](envInfo,set);
1465
+ };
1466
+ };
1467
+
1468
+ return errMsg||"";
1469
+ }
1470
+ ,envStart:function(mockEnvInfo,sampleRate){//平台环境相关的start调用
1471
+ var This=this,set=This.set;
1472
+ This.isMock=mockEnvInfo?1:0;//非H5环境需要启用mock,并提供envCheck需要的环境信息
1473
+ This.mockEnvInfo=mockEnvInfo;
1474
+ This.buffers=[];//数据缓冲
1475
+ This.recSize=0;//数据大小
1476
+ if(mockEnvInfo){
1477
+ This._streamTag="env$"+mockEnvInfo.envName;
1478
+ };
1479
+
1480
+ This.state=1;//运行状态,0未录音 1录音中 2暂停 3等待ctx激活
1481
+ This.envInLast=0;//envIn接收到最后录音内容的时间
1482
+ This.envInFirst=0;//envIn接收到的首个录音内容的录制时间
1483
+ This.envInFix=0;//补偿的总时间
1484
+ This.envInFixTs=[];//补偿计数列表
1485
+
1486
+ //engineCtx需要提前确定最终的采样率
1487
+ This._setSrcSR(sampleRate);
1488
+
1489
+ This.engineCtx=0;
1490
+ //此类型有边录边转码(Worker)支持
1491
+ if(This[set.type+"_start"]){
1492
+ var engineCtx=This.engineCtx=This[set.type+"_start"](set);
1493
+ if(engineCtx){
1494
+ engineCtx.pcmDatas=[];
1495
+ engineCtx.pcmSize=0;
1496
+ };
1497
+ };
1498
+ }
1499
+ ,envResume:function(){//和平台环境无关的恢复录音
1500
+ //重新开始计数
1501
+ this.envInFixTs=[];
1502
+ }
1503
+ ,envIn:function(pcm,sum){//和平台环境无关的pcm[Int16]输入
1504
+ var This=this,set=This.set,engineCtx=This.engineCtx;
1505
+ if(This.state!=1){
1506
+ if(!This.state)This.CLog("envIn at state=0",3);
1507
+ return;
1508
+ };
1509
+ var bufferSampleRate=This[srcSampleRateTxt];
1510
+ var size=pcm.length;
1511
+ var powerLevel=Recorder.PowerLevel(sum,size);
1512
+
1513
+ var buffers=This.buffers;
1514
+ var bufferFirstIdx=buffers.length;//之前的buffer都是经过onProcess处理好的,不允许再修改
1515
+ buffers.push(pcm);
1516
+
1517
+ //有engineCtx时会被覆盖,这里保存一份
1518
+ var buffersThis=buffers;
1519
+ var bufferFirstIdxThis=bufferFirstIdx;
1520
+
1521
+ //卡顿丢失补偿:因为设备很卡的时候导致H5接收到的数据量不够造成播放时候变速,结果比实际的时长要短,此处保证了不会变短,但不能修复丢失的音频数据造成音质变差。当前算法采用输入时间侦测下一帧是否需要添加补偿帧,需要(6次输入||超过1秒)以上才会开始侦测,如果滑动窗口内丢失超过1/3就会进行补偿
1522
+ var now=Date.now();
1523
+ var pcmTime=Math.round(size/bufferSampleRate*1000);
1524
+ This.envInLast=now;
1525
+ if(This.buffers.length==1){//记下首个录音数据的录制时间
1526
+ This.envInFirst=now-pcmTime;
1527
+ };
1528
+ var envInFixTs=This.envInFixTs;
1529
+ envInFixTs.splice(0,0,{t:now,d:pcmTime});
1530
+ //保留3秒的计数滑动窗口,另外超过3秒的停顿不补偿
1531
+ var tsInStart=now,tsPcm=0;
1532
+ for(var i=0;i<envInFixTs.length;i++){
1533
+ var o=envInFixTs[i];
1534
+ if(now-o.t>3000){
1535
+ envInFixTs.length=i;
1536
+ break;
1537
+ };
1538
+ tsInStart=o.t;
1539
+ tsPcm+=o.d;
1540
+ };
1541
+ //达到需要的数据量,开始侦测是否需要补偿
1542
+ var tsInPrev=envInFixTs[1];
1543
+ var tsIn=now-tsInStart;
1544
+ var lost=tsIn-tsPcm;
1545
+ if( lost>tsIn/3 && (tsInPrev&&tsIn>1000 || envInFixTs.length>=6) ){
1546
+ //丢失过多,开始执行补偿
1547
+ var addTime=now-tsInPrev.t-pcmTime;//距离上次输入丢失这么多ms
1548
+ if(addTime>pcmTime/5){//丢失超过本帧的1/5
1549
+ var fixOpen=!set.disableEnvInFix;
1550
+ This.CLog("["+now+"]"+i18n.get(fixOpen?$T("4Kfd::补偿{1}ms",1):$T("bM5i::未补偿{1}ms",1),[addTime]),3);
1551
+ This.envInFix+=addTime;
1552
+
1553
+ //用静默进行补偿
1554
+ if(fixOpen){
1555
+ var addPcm=new Int16Array(addTime*bufferSampleRate/1000);
1556
+ size+=addPcm.length;
1557
+ buffers.push(addPcm);
1558
+ };
1559
+ };
1560
+ };
1561
+
1562
+
1563
+ var sizeOld=This.recSize,addSize=size;
1564
+ var bufferSize=sizeOld+addSize;
1565
+ This.recSize=bufferSize;//此值在onProcess后需要修正,可能新数据被修改
1566
+
1567
+
1568
+ //此类型有边录边转码(Worker)支持,开启实时转码
1569
+ if(engineCtx){
1570
+ //转换成set的采样率
1571
+ var chunkInfo=Recorder.SampleData(buffers,bufferSampleRate,set[sampleRateTxt],engineCtx.chunkInfo);
1572
+ engineCtx.chunkInfo=chunkInfo;
1573
+
1574
+ sizeOld=engineCtx.pcmSize;
1575
+ addSize=chunkInfo.data.length;
1576
+ bufferSize=sizeOld+addSize;
1577
+ engineCtx.pcmSize=bufferSize;//此值在onProcess后需要修正,可能新数据被修改
1578
+
1579
+ buffers=engineCtx.pcmDatas;
1580
+ bufferFirstIdx=buffers.length;
1581
+ buffers.push(chunkInfo.data);
1582
+ bufferSampleRate=chunkInfo[sampleRateTxt];
1583
+ };
1584
+
1585
+ var duration=Math.round(bufferSize/bufferSampleRate*1000);
1586
+ var bufferNextIdx=buffers.length;
1587
+ var bufferNextIdxThis=buffersThis.length;
1588
+
1589
+ //允许异步处理buffer数据
1590
+ var asyncEnd=function(){
1591
+ //重新计算size,异步的早已减去添加的,同步的需去掉本次添加的然后重新计算
1592
+ var num=asyncBegin?0:-addSize;
1593
+ var hasClear=buffers[0]==null;
1594
+ for(var i=bufferFirstIdx;i<bufferNextIdx;i++){
1595
+ var buffer=buffers[i];
1596
+ if(buffer==null){//已被主动释放内存,比如长时间实时传输录音时
1597
+ hasClear=1;
1598
+ }else{
1599
+ num+=buffer.length;
1600
+
1601
+ //推入后台边录边转码
1602
+ if(engineCtx&&buffer.length){
1603
+ This[set.type+"_encode"](engineCtx,buffer);
1604
+ };
1605
+ };
1606
+ };
1607
+
1608
+ //同步清理This.buffers,不管buffers到底清了多少个,buffersThis是使用不到的进行全清
1609
+ if(hasClear && engineCtx){
1610
+ var i=bufferFirstIdxThis;
1611
+ if(buffersThis[0]){
1612
+ i=0;
1613
+ };
1614
+ for(;i<bufferNextIdxThis;i++){
1615
+ buffersThis[i]=null;
1616
+ };
1617
+ };
1618
+
1619
+ //统计修改后的size,如果异步发生clear要原样加回来,同步的无需操作
1620
+ if(hasClear){
1621
+ num=asyncBegin?addSize:0;
1622
+
1623
+ buffers[0]=null;//彻底被清理
1624
+ };
1625
+ if(engineCtx){
1626
+ engineCtx.pcmSize+=num;
1627
+ }else{
1628
+ This.recSize+=num;
1629
+ };
1630
+ };
1631
+ //实时回调处理数据,允许修改或替换上次回调以来新增的数据 ,但是不允许修改已处理过的,不允许增删第一维数组 ,允许将第二维数组任意修改替换成空数组也可以
1632
+ var asyncBegin=0,procTxt="rec.set.onProcess";
1633
+ try{
1634
+ asyncBegin=set.onProcess(buffers,powerLevel,duration,bufferSampleRate,bufferFirstIdx,asyncEnd);
1635
+ }catch(e){
1636
+ //此错误显示不要用CLog,这样控制台内相同内容不会重复打印
1637
+ console.error(procTxt+$T("gFUF::回调出错是不允许的,需保证不会抛异常"),e);
1638
+ };
1639
+
1640
+ var slowT=Date.now()-now;
1641
+ if(slowT>10 && This.envInFirst-now>1000){ //1秒后开始onProcess性能监测
1642
+ This.CLog(procTxt+$T("2ghS::低性能,耗时{1}ms",0,slowT),3);
1643
+ };
1644
+
1645
+ if(asyncBegin===true){
1646
+ //开启了异步模式,onProcess已接管buffers新数据,立即清空,避免出现未处理的数据
1647
+ var hasClear=0;
1648
+ for(var i=bufferFirstIdx;i<bufferNextIdx;i++){
1649
+ if(buffers[i]==null){//已被主动释放内存,比如长时间实时传输录音时 ,但又要开启异步模式,此种情况是非法的
1650
+ hasClear=1;
1651
+ }else{
1652
+ buffers[i]=new Int16Array(0);
1653
+ };
1654
+ };
1655
+
1656
+ if(hasClear){
1657
+ This.CLog($T("ufqH::未进入异步前不能清除buffers"),3);
1658
+ }else{
1659
+ //还原size,异步结束后再统计仅修改后的size,如果发生clear要原样加回来
1660
+ if(engineCtx){
1661
+ engineCtx.pcmSize-=addSize;
1662
+ }else{
1663
+ This.recSize-=addSize;
1664
+ };
1665
+ };
1666
+ }else{
1667
+ asyncEnd();
1668
+ };
1669
+ }
1670
+
1671
+
1672
+
1673
+
1674
+ //开始录音,需先调用open;只要open成功时,调用此方法是安全的,如果未open强行调用导致的内部错误将不会有任何提示,stop时自然能得到错误;注意:open和start至少有一个应当在用户操作(触摸、点击等)下进行调用,原因参考runningContext配置
1675
+ ,start:function(){
1676
+ var This=this;
1677
+
1678
+ var isOpen=1;
1679
+ if(This.set.sourceStream){//直接提供了流,仅判断是否调用了open
1680
+ if(!This.Stream){
1681
+ isOpen=0;
1682
+ }
1683
+ }else if(!Recorder.IsOpen()){//监测全局麦克风是否打开并且有效
1684
+ isOpen=0;
1685
+ };
1686
+ if(!isOpen){
1687
+ This.CLog($T("6WmN::start失败:未open"),1);
1688
+ return;
1689
+ };
1690
+ var ctx=This._streamCtx();
1691
+ This.CLog($T("kLDN::start 开始录音,")+CtxState(ctx)+" stream:"+This._streamTag);
1692
+
1693
+ This._stop();
1694
+ This.envStart(null, ctx[sampleRateTxt]);
1695
+ This.state=3;//0未录音 1录音中 2暂停 3等待ctx激活
1696
+
1697
+ //检查open过程中stop是否已经调用过
1698
+ if(This._SO&&This._SO+1!=This._S){//上面调用过一次 _stop
1699
+ //open未完成就调用了stop,此种情况终止start。也应尽量避免出现此情况
1700
+ This.CLog($T("Bp2y::start被中断"),3);
1701
+ return;
1702
+ };
1703
+ This._SO=0;
1704
+
1705
+ var end=function(){
1706
+ if(This.state==3){
1707
+ This.state=1;
1708
+ This.resume();
1709
+ }
1710
+ };
1711
+ var tag="AudioContext resume: ";
1712
+
1713
+ //如果有数据回调,就不等待ctx resume
1714
+ var stream=This._streamGet();
1715
+ stream._call[This.id]=function(){
1716
+ This.CLog(tag+ctx.state+'|stream ok');
1717
+ end();
1718
+ };
1719
+ ResumeCtx(ctx,function(runC){
1720
+ runC&&This.CLog(tag+"wait...");
1721
+ return This.state==3;
1722
+ },function(runC){
1723
+ runC&&This.CLog(tag+ctx.state);
1724
+ end();
1725
+ },function(err){ //比较少见,可能对录音没有影响
1726
+ This.CLog(tag+ctx.state+$T("upkE::,可能无法录音:")+err,1);
1727
+ end();
1728
+ });
1729
+ }
1730
+
1731
+
1732
+
1733
+ /*暂停录音*/
1734
+ ,pause:function(){
1735
+ var This=this,stream=This._streamGet();
1736
+ if(This.state){
1737
+ This.state=2;
1738
+ This.CLog("pause");
1739
+ if(stream) delete stream._call[This.id];
1740
+ };
1741
+ }
1742
+ /*恢复录音*/
1743
+ ,resume:function(){
1744
+ var This=this,stream=This._streamGet();
1745
+ var tag="resume",tag3=tag+"(wait ctx)";
1746
+ if(This.state==3){ //start还在等ctx恢复
1747
+ This.CLog(tag3);
1748
+ }else if(This.state){
1749
+ This.state=1;
1750
+ This.CLog(tag);
1751
+ This.envResume();
1752
+
1753
+ if(stream){
1754
+ stream._call[This.id]=function(pcm,sum){
1755
+ if(This.state==1){
1756
+ This.envIn(pcm,sum);
1757
+ };
1758
+ };
1759
+ ConnAlive(stream);//AudioWorklet只会在ctx激活后运行
1760
+ };
1761
+
1762
+ var ctx=This._streamCtx();
1763
+ if(ctx){ //AudioContext如果被暂停,尽量恢复
1764
+ ResumeCtx(ctx,function(runC){
1765
+ runC&&This.CLog(tag3+"...");
1766
+ return This.state==1;
1767
+ },function(runC){
1768
+ runC&&This.CLog(tag3+ctx.state);
1769
+ ConnAlive(stream);
1770
+ },function(err){
1771
+ This.CLog(tag3+ctx.state+"[err]"+err,1);
1772
+ });
1773
+ };
1774
+ };
1775
+ }
1776
+
1777
+
1778
+
1779
+
1780
+ ,_stop:function(keepEngine){
1781
+ var This=this,set=This.set;
1782
+ if(!This.isMock){
1783
+ This._S++;
1784
+ };
1785
+ if(This.state){
1786
+ This.pause();
1787
+ This.state=0;
1788
+ };
1789
+ if(!keepEngine && This[set.type+"_stop"]){
1790
+ This[set.type+"_stop"](This.engineCtx);
1791
+ This.engineCtx=0;
1792
+ };
1793
+ }
1794
+ /*
1795
+ 结束录音并返回录音数据blob对象
1796
+ True(blob,duration,mime)
1797
+ blob:录音数据audio/mp3|wav格式;默认是Blob对象,可设置rec.dataType="arraybuffer"改成ArrayBuffer
1798
+ duration:录音时长,单位毫秒
1799
+ mime:"auido/mp3" blob数据的类型,方便ArrayBuffer时区分类型
1800
+ False(msg)
1801
+ autoClose:false 可选,是否自动调用close,默认为false
1802
+ */
1803
+ ,stop:function(True,False,autoClose){
1804
+ var This=this,set=This.set,t1;
1805
+ var envInMS=This.envInLast-This.envInFirst, envInLen=envInMS&&This.buffers.length; //可能未start
1806
+ This.CLog($T("Xq4s::stop 和start时差:")
1807
+ +(envInMS?envInMS+"ms "+$T("3CQP::补偿:")+This.envInFix+"ms"
1808
+ +" envIn:"+envInLen+" fps:"+(envInLen/envInMS*1000).toFixed(1)
1809
+ :"-")+" stream:"+This._streamTag+" ("+GitUrl+") LM:"+LM);
1810
+
1811
+ var end=function(){
1812
+ This._stop();//彻底关掉engineCtx
1813
+ if(autoClose){
1814
+ This.close();
1815
+ };
1816
+ };
1817
+ var err=function(msg){
1818
+ This.CLog($T("u8JG::结束录音失败:")+msg,1);
1819
+ False&&False(msg);
1820
+ end();
1821
+ };
1822
+ var ok=function(blob,mime,duration){
1823
+ var tBlob="blob",tABuf="arraybuffer",tDT="dataType",tDDT="DefaultDataType";
1824
+ var dType=This[tDT]||Recorder[tDDT]||tBlob,dTag=tDT+"="+dType;
1825
+ var isAB=blob instanceof ArrayBuffer,dErr=0;
1826
+ var dLen=isAB?blob.byteLength:blob.size;
1827
+ if(dType==tABuf){
1828
+ if(!isAB) dErr=1;
1829
+ }else if(dType==tBlob){
1830
+ if(typeof Blob!="function"){
1831
+ dErr=$T.G("NonBrowser-1",[dTag])+$T("1skY::,请设置{1}",0,RecTxt+"."+tDDT+'="'+tABuf+'"');
1832
+ }else{
1833
+ if(isAB) blob=new Blob([blob],{type:mime});
1834
+ if(!(blob instanceof Blob)) dErr=1;
1835
+ mime=blob.type||mime;
1836
+ }
1837
+ }else{
1838
+ dErr=$T.G("NotSupport-1",[dTag]);
1839
+ };
1840
+
1841
+ This.CLog($T("Wv7l::结束录音 编码花{1}ms 音频时长{2}ms 文件大小{3}b",0,Date.now()-t1,duration,dLen)+" "+dTag+","+mime);
1842
+ if(dErr){
1843
+ err(dErr!=1?dErr:$T("Vkbd::{1}编码器返回的不是{2}",0,set.type,dType)+", "+dTag);
1844
+ return;
1845
+ };
1846
+ if(set.takeoffEncodeChunk){//接管了输出,此时blob长度为0
1847
+ This.CLog($T("QWnr::启用takeoffEncodeChunk后stop返回的blob长度为0不提供音频数据"),3);
1848
+ }else if(dLen<Math.max(50,duration/5)){//1秒小于0.2k?
1849
+ err($T("Sz2H::生成的{1}无效",0,set.type));
1850
+ return;
1851
+ };
1852
+
1853
+ True&&True(blob,duration,mime);
1854
+ end();
1855
+ };
1856
+ if(!This.isMock){
1857
+ var isCtxWait=This.state==3;
1858
+ if(!This.state || isCtxWait){
1859
+ err($T("wf9t::未开始录音")+(isCtxWait?$T("Dl2c::,开始录音前无用户交互导致AudioContext未运行"):""));
1860
+ return;
1861
+ };
1862
+ };
1863
+ This._stop(true); //将录音状态改成未录音
1864
+ var size=This.recSize;
1865
+ if(!size){
1866
+ err($T("Ltz3::未采集到录音"));
1867
+ return;
1868
+ };
1869
+ if(!This[set.type]){
1870
+ err($T("xGuI::未加载{1}编码器,请尝试到{2}的src/engine内找到{1}的编码器并加载",0,set.type,RecTxt));
1871
+ return;
1872
+ };
1873
+
1874
+ //环境配置检查,此处仅针对mock调用,因为open已经检查过了
1875
+ if(This.isMock){
1876
+ var checkMsg=This.envCheck(This.mockEnvInfo||{envName:"mock",canProcess:false});//没有提供环境信息的mock时没有onProcess回调
1877
+ if(checkMsg){
1878
+ err($T("AxOH::录音错误:")+checkMsg);
1879
+ return;
1880
+ };
1881
+ };
1882
+
1883
+ //此类型有边录边转码(Worker)支持
1884
+ var engineCtx=This.engineCtx;
1885
+ if(This[set.type+"_complete"]&&engineCtx){
1886
+ var duration=Math.round(engineCtx.pcmSize/set[sampleRateTxt]*1000);//采用后的数据长度和buffers的长度可能微小的不一致,是采样率连续转换的精度问题
1887
+
1888
+ t1=Date.now();
1889
+ This[set.type+"_complete"](engineCtx,function(blob,mime){
1890
+ ok(blob,mime,duration);
1891
+ },err);
1892
+ return;
1893
+ };
1894
+
1895
+ //标准UI线程转码,调整采样率
1896
+ t1=Date.now();
1897
+ if(!This.buffers[0]){
1898
+ err($T("xkKd::音频buffers被释放"));
1899
+ return;
1900
+ };
1901
+ var chunk=Recorder.SampleData(This.buffers,This[srcSampleRateTxt],set[sampleRateTxt]);
1902
+
1903
+ set[sampleRateTxt]=chunk[sampleRateTxt];
1904
+ var res=chunk.data;
1905
+ var duration=Math.round(res.length/set[sampleRateTxt]*1000);
1906
+
1907
+ This.CLog($T("CxeT::采样:{1} 花:{2}ms",0,size+"->"+res.length,Date.now()-t1));
1908
+
1909
+ setTimeout(function(){
1910
+ t1=Date.now();
1911
+ This[set.type](res,function(blob,mime){
1912
+ ok(blob,mime,duration);
1913
+ },function(msg){
1914
+ err(msg);
1915
+ });
1916
+ });
1917
+ }
1918
+
1919
+ };
34
1920
 
35
- module.exports = __webpack_require__(5425);
36
1921
 
37
1922
 
1923
+
1924
+
1925
+ //=======从WebM字节流中提取pcm数据,提取成功返回Float32Array,失败返回null||-1=====
1926
+ var WebM_Extract=function(inBytes, scope){
1927
+ if(!scope.pos){
1928
+ scope.pos=[0]; scope.tracks={}; scope.bytes=[];
1929
+ };
1930
+ var tracks=scope.tracks, position=[scope.pos[0]];
1931
+ var endPos=function(){ scope.pos[0]=position[0] };
1932
+
1933
+ var sBL=scope.bytes.length;
1934
+ var bytes=new Uint8Array(sBL+inBytes.length);
1935
+ bytes.set(scope.bytes); bytes.set(inBytes,sBL);
1936
+ scope.bytes=bytes;
1937
+
1938
+ //先读取文件头和Track信息
1939
+ if(!scope._ht){
1940
+ readMatroskaVInt(bytes, position);//EBML Header
1941
+ readMatroskaBlock(bytes, position);//跳过EBML Header内容
1942
+ if(!BytesEq(readMatroskaVInt(bytes, position), [0x18,0x53,0x80,0x67])){
1943
+ return;//未识别到Segment
1944
+ }
1945
+ readMatroskaVInt(bytes, position);//跳过Segment长度值
1946
+ while(position[0]<bytes.length){
1947
+ var eid0=readMatroskaVInt(bytes, position);
1948
+ var bytes0=readMatroskaBlock(bytes, position);
1949
+ var pos0=[0],audioIdx=0;
1950
+ if(!bytes0)return;//数据不全,等待缓冲
1951
+ //Track完整数据,循环读取TrackEntry
1952
+ if(BytesEq(eid0, [0x16,0x54,0xAE,0x6B])){
1953
+ while(pos0[0]<bytes0.length){
1954
+ var eid1=readMatroskaVInt(bytes0, pos0);
1955
+ var bytes1=readMatroskaBlock(bytes0, pos0);
1956
+ var pos1=[0],track={channels:0,sampleRate:0};
1957
+ if(BytesEq(eid1, [0xAE])){//TrackEntry
1958
+ while(pos1[0]<bytes1.length){
1959
+ var eid2=readMatroskaVInt(bytes1, pos1);
1960
+ var bytes2=readMatroskaBlock(bytes1, pos1);
1961
+ var pos2=[0];
1962
+ if(BytesEq(eid2, [0xD7])){//Track Number
1963
+ var val=BytesInt(bytes2);
1964
+ track.number=val;
1965
+ tracks[val]=track;
1966
+ }else if(BytesEq(eid2, [0x83])){//Track Type
1967
+ var val=BytesInt(bytes2);
1968
+ if(val==1) track.type="video";
1969
+ else if(val==2) {
1970
+ track.type="audio";
1971
+ if(!audioIdx) scope.track0=track;
1972
+ track.idx=audioIdx++;
1973
+ }else track.type="Type-"+val;
1974
+ }else if(BytesEq(eid2, [0x86])){//Track Codec
1975
+ var str="";
1976
+ for(var i=0;i<bytes2.length;i++){
1977
+ str+=String.fromCharCode(bytes2[i]);
1978
+ }
1979
+ track.codec=str;
1980
+ }else if(BytesEq(eid2, [0xE1])){
1981
+ while(pos2[0]<bytes2.length){//循环读取 Audio 属性
1982
+ var eid3=readMatroskaVInt(bytes2, pos2);
1983
+ var bytes3=readMatroskaBlock(bytes2, pos2);
1984
+ //采样率、位数、声道数
1985
+ if(BytesEq(eid3, [0xB5])){
1986
+ var val=0,arr=new Uint8Array(bytes3.reverse()).buffer;
1987
+ if(bytes3.length==4) val=new Float32Array(arr)[0];
1988
+ else if(bytes3.length==8) val=new Float64Array(arr)[0];
1989
+ else CLog("WebM Track !Float",1,bytes3);
1990
+ track[sampleRateTxt]=Math.round(val);
1991
+ }else if(BytesEq(eid3, [0x62,0x64])) track.bitDepth=BytesInt(bytes3);
1992
+ else if(BytesEq(eid3, [0x9F])) track.channels=BytesInt(bytes3);
1993
+ }
1994
+ }
1995
+ }
1996
+ }
1997
+ };
1998
+ scope._ht=1;
1999
+ CLog("WebM Tracks",tracks);
2000
+ endPos();
2001
+ break;
2002
+ }
2003
+ }
2004
+ }
2005
+
2006
+ //校验音频参数信息,如果不符合代码要求,统统拒绝处理
2007
+ var track0=scope.track0;
2008
+ if(!track0)return;
2009
+ var trackSR=track0[sampleRateTxt]; scope.webmSR=trackSR;
2010
+ if(track0.bitDepth==16 && /FLOAT/i.test(track0.codec)){
2011
+ track0.bitDepth=32; //chrome v66 实际为浮点数
2012
+ CLog("WebM 16->32 bit",3);
2013
+ }
2014
+ if(trackSR<8000 || track0.bitDepth!=32 || track0.channels<1 || !/(\b|_)PCM\b/i.test(track0.codec)){
2015
+ scope.bytes=[];//格式非预期 无法处理,清空缓冲数据
2016
+ if(!scope.bad)CLog("WebM Track Unexpected",3,scope);
2017
+ scope.bad=1;
2018
+ return -1;
2019
+ }
2020
+
2021
+ //循环读取Cluster内的SimpleBlock
2022
+ var datas=[],dataLen=0;
2023
+ while(position[0]<bytes.length){
2024
+ var eid1=readMatroskaVInt(bytes, position);
2025
+ var bytes1=readMatroskaBlock(bytes, position);
2026
+ if(!bytes1)break;//数据不全,等待缓冲
2027
+ if(BytesEq(eid1, [0xA3])){//SimpleBlock完整数据
2028
+ var trackNo=bytes1[0]&0xf;
2029
+ var track=tracks[trackNo];
2030
+ if(!track){//不可能没有,数据出错?
2031
+ CLog("WebM !Track"+trackNo,1,tracks);
2032
+ }else if(track.idx===0){
2033
+ var u8arr=new Uint8Array(bytes1.length-4);
2034
+ for(var i=4;i<bytes1.length;i++){
2035
+ u8arr[i-4]=bytes1[i];
2036
+ }
2037
+ datas.push(u8arr); dataLen+=u8arr.length;
2038
+ }
2039
+ }
2040
+ endPos();
2041
+ }
2042
+
2043
+ if(dataLen){
2044
+ var more=new Uint8Array(bytes.length-scope.pos[0]);
2045
+ more.set(bytes.subarray(scope.pos[0]));
2046
+ scope.bytes=more; //清理已读取了的缓冲数据
2047
+ scope.pos[0]=0;
2048
+
2049
+ var u8arr=new Uint8Array(dataLen); //已获取的音频数据
2050
+ for(var i=0,i2=0;i<datas.length;i++){
2051
+ u8arr.set(datas[i],i2);
2052
+ i2+=datas[i].length;
2053
+ }
2054
+ var arr=new Float32Array(u8arr.buffer);
2055
+
2056
+ if(track0.channels>1){//多声道,提取一个声道
2057
+ var arr2=[];
2058
+ for(var i=0;i<arr.length;){
2059
+ arr2.push(arr[i]);
2060
+ i+=track0.channels;
2061
+ }
2062
+ arr=new Float32Array(arr2);
2063
+ };
2064
+ return arr;
2065
+ }
2066
+ };
2067
+ //两个字节数组内容是否相同
2068
+ var BytesEq=function(bytes1,bytes2){
2069
+ if(!bytes1 || bytes1.length!=bytes2.length) return false;
2070
+ if(bytes1.length==1) return bytes1[0]==bytes2[0];
2071
+ for(var i=0;i<bytes1.length;i++){
2072
+ if(bytes1[i]!=bytes2[i]) return false;
2073
+ }
2074
+ return true;
2075
+ };
2076
+ //字节数组BE转成int数字
2077
+ var BytesInt=function(bytes){
2078
+ var s="";//0-8字节,js位运算只支持4字节
2079
+ for(var i=0;i<bytes.length;i++){var n=bytes[i];s+=(n<16?"0":"")+n.toString(16)};
2080
+ return parseInt(s,16)||0;
2081
+ };
2082
+ //读取一个可变长数值字节数组
2083
+ var readMatroskaVInt=function(arr,pos,trim){
2084
+ var i=pos[0];
2085
+ if(i>=arr.length)return;
2086
+ var b0=arr[i],b2=("0000000"+b0.toString(2)).substr(-8);
2087
+ var m=/^(0*1)(\d*)$/.exec(b2);
2088
+ if(!m)return;
2089
+ var len=m[1].length, val=[];
2090
+ if(i+len>arr.length)return;
2091
+ for(var i2=0;i2<len;i2++){ val[i2]=arr[i]; i++; }
2092
+ if(trim) val[0]=parseInt(m[2]||'0',2);
2093
+ pos[0]=i;
2094
+ return val;
2095
+ };
2096
+ //读取一个自带长度的内容字节数组
2097
+ var readMatroskaBlock=function(arr,pos){
2098
+ var lenVal=readMatroskaVInt(arr,pos,1);
2099
+ if(!lenVal)return;
2100
+ var len=BytesInt(lenVal);
2101
+ var i=pos[0], val=[];
2102
+ if(len<0x7FFFFFFF){ //超大值代表没有长度
2103
+ if(i+len>arr.length)return;
2104
+ for(var i2=0;i2<len;i2++){ val[i2]=arr[i]; i++; }
2105
+ }
2106
+ pos[0]=i;
2107
+ return val;
2108
+ };
2109
+ //=====End WebM读取=====
2110
+
2111
+
2112
+ //=====i18n 简版国际化多语言支持=====
2113
+ var i18n=Recorder.i18n={
2114
+ lang: "zh-CN" //默认中文
2115
+ ,alias:{"zh-CN":"zh","en-US":"en"} //别名配置,映射到一个语言实例
2116
+ ,locales:{} //语言实例:zh:{key:"text"}
2117
+ ,data:{} //各种数据,desc$xx:语言描述,rtl$xx:文本方向是否从右到左 rtl$zh:false rtl$ar:true
2118
+ //添加语言文本内容,set={lang:"",overwrite:true},texts=["key:text{1}",...]
2119
+ ,put:function(set,texts){
2120
+ var tag=RecTxt+".i18n.put: ";
2121
+ var overwrite=set.overwrite; overwrite=overwrite==null||overwrite;
2122
+ var lang=set.lang; lang=i18n.alias[lang]||lang;
2123
+ if(!lang)throw new Error(tag+"set.lang?");
2124
+ var locale=i18n.locales[lang];
2125
+ if(!locale){ locale={}; i18n.locales[lang]=locale };
2126
+ var exp=/^([\w\-]+):/,m;
2127
+ for(var i=0;i<texts.length;i++){
2128
+ var v=texts[i]; m=exp.exec(v);
2129
+ if(!m){ CLog(tag+"'key:'? "+v,3,set); continue }
2130
+ var key=m[1],v=v.substr(key.length+1);
2131
+ if(!overwrite && locale[key]) continue;
2132
+ locale[key]=v;
2133
+ }
2134
+ }
2135
+ //获取key对应的文本,如果没有对应文本,将返回en的,en的也没有将返回zh的
2136
+ ,get:function(/*key,args,lang*/){
2137
+ return i18n.v_G.apply(null,arguments);
2138
+ }, v_G:function(key,args,lang){ //全局可重写get
2139
+ args=args||[];
2140
+ lang=lang||i18n.lang; lang=i18n.alias[lang]||lang;
2141
+ var locale=i18n.locales[lang];
2142
+ var val=locale&&locale[key]||"";
2143
+ if(!val&&lang!="zh"){
2144
+ if(lang=="en")return i18n.v_G(key,args,"zh");
2145
+ return i18n.v_G(key,args,"en");
2146
+ }
2147
+ i18n.lastLang=lang;
2148
+ if(val=="=Empty")return "";
2149
+ return val.replace(/\{(\d+)(\!?)\}/g,function(v,a,b){
2150
+ a=+a||0; v=args[a-1];
2151
+ if(a<1 || a>args.length){ v="{?}"; CLog("i18n["+key+"] no {"+a+"}: "+val,3) }
2152
+ return b?"":v;
2153
+ });
2154
+ }
2155
+ /**返回一个国际化文本,返回的文本取决于i18n.lang。
2156
+ 调用参数:T("key:[lang]:中文{1}","[lang]:英文{1}",...,0,"args1","args2"),除了key:,其他都是可选的,文本如果在语言实例中不存在会push进去,第一个文本无lang时默认zh,第二个无lang时默认en,文本中用{1-n}来插入args
2157
+ 第一个args前面这个参数必须是0;也可以不提供args,这个参数填args的数量,此时不返回文本,只返回key,再用i18n.get提供参数获取文本
2158
+ 本函数调用,第一个文本需中文,调用尽量简单,不要换行,方便后续自动提取翻译列表
2159
+ args如果旧的参数位置发生了变更,应当使用新的key,让旧的翻译失效,增加args无需更换key
2160
+ key的生成使用随机字符串,不同源码里面可以搞个不同前缀:
2161
+ s="";L=4; for(var i=0,n;i<L;i++){ n=~~(Math.random()*62);s+=n<10?n:String.fromCharCode(n<36?55+n:61+n); }; s
2162
+ **/
2163
+ ,$T:function(){
2164
+ return i18n.v_T.apply(null,arguments);
2165
+ } ,v_T:function(){ //全局可重写$T
2166
+ var a=arguments,key="",args=[],isArgs=0,tag=RecTxt+".i18n.$T:";
2167
+ var exp=/^([\w\-]*):/,m;
2168
+ for(var i=0;i<a.length;i++){
2169
+ var v=a[i];
2170
+ if(i==0){
2171
+ m=exp.exec(v); key=m&&m[1];
2172
+ if(!key)throw new Error(tag+"0 'key:'?");
2173
+ v=v.substr(key.length+1);
2174
+ }
2175
+ if(isArgs===-1) args.push(v);
2176
+ else if(isArgs) throw new Error(tag+" bad args");
2177
+ else if(v===0) isArgs=-1;
2178
+ else if(IsNum(v)){
2179
+ if(v<1) throw new Error(tag+" bad args");
2180
+ isArgs=v;
2181
+ }else{
2182
+ var lang=i==1?"en":i?"":"zh";
2183
+ m=exp.exec(v); if(m){ lang=m[1]||lang; v=v.substr(m[1].length+1); }
2184
+ if(!m || !lang)throw new Error(tag+i+" 'lang:'?");
2185
+ i18n.put({lang:lang,overwrite:false},[key+":"+v]);
2186
+ }
2187
+ }
2188
+ if(!key)return "";
2189
+ if(isArgs>0)return key;
2190
+ return i18n.v_G(key,args);
2191
+ }
2192
+ };
2193
+ var $T=i18n.$T; $T.G=i18n.get;
2194
+ //预定义文本
2195
+ $T("NonBrowser-1::非浏览器环境,不支持{1}",1);
2196
+ $T("IllegalArgs-1::参数错误:{1}",1);
2197
+ $T("NeedImport-2::调用{1}需要先导入{2}",2);
2198
+ $T("NotSupport-1::不支持:{1}",1);
2199
+ //=====End i18n=====
2200
+
2201
+
2202
+
2203
+ //流量统计用1像素图片地址,设置为空将不参与统计
2204
+ Recorder.TrafficImgUrl="//ia.51.la/go1?id=20469973&pvFlag=1";
2205
+ var Traffic=Recorder.Traffic=function(report){
2206
+ if(!isBrowser)return;
2207
+ report=report?"/"+RecTxt+"/Report/"+report:"";
2208
+ var imgUrl=Recorder.TrafficImgUrl;
2209
+ if(imgUrl){
2210
+ var data=Recorder.Traffic;
2211
+ var m=/^(https?:..[^\/#]*\/?)[^#]*/i.exec(location.href)||[];
2212
+ var host=(m[1]||"http://file/");
2213
+ var idf=(m[0]||host)+report;
2214
+
2215
+ if(imgUrl.indexOf("//")==0){
2216
+ //给url加上http前缀,如果是file协议下,不加前缀没法用
2217
+ if(/^https:/i.test(idf)){
2218
+ imgUrl="https:"+imgUrl;
2219
+ }else{
2220
+ imgUrl="http:"+imgUrl;
2221
+ };
2222
+ };
2223
+ if(report){
2224
+ imgUrl=imgUrl+"&cu="+encodeURIComponent(host+report);
2225
+ };
2226
+
2227
+ if(!data[idf]){
2228
+ data[idf]=1;
2229
+
2230
+ var img=new Image();
2231
+ img.src=imgUrl;
2232
+ CLog("Traffic Analysis Image: "+(report||RecTxt+".TrafficImgUrl="+Recorder.TrafficImgUrl));
2233
+ };
2234
+ };
2235
+ };
2236
+
2237
+
2238
+
2239
+ if(WRec2){
2240
+ CLog($T("8HO5::覆盖导入{1}",0,RecTxt),1);
2241
+ WRec2.Destroy();
2242
+ };
2243
+ Export[RecTxt]=Recorder;
2244
+
2245
+ }));
2246
+
38
2247
  /***/ }),
39
2248
 
40
2249
  /***/ 6262:
@@ -122,6 +2331,24 @@ module.exports = function (argument) {
122
2331
  };
123
2332
 
124
2333
 
2334
+ /***/ }),
2335
+
2336
+ /***/ 3506:
2337
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2338
+
2339
+ "use strict";
2340
+
2341
+ var isPossiblePrototype = __webpack_require__(3925);
2342
+
2343
+ var $String = String;
2344
+ var $TypeError = TypeError;
2345
+
2346
+ module.exports = function (argument) {
2347
+ if (isPossiblePrototype(argument)) return argument;
2348
+ throw new $TypeError("Can't set " + $String(argument) + ' as a prototype');
2349
+ };
2350
+
2351
+
125
2352
  /***/ }),
126
2353
 
127
2354
  /***/ 8551:
@@ -141,6 +2368,356 @@ module.exports = function (argument) {
141
2368
  };
142
2369
 
143
2370
 
2371
+ /***/ }),
2372
+
2373
+ /***/ 7811:
2374
+ /***/ (function(module) {
2375
+
2376
+ "use strict";
2377
+
2378
+ // eslint-disable-next-line es/no-typed-arrays -- safe
2379
+ module.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
2380
+
2381
+
2382
+ /***/ }),
2383
+
2384
+ /***/ 7394:
2385
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2386
+
2387
+ "use strict";
2388
+
2389
+ var globalThis = __webpack_require__(4576);
2390
+ var uncurryThisAccessor = __webpack_require__(6706);
2391
+ var classof = __webpack_require__(2195);
2392
+
2393
+ var ArrayBuffer = globalThis.ArrayBuffer;
2394
+ var TypeError = globalThis.TypeError;
2395
+
2396
+ // Includes
2397
+ // - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
2398
+ // - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
2399
+ module.exports = ArrayBuffer && uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {
2400
+ if (classof(O) !== 'ArrayBuffer') throw new TypeError('ArrayBuffer expected');
2401
+ return O.byteLength;
2402
+ };
2403
+
2404
+
2405
+ /***/ }),
2406
+
2407
+ /***/ 3238:
2408
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2409
+
2410
+ "use strict";
2411
+
2412
+ var globalThis = __webpack_require__(4576);
2413
+ var uncurryThis = __webpack_require__(7476);
2414
+ var arrayBufferByteLength = __webpack_require__(7394);
2415
+
2416
+ var ArrayBuffer = globalThis.ArrayBuffer;
2417
+ var ArrayBufferPrototype = ArrayBuffer && ArrayBuffer.prototype;
2418
+ var slice = ArrayBufferPrototype && uncurryThis(ArrayBufferPrototype.slice);
2419
+
2420
+ module.exports = function (O) {
2421
+ if (arrayBufferByteLength(O) !== 0) return false;
2422
+ if (!slice) return false;
2423
+ try {
2424
+ slice(O, 0, 0);
2425
+ return false;
2426
+ } catch (error) {
2427
+ return true;
2428
+ }
2429
+ };
2430
+
2431
+
2432
+ /***/ }),
2433
+
2434
+ /***/ 5169:
2435
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2436
+
2437
+ "use strict";
2438
+
2439
+ var isDetached = __webpack_require__(3238);
2440
+
2441
+ var $TypeError = TypeError;
2442
+
2443
+ module.exports = function (it) {
2444
+ if (isDetached(it)) throw new $TypeError('ArrayBuffer is detached');
2445
+ return it;
2446
+ };
2447
+
2448
+
2449
+ /***/ }),
2450
+
2451
+ /***/ 5636:
2452
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2453
+
2454
+ "use strict";
2455
+
2456
+ var globalThis = __webpack_require__(4576);
2457
+ var uncurryThis = __webpack_require__(9504);
2458
+ var uncurryThisAccessor = __webpack_require__(6706);
2459
+ var toIndex = __webpack_require__(7696);
2460
+ var notDetached = __webpack_require__(5169);
2461
+ var arrayBufferByteLength = __webpack_require__(7394);
2462
+ var detachTransferable = __webpack_require__(4483);
2463
+ var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
2464
+
2465
+ var structuredClone = globalThis.structuredClone;
2466
+ var ArrayBuffer = globalThis.ArrayBuffer;
2467
+ var DataView = globalThis.DataView;
2468
+ var min = Math.min;
2469
+ var ArrayBufferPrototype = ArrayBuffer.prototype;
2470
+ var DataViewPrototype = DataView.prototype;
2471
+ var slice = uncurryThis(ArrayBufferPrototype.slice);
2472
+ var isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');
2473
+ var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');
2474
+ var getInt8 = uncurryThis(DataViewPrototype.getInt8);
2475
+ var setInt8 = uncurryThis(DataViewPrototype.setInt8);
2476
+
2477
+ module.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {
2478
+ var byteLength = arrayBufferByteLength(arrayBuffer);
2479
+ var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);
2480
+ var fixedLength = !isResizable || !isResizable(arrayBuffer);
2481
+ var newBuffer;
2482
+ notDetached(arrayBuffer);
2483
+ if (PROPER_STRUCTURED_CLONE_TRANSFER) {
2484
+ arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
2485
+ if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;
2486
+ }
2487
+ if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {
2488
+ newBuffer = slice(arrayBuffer, 0, newByteLength);
2489
+ } else {
2490
+ var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;
2491
+ newBuffer = new ArrayBuffer(newByteLength, options);
2492
+ var a = new DataView(arrayBuffer);
2493
+ var b = new DataView(newBuffer);
2494
+ var copyLength = min(newByteLength, byteLength);
2495
+ for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));
2496
+ }
2497
+ if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);
2498
+ return newBuffer;
2499
+ };
2500
+
2501
+
2502
+ /***/ }),
2503
+
2504
+ /***/ 4644:
2505
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2506
+
2507
+ "use strict";
2508
+
2509
+ var NATIVE_ARRAY_BUFFER = __webpack_require__(7811);
2510
+ var DESCRIPTORS = __webpack_require__(3724);
2511
+ var globalThis = __webpack_require__(4576);
2512
+ var isCallable = __webpack_require__(4901);
2513
+ var isObject = __webpack_require__(34);
2514
+ var hasOwn = __webpack_require__(9297);
2515
+ var classof = __webpack_require__(6955);
2516
+ var tryToString = __webpack_require__(6823);
2517
+ var createNonEnumerableProperty = __webpack_require__(6699);
2518
+ var defineBuiltIn = __webpack_require__(6840);
2519
+ var defineBuiltInAccessor = __webpack_require__(2106);
2520
+ var isPrototypeOf = __webpack_require__(1625);
2521
+ var getPrototypeOf = __webpack_require__(2787);
2522
+ var setPrototypeOf = __webpack_require__(2967);
2523
+ var wellKnownSymbol = __webpack_require__(8227);
2524
+ var uid = __webpack_require__(3392);
2525
+ var InternalStateModule = __webpack_require__(1181);
2526
+
2527
+ var enforceInternalState = InternalStateModule.enforce;
2528
+ var getInternalState = InternalStateModule.get;
2529
+ var Int8Array = globalThis.Int8Array;
2530
+ var Int8ArrayPrototype = Int8Array && Int8Array.prototype;
2531
+ var Uint8ClampedArray = globalThis.Uint8ClampedArray;
2532
+ var Uint8ClampedArrayPrototype = Uint8ClampedArray && Uint8ClampedArray.prototype;
2533
+ var TypedArray = Int8Array && getPrototypeOf(Int8Array);
2534
+ var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf(Int8ArrayPrototype);
2535
+ var ObjectPrototype = Object.prototype;
2536
+ var TypeError = globalThis.TypeError;
2537
+
2538
+ var TO_STRING_TAG = wellKnownSymbol('toStringTag');
2539
+ var TYPED_ARRAY_TAG = uid('TYPED_ARRAY_TAG');
2540
+ var TYPED_ARRAY_CONSTRUCTOR = 'TypedArrayConstructor';
2541
+ // Fixing native typed arrays in Opera Presto crashes the browser, see #595
2542
+ var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(globalThis.opera) !== 'Opera';
2543
+ var TYPED_ARRAY_TAG_REQUIRED = false;
2544
+ var NAME, Constructor, Prototype;
2545
+
2546
+ var TypedArrayConstructorsList = {
2547
+ Int8Array: 1,
2548
+ Uint8Array: 1,
2549
+ Uint8ClampedArray: 1,
2550
+ Int16Array: 2,
2551
+ Uint16Array: 2,
2552
+ Int32Array: 4,
2553
+ Uint32Array: 4,
2554
+ Float32Array: 4,
2555
+ Float64Array: 8
2556
+ };
2557
+
2558
+ var BigIntArrayConstructorsList = {
2559
+ BigInt64Array: 8,
2560
+ BigUint64Array: 8
2561
+ };
2562
+
2563
+ var isView = function isView(it) {
2564
+ if (!isObject(it)) return false;
2565
+ var klass = classof(it);
2566
+ return klass === 'DataView'
2567
+ || hasOwn(TypedArrayConstructorsList, klass)
2568
+ || hasOwn(BigIntArrayConstructorsList, klass);
2569
+ };
2570
+
2571
+ var getTypedArrayConstructor = function (it) {
2572
+ var proto = getPrototypeOf(it);
2573
+ if (!isObject(proto)) return;
2574
+ var state = getInternalState(proto);
2575
+ return (state && hasOwn(state, TYPED_ARRAY_CONSTRUCTOR)) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto);
2576
+ };
2577
+
2578
+ var isTypedArray = function (it) {
2579
+ if (!isObject(it)) return false;
2580
+ var klass = classof(it);
2581
+ return hasOwn(TypedArrayConstructorsList, klass)
2582
+ || hasOwn(BigIntArrayConstructorsList, klass);
2583
+ };
2584
+
2585
+ var aTypedArray = function (it) {
2586
+ if (isTypedArray(it)) return it;
2587
+ throw new TypeError('Target is not a typed array');
2588
+ };
2589
+
2590
+ var aTypedArrayConstructor = function (C) {
2591
+ if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C;
2592
+ throw new TypeError(tryToString(C) + ' is not a typed array constructor');
2593
+ };
2594
+
2595
+ var exportTypedArrayMethod = function (KEY, property, forced, options) {
2596
+ if (!DESCRIPTORS) return;
2597
+ if (forced) for (var ARRAY in TypedArrayConstructorsList) {
2598
+ var TypedArrayConstructor = globalThis[ARRAY];
2599
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try {
2600
+ delete TypedArrayConstructor.prototype[KEY];
2601
+ } catch (error) {
2602
+ // old WebKit bug - some methods are non-configurable
2603
+ try {
2604
+ TypedArrayConstructor.prototype[KEY] = property;
2605
+ } catch (error2) { /* empty */ }
2606
+ }
2607
+ }
2608
+ if (!TypedArrayPrototype[KEY] || forced) {
2609
+ defineBuiltIn(TypedArrayPrototype, KEY, forced ? property
2610
+ : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property, options);
2611
+ }
2612
+ };
2613
+
2614
+ var exportTypedArrayStaticMethod = function (KEY, property, forced) {
2615
+ var ARRAY, TypedArrayConstructor;
2616
+ if (!DESCRIPTORS) return;
2617
+ if (setPrototypeOf) {
2618
+ if (forced) for (ARRAY in TypedArrayConstructorsList) {
2619
+ TypedArrayConstructor = globalThis[ARRAY];
2620
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try {
2621
+ delete TypedArrayConstructor[KEY];
2622
+ } catch (error) { /* empty */ }
2623
+ }
2624
+ if (!TypedArray[KEY] || forced) {
2625
+ // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
2626
+ try {
2627
+ return defineBuiltIn(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property);
2628
+ } catch (error) { /* empty */ }
2629
+ } else return;
2630
+ }
2631
+ for (ARRAY in TypedArrayConstructorsList) {
2632
+ TypedArrayConstructor = globalThis[ARRAY];
2633
+ if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
2634
+ defineBuiltIn(TypedArrayConstructor, KEY, property);
2635
+ }
2636
+ }
2637
+ };
2638
+
2639
+ for (NAME in TypedArrayConstructorsList) {
2640
+ Constructor = globalThis[NAME];
2641
+ Prototype = Constructor && Constructor.prototype;
2642
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
2643
+ else NATIVE_ARRAY_BUFFER_VIEWS = false;
2644
+ }
2645
+
2646
+ for (NAME in BigIntArrayConstructorsList) {
2647
+ Constructor = globalThis[NAME];
2648
+ Prototype = Constructor && Constructor.prototype;
2649
+ if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor;
2650
+ }
2651
+
2652
+ // WebKit bug - typed arrays constructors prototype is Object.prototype
2653
+ if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) {
2654
+ // eslint-disable-next-line no-shadow -- safe
2655
+ TypedArray = function TypedArray() {
2656
+ throw new TypeError('Incorrect invocation');
2657
+ };
2658
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
2659
+ if (globalThis[NAME]) setPrototypeOf(globalThis[NAME], TypedArray);
2660
+ }
2661
+ }
2662
+
2663
+ if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) {
2664
+ TypedArrayPrototype = TypedArray.prototype;
2665
+ if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) {
2666
+ if (globalThis[NAME]) setPrototypeOf(globalThis[NAME].prototype, TypedArrayPrototype);
2667
+ }
2668
+ }
2669
+
2670
+ // WebKit bug - one more object in Uint8ClampedArray prototype chain
2671
+ if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) {
2672
+ setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype);
2673
+ }
2674
+
2675
+ if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) {
2676
+ TYPED_ARRAY_TAG_REQUIRED = true;
2677
+ defineBuiltInAccessor(TypedArrayPrototype, TO_STRING_TAG, {
2678
+ configurable: true,
2679
+ get: function () {
2680
+ return isObject(this) ? this[TYPED_ARRAY_TAG] : undefined;
2681
+ }
2682
+ });
2683
+ for (NAME in TypedArrayConstructorsList) if (globalThis[NAME]) {
2684
+ createNonEnumerableProperty(globalThis[NAME], TYPED_ARRAY_TAG, NAME);
2685
+ }
2686
+ }
2687
+
2688
+ module.exports = {
2689
+ NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS,
2690
+ TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG,
2691
+ aTypedArray: aTypedArray,
2692
+ aTypedArrayConstructor: aTypedArrayConstructor,
2693
+ exportTypedArrayMethod: exportTypedArrayMethod,
2694
+ exportTypedArrayStaticMethod: exportTypedArrayStaticMethod,
2695
+ getTypedArrayConstructor: getTypedArrayConstructor,
2696
+ isView: isView,
2697
+ isTypedArray: isTypedArray,
2698
+ TypedArray: TypedArray,
2699
+ TypedArrayPrototype: TypedArrayPrototype
2700
+ };
2701
+
2702
+
2703
+ /***/ }),
2704
+
2705
+ /***/ 5370:
2706
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2707
+
2708
+ "use strict";
2709
+
2710
+ var lengthOfArrayLike = __webpack_require__(6198);
2711
+
2712
+ module.exports = function (Constructor, list, $length) {
2713
+ var index = 0;
2714
+ var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);
2715
+ var result = new Constructor(length);
2716
+ while (length > index) result[index] = list[index++];
2717
+ return result;
2718
+ };
2719
+
2720
+
144
2721
  /***/ }),
145
2722
 
146
2723
  /***/ 9617:
@@ -218,6 +2795,52 @@ module.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
218
2795
  };
219
2796
 
220
2797
 
2798
+ /***/ }),
2799
+
2800
+ /***/ 7628:
2801
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2802
+
2803
+ "use strict";
2804
+
2805
+ var lengthOfArrayLike = __webpack_require__(6198);
2806
+
2807
+ // https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
2808
+ // https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
2809
+ module.exports = function (O, C) {
2810
+ var len = lengthOfArrayLike(O);
2811
+ var A = new C(len);
2812
+ var k = 0;
2813
+ for (; k < len; k++) A[k] = O[len - k - 1];
2814
+ return A;
2815
+ };
2816
+
2817
+
2818
+ /***/ }),
2819
+
2820
+ /***/ 9928:
2821
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2822
+
2823
+ "use strict";
2824
+
2825
+ var lengthOfArrayLike = __webpack_require__(6198);
2826
+ var toIntegerOrInfinity = __webpack_require__(1291);
2827
+
2828
+ var $RangeError = RangeError;
2829
+
2830
+ // https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
2831
+ // https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
2832
+ module.exports = function (O, C, index, value) {
2833
+ var len = lengthOfArrayLike(O);
2834
+ var relativeIndex = toIntegerOrInfinity(index);
2835
+ var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;
2836
+ if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');
2837
+ var A = new C(len);
2838
+ var k = 0;
2839
+ for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];
2840
+ return A;
2841
+ };
2842
+
2843
+
221
2844
  /***/ }),
222
2845
 
223
2846
  /***/ 2195:
@@ -298,6 +2921,23 @@ module.exports = function (target, source, exceptions) {
298
2921
  };
299
2922
 
300
2923
 
2924
+ /***/ }),
2925
+
2926
+ /***/ 2211:
2927
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2928
+
2929
+ "use strict";
2930
+
2931
+ var fails = __webpack_require__(9039);
2932
+
2933
+ module.exports = !fails(function () {
2934
+ function F() { /* empty */ }
2935
+ F.prototype.constructor = null;
2936
+ // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
2937
+ return Object.getPrototypeOf(new F()) !== F.prototype;
2938
+ });
2939
+
2940
+
301
2941
  /***/ }),
302
2942
 
303
2943
  /***/ 6699:
@@ -424,6 +3064,51 @@ module.exports = !fails(function () {
424
3064
  });
425
3065
 
426
3066
 
3067
+ /***/ }),
3068
+
3069
+ /***/ 4483:
3070
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3071
+
3072
+ "use strict";
3073
+
3074
+ var globalThis = __webpack_require__(4576);
3075
+ var getBuiltInNodeModule = __webpack_require__(9429);
3076
+ var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(1548);
3077
+
3078
+ var structuredClone = globalThis.structuredClone;
3079
+ var $ArrayBuffer = globalThis.ArrayBuffer;
3080
+ var $MessageChannel = globalThis.MessageChannel;
3081
+ var detach = false;
3082
+ var WorkerThreads, channel, buffer, $detach;
3083
+
3084
+ if (PROPER_STRUCTURED_CLONE_TRANSFER) {
3085
+ detach = function (transferable) {
3086
+ structuredClone(transferable, { transfer: [transferable] });
3087
+ };
3088
+ } else if ($ArrayBuffer) try {
3089
+ if (!$MessageChannel) {
3090
+ WorkerThreads = getBuiltInNodeModule('worker_threads');
3091
+ if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;
3092
+ }
3093
+
3094
+ if ($MessageChannel) {
3095
+ channel = new $MessageChannel();
3096
+ buffer = new $ArrayBuffer(2);
3097
+
3098
+ $detach = function (transferable) {
3099
+ channel.port1.postMessage(null, [transferable]);
3100
+ };
3101
+
3102
+ if (buffer.byteLength === 2) {
3103
+ $detach(buffer);
3104
+ if (buffer.byteLength === 0) detach = $detach;
3105
+ }
3106
+ }
3107
+ } catch (error) { /* empty */ }
3108
+
3109
+ module.exports = detach;
3110
+
3111
+
427
3112
  /***/ }),
428
3113
 
429
3114
  /***/ 4055:
@@ -478,6 +3163,18 @@ module.exports = [
478
3163
  ];
479
3164
 
480
3165
 
3166
+ /***/ }),
3167
+
3168
+ /***/ 6193:
3169
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3170
+
3171
+ "use strict";
3172
+
3173
+ var ENVIRONMENT = __webpack_require__(4215);
3174
+
3175
+ module.exports = ENVIRONMENT === 'NODE';
3176
+
3177
+
481
3178
  /***/ }),
482
3179
 
483
3180
  /***/ 2839:
@@ -529,6 +3226,35 @@ if (!version && userAgent) {
529
3226
  module.exports = version;
530
3227
 
531
3228
 
3229
+ /***/ }),
3230
+
3231
+ /***/ 4215:
3232
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3233
+
3234
+ "use strict";
3235
+
3236
+ /* global Bun, Deno -- detection */
3237
+ var globalThis = __webpack_require__(4576);
3238
+ var userAgent = __webpack_require__(2839);
3239
+ var classof = __webpack_require__(2195);
3240
+
3241
+ var userAgentStartsWith = function (string) {
3242
+ return userAgent.slice(0, string.length) === string;
3243
+ };
3244
+
3245
+ module.exports = (function () {
3246
+ if (userAgentStartsWith('Bun/')) return 'BUN';
3247
+ if (userAgentStartsWith('Cloudflare-Workers')) return 'CLOUDFLARE';
3248
+ if (userAgentStartsWith('Deno/')) return 'DENO';
3249
+ if (userAgentStartsWith('Node.js/')) return 'NODE';
3250
+ if (globalThis.Bun && typeof Bun.version == 'string') return 'BUN';
3251
+ if (globalThis.Deno && typeof Deno.version == 'object') return 'DENO';
3252
+ if (classof(globalThis.process) === 'process') return 'NODE';
3253
+ if (globalThis.window && globalThis.document) return 'BROWSER';
3254
+ return 'REST';
3255
+ })();
3256
+
3257
+
532
3258
  /***/ }),
533
3259
 
534
3260
  /***/ 6518:
@@ -667,6 +3393,42 @@ module.exports = {
667
3393
  };
668
3394
 
669
3395
 
3396
+ /***/ }),
3397
+
3398
+ /***/ 6706:
3399
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3400
+
3401
+ "use strict";
3402
+
3403
+ var uncurryThis = __webpack_require__(9504);
3404
+ var aCallable = __webpack_require__(9306);
3405
+
3406
+ module.exports = function (object, key, method) {
3407
+ try {
3408
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
3409
+ return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));
3410
+ } catch (error) { /* empty */ }
3411
+ };
3412
+
3413
+
3414
+ /***/ }),
3415
+
3416
+ /***/ 7476:
3417
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3418
+
3419
+ "use strict";
3420
+
3421
+ var classofRaw = __webpack_require__(2195);
3422
+ var uncurryThis = __webpack_require__(9504);
3423
+
3424
+ module.exports = function (fn) {
3425
+ // Nashorn bug:
3426
+ // https://github.com/zloirock/core-js/issues/1128
3427
+ // https://github.com/zloirock/core-js/issues/1130
3428
+ if (classofRaw(fn) === 'Function') return uncurryThis(fn);
3429
+ };
3430
+
3431
+
670
3432
  /***/ }),
671
3433
 
672
3434
  /***/ 9504:
@@ -687,6 +3449,29 @@ module.exports = NATIVE_BIND ? uncurryThisWithBind : function (fn) {
687
3449
  };
688
3450
 
689
3451
 
3452
+ /***/ }),
3453
+
3454
+ /***/ 9429:
3455
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3456
+
3457
+ "use strict";
3458
+
3459
+ var globalThis = __webpack_require__(4576);
3460
+ var IS_NODE = __webpack_require__(6193);
3461
+
3462
+ module.exports = function (name) {
3463
+ if (IS_NODE) {
3464
+ try {
3465
+ return globalThis.process.getBuiltinModule(name);
3466
+ } catch (error) { /* empty */ }
3467
+ try {
3468
+ // eslint-disable-next-line no-new-func -- safe
3469
+ return Function('return require("' + name + '")')();
3470
+ } catch (error) { /* empty */ }
3471
+ }
3472
+ };
3473
+
3474
+
690
3475
  /***/ }),
691
3476
 
692
3477
  /***/ 7751:
@@ -941,6 +3726,21 @@ module.exports = Array.isArray || function isArray(argument) {
941
3726
  };
942
3727
 
943
3728
 
3729
+ /***/ }),
3730
+
3731
+ /***/ 1108:
3732
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3733
+
3734
+ "use strict";
3735
+
3736
+ var classof = __webpack_require__(6955);
3737
+
3738
+ module.exports = function (it) {
3739
+ var klass = classof(it);
3740
+ return klass === 'BigInt64Array' || klass === 'BigUint64Array';
3741
+ };
3742
+
3743
+
944
3744
  /***/ }),
945
3745
 
946
3746
  /***/ 4901:
@@ -1020,6 +3820,20 @@ module.exports = function (it) {
1020
3820
  };
1021
3821
 
1022
3822
 
3823
+ /***/ }),
3824
+
3825
+ /***/ 3925:
3826
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3827
+
3828
+ "use strict";
3829
+
3830
+ var isObject = __webpack_require__(34);
3831
+
3832
+ module.exports = function (argument) {
3833
+ return isObject(argument) || argument === null;
3834
+ };
3835
+
3836
+
1023
3837
  /***/ }),
1024
3838
 
1025
3839
  /***/ 6395:
@@ -1264,6 +4078,36 @@ exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
1264
4078
  exports.f = Object.getOwnPropertySymbols;
1265
4079
 
1266
4080
 
4081
+ /***/ }),
4082
+
4083
+ /***/ 2787:
4084
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4085
+
4086
+ "use strict";
4087
+
4088
+ var hasOwn = __webpack_require__(9297);
4089
+ var isCallable = __webpack_require__(4901);
4090
+ var toObject = __webpack_require__(8981);
4091
+ var sharedKey = __webpack_require__(6119);
4092
+ var CORRECT_PROTOTYPE_GETTER = __webpack_require__(2211);
4093
+
4094
+ var IE_PROTO = sharedKey('IE_PROTO');
4095
+ var $Object = Object;
4096
+ var ObjectPrototype = $Object.prototype;
4097
+
4098
+ // `Object.getPrototypeOf` method
4099
+ // https://tc39.es/ecma262/#sec-object.getprototypeof
4100
+ // eslint-disable-next-line es/no-object-getprototypeof -- safe
4101
+ module.exports = CORRECT_PROTOTYPE_GETTER ? $Object.getPrototypeOf : function (O) {
4102
+ var object = toObject(O);
4103
+ if (hasOwn(object, IE_PROTO)) return object[IE_PROTO];
4104
+ var constructor = object.constructor;
4105
+ if (isCallable(constructor) && object instanceof constructor) {
4106
+ return constructor.prototype;
4107
+ } return object instanceof $Object ? ObjectPrototype : null;
4108
+ };
4109
+
4110
+
1267
4111
  /***/ }),
1268
4112
 
1269
4113
  /***/ 1625:
@@ -1327,6 +4171,43 @@ exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
1327
4171
  } : $propertyIsEnumerable;
1328
4172
 
1329
4173
 
4174
+ /***/ }),
4175
+
4176
+ /***/ 2967:
4177
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4178
+
4179
+ "use strict";
4180
+
4181
+ /* eslint-disable no-proto -- safe */
4182
+ var uncurryThisAccessor = __webpack_require__(6706);
4183
+ var isObject = __webpack_require__(34);
4184
+ var requireObjectCoercible = __webpack_require__(7750);
4185
+ var aPossiblePrototype = __webpack_require__(3506);
4186
+
4187
+ // `Object.setPrototypeOf` method
4188
+ // https://tc39.es/ecma262/#sec-object.setprototypeof
4189
+ // Works with __proto__ only. Old v8 can't work with null proto objects.
4190
+ // eslint-disable-next-line es/no-object-setprototypeof -- safe
4191
+ module.exports = Object.setPrototypeOf || ('__proto__' in {} ? function () {
4192
+ var CORRECT_SETTER = false;
4193
+ var test = {};
4194
+ var setter;
4195
+ try {
4196
+ setter = uncurryThisAccessor(Object.prototype, '__proto__', 'set');
4197
+ setter(test, []);
4198
+ CORRECT_SETTER = test instanceof Array;
4199
+ } catch (error) { /* empty */ }
4200
+ return function setPrototypeOf(O, proto) {
4201
+ requireObjectCoercible(O);
4202
+ aPossiblePrototype(proto);
4203
+ if (!isObject(O)) return O;
4204
+ if (CORRECT_SETTER) setter(O, proto);
4205
+ else O.__proto__ = proto;
4206
+ return O;
4207
+ };
4208
+ }() : undefined);
4209
+
4210
+
1330
4211
  /***/ }),
1331
4212
 
1332
4213
  /***/ 4270:
@@ -1447,6 +4328,30 @@ module.exports = function (key, value) {
1447
4328
  };
1448
4329
 
1449
4330
 
4331
+ /***/ }),
4332
+
4333
+ /***/ 1548:
4334
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4335
+
4336
+ "use strict";
4337
+
4338
+ var globalThis = __webpack_require__(4576);
4339
+ var fails = __webpack_require__(9039);
4340
+ var V8 = __webpack_require__(9519);
4341
+ var ENVIRONMENT = __webpack_require__(4215);
4342
+
4343
+ var structuredClone = globalThis.structuredClone;
4344
+
4345
+ module.exports = !!structuredClone && !fails(function () {
4346
+ // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
4347
+ // https://github.com/zloirock/core-js/issues/679
4348
+ if ((ENVIRONMENT === 'DENO' && V8 > 92) || (ENVIRONMENT === 'NODE' && V8 > 94) || (ENVIRONMENT === 'BROWSER' && V8 > 97)) return false;
4349
+ var buffer = new ArrayBuffer(8);
4350
+ var clone = structuredClone(buffer, { transfer: [buffer] });
4351
+ return buffer.byteLength !== 0 || clone.byteLength !== 8;
4352
+ });
4353
+
4354
+
1450
4355
  /***/ }),
1451
4356
 
1452
4357
  /***/ 4495:
@@ -1495,6 +4400,50 @@ module.exports = function (index, length) {
1495
4400
  };
1496
4401
 
1497
4402
 
4403
+ /***/ }),
4404
+
4405
+ /***/ 5854:
4406
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4407
+
4408
+ "use strict";
4409
+
4410
+ var toPrimitive = __webpack_require__(2777);
4411
+
4412
+ var $TypeError = TypeError;
4413
+
4414
+ // `ToBigInt` abstract operation
4415
+ // https://tc39.es/ecma262/#sec-tobigint
4416
+ module.exports = function (argument) {
4417
+ var prim = toPrimitive(argument, 'number');
4418
+ if (typeof prim == 'number') throw new $TypeError("Can't convert number to bigint");
4419
+ // eslint-disable-next-line es/no-bigint -- safe
4420
+ return BigInt(prim);
4421
+ };
4422
+
4423
+
4424
+ /***/ }),
4425
+
4426
+ /***/ 7696:
4427
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4428
+
4429
+ "use strict";
4430
+
4431
+ var toIntegerOrInfinity = __webpack_require__(1291);
4432
+ var toLength = __webpack_require__(8014);
4433
+
4434
+ var $RangeError = RangeError;
4435
+
4436
+ // `ToIndex` abstract operation
4437
+ // https://tc39.es/ecma262/#sec-toindex
4438
+ module.exports = function (it) {
4439
+ if (it === undefined) return 0;
4440
+ var number = toIntegerOrInfinity(it);
4441
+ var length = toLength(number);
4442
+ if (number !== length) throw new $RangeError('Wrong length or index');
4443
+ return length;
4444
+ };
4445
+
4446
+
1498
4447
  /***/ }),
1499
4448
 
1500
4449
  /***/ 5397:
@@ -1635,23 +4584,6 @@ test[TO_STRING_TAG] = 'z';
1635
4584
  module.exports = String(test) === '[object z]';
1636
4585
 
1637
4586
 
1638
- /***/ }),
1639
-
1640
- /***/ 655:
1641
- /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
1642
-
1643
- "use strict";
1644
-
1645
- var classof = __webpack_require__(6955);
1646
-
1647
- var $String = String;
1648
-
1649
- module.exports = function (argument) {
1650
- if (classof(argument) === 'Symbol') throw new TypeError('Cannot convert a Symbol value to a string');
1651
- return $String(argument);
1652
- };
1653
-
1654
-
1655
4587
  /***/ }),
1656
4588
 
1657
4589
  /***/ 6823:
@@ -1713,30 +4645,15 @@ module.exports = NATIVE_SYMBOL
1713
4645
  var DESCRIPTORS = __webpack_require__(3724);
1714
4646
  var fails = __webpack_require__(9039);
1715
4647
 
1716
- // V8 ~ Chrome 36-
1717
- // https://bugs.chromium.org/p/v8/issues/detail?id=3334
1718
- module.exports = DESCRIPTORS && fails(function () {
1719
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1720
- return Object.defineProperty(function () { /* empty */ }, 'prototype', {
1721
- value: 42,
1722
- writable: false
1723
- }).prototype !== 42;
1724
- });
1725
-
1726
-
1727
- /***/ }),
1728
-
1729
- /***/ 2812:
1730
- /***/ (function(module) {
1731
-
1732
- "use strict";
1733
-
1734
- var $TypeError = TypeError;
1735
-
1736
- module.exports = function (passed, required) {
1737
- if (passed < required) throw new $TypeError('Not enough arguments');
1738
- return passed;
1739
- };
4648
+ // V8 ~ Chrome 36-
4649
+ // https://bugs.chromium.org/p/v8/issues/detail?id=3334
4650
+ module.exports = DESCRIPTORS && fails(function () {
4651
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
4652
+ return Object.defineProperty(function () { /* empty */ }, 'prototype', {
4653
+ value: 42,
4654
+ writable: false
4655
+ }).prototype !== 42;
4656
+ });
1740
4657
 
1741
4658
 
1742
4659
  /***/ }),
@@ -1781,6 +4698,67 @@ module.exports = function (name) {
1781
4698
  };
1782
4699
 
1783
4700
 
4701
+ /***/ }),
4702
+
4703
+ /***/ 6573:
4704
+ /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
4705
+
4706
+ "use strict";
4707
+
4708
+ var DESCRIPTORS = __webpack_require__(3724);
4709
+ var defineBuiltInAccessor = __webpack_require__(2106);
4710
+ var isDetached = __webpack_require__(3238);
4711
+
4712
+ var ArrayBufferPrototype = ArrayBuffer.prototype;
4713
+
4714
+ if (DESCRIPTORS && !('detached' in ArrayBufferPrototype)) {
4715
+ defineBuiltInAccessor(ArrayBufferPrototype, 'detached', {
4716
+ configurable: true,
4717
+ get: function detached() {
4718
+ return isDetached(this);
4719
+ }
4720
+ });
4721
+ }
4722
+
4723
+
4724
+ /***/ }),
4725
+
4726
+ /***/ 7936:
4727
+ /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
4728
+
4729
+ "use strict";
4730
+
4731
+ var $ = __webpack_require__(6518);
4732
+ var $transfer = __webpack_require__(5636);
4733
+
4734
+ // `ArrayBuffer.prototype.transferToFixedLength` method
4735
+ // https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength
4736
+ if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
4737
+ transferToFixedLength: function transferToFixedLength() {
4738
+ return $transfer(this, arguments.length ? arguments[0] : undefined, false);
4739
+ }
4740
+ });
4741
+
4742
+
4743
+ /***/ }),
4744
+
4745
+ /***/ 8100:
4746
+ /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
4747
+
4748
+ "use strict";
4749
+
4750
+ var $ = __webpack_require__(6518);
4751
+ var $transfer = __webpack_require__(5636);
4752
+
4753
+ // `ArrayBuffer.prototype.transfer` method
4754
+ // https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfer
4755
+ if ($transfer) $({ target: 'ArrayBuffer', proto: true }, {
4756
+ transfer: function transfer() {
4757
+ return $transfer(this, arguments.length ? arguments[0] : undefined, true);
4758
+ }
4759
+ });
4760
+
4761
+
1784
4762
  /***/ }),
1785
4763
 
1786
4764
  /***/ 4114:
@@ -1833,124 +4811,88 @@ $({ target: 'Array', proto: true, arity: 1, forced: FORCED }, {
1833
4811
 
1834
4812
  /***/ }),
1835
4813
 
1836
- /***/ 4603:
4814
+ /***/ 7467:
1837
4815
  /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
1838
4816
 
1839
4817
  "use strict";
1840
4818
 
1841
- var defineBuiltIn = __webpack_require__(6840);
1842
- var uncurryThis = __webpack_require__(9504);
1843
- var toString = __webpack_require__(655);
1844
- var validateArgumentsLength = __webpack_require__(2812);
1845
-
1846
- var $URLSearchParams = URLSearchParams;
1847
- var URLSearchParamsPrototype = $URLSearchParams.prototype;
1848
- var append = uncurryThis(URLSearchParamsPrototype.append);
1849
- var $delete = uncurryThis(URLSearchParamsPrototype['delete']);
1850
- var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
1851
- var push = uncurryThis([].push);
1852
- var params = new $URLSearchParams('a=1&a=2&b=3');
1853
-
1854
- params['delete']('a', 1);
1855
- // `undefined` case is a Chromium 117 bug
1856
- // https://bugs.chromium.org/p/v8/issues/detail?id=14222
1857
- params['delete']('b', undefined);
1858
-
1859
- if (params + '' !== 'a=2') {
1860
- defineBuiltIn(URLSearchParamsPrototype, 'delete', function (name /* , value */) {
1861
- var length = arguments.length;
1862
- var $value = length < 2 ? undefined : arguments[1];
1863
- if (length && $value === undefined) return $delete(this, name);
1864
- var entries = [];
1865
- forEach(this, function (v, k) { // also validates `this`
1866
- push(entries, { key: k, value: v });
1867
- });
1868
- validateArgumentsLength(length, 1);
1869
- var key = toString(name);
1870
- var value = toString($value);
1871
- var index = 0;
1872
- var dindex = 0;
1873
- var found = false;
1874
- var entriesLength = entries.length;
1875
- var entry;
1876
- while (index < entriesLength) {
1877
- entry = entries[index++];
1878
- if (found || entry.key === key) {
1879
- found = true;
1880
- $delete(this, entry.key);
1881
- } else dindex++;
1882
- }
1883
- while (dindex < entriesLength) {
1884
- entry = entries[dindex++];
1885
- if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value);
1886
- }
1887
- }, { enumerable: true, unsafe: true });
1888
- }
4819
+ var arrayToReversed = __webpack_require__(7628);
4820
+ var ArrayBufferViewCore = __webpack_require__(4644);
4821
+
4822
+ var aTypedArray = ArrayBufferViewCore.aTypedArray;
4823
+ var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
4824
+ var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
4825
+
4826
+ // `%TypedArray%.prototype.toReversed` method
4827
+ // https://tc39.es/ecma262/#sec-%typedarray%.prototype.toreversed
4828
+ exportTypedArrayMethod('toReversed', function toReversed() {
4829
+ return arrayToReversed(aTypedArray(this), getTypedArrayConstructor(this));
4830
+ });
1889
4831
 
1890
4832
 
1891
4833
  /***/ }),
1892
4834
 
1893
- /***/ 7566:
4835
+ /***/ 4732:
1894
4836
  /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
1895
4837
 
1896
4838
  "use strict";
1897
4839
 
1898
- var defineBuiltIn = __webpack_require__(6840);
4840
+ var ArrayBufferViewCore = __webpack_require__(4644);
1899
4841
  var uncurryThis = __webpack_require__(9504);
1900
- var toString = __webpack_require__(655);
1901
- var validateArgumentsLength = __webpack_require__(2812);
1902
-
1903
- var $URLSearchParams = URLSearchParams;
1904
- var URLSearchParamsPrototype = $URLSearchParams.prototype;
1905
- var getAll = uncurryThis(URLSearchParamsPrototype.getAll);
1906
- var $has = uncurryThis(URLSearchParamsPrototype.has);
1907
- var params = new $URLSearchParams('a=1');
1908
-
1909
- // `undefined` case is a Chromium 117 bug
1910
- // https://bugs.chromium.org/p/v8/issues/detail?id=14222
1911
- if (params.has('a', 2) || !params.has('a', undefined)) {
1912
- defineBuiltIn(URLSearchParamsPrototype, 'has', function has(name /* , value */) {
1913
- var length = arguments.length;
1914
- var $value = length < 2 ? undefined : arguments[1];
1915
- if (length && $value === undefined) return $has(this, name);
1916
- var values = getAll(this, name); // also validates `this`
1917
- validateArgumentsLength(length, 1);
1918
- var value = toString($value);
1919
- var index = 0;
1920
- while (index < values.length) {
1921
- if (values[index++] === value) return true;
1922
- } return false;
1923
- }, { enumerable: true, unsafe: true });
1924
- }
4842
+ var aCallable = __webpack_require__(9306);
4843
+ var arrayFromConstructorAndList = __webpack_require__(5370);
4844
+
4845
+ var aTypedArray = ArrayBufferViewCore.aTypedArray;
4846
+ var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
4847
+ var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
4848
+ var sort = uncurryThis(ArrayBufferViewCore.TypedArrayPrototype.sort);
4849
+
4850
+ // `%TypedArray%.prototype.toSorted` method
4851
+ // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted
4852
+ exportTypedArrayMethod('toSorted', function toSorted(compareFn) {
4853
+ if (compareFn !== undefined) aCallable(compareFn);
4854
+ var O = aTypedArray(this);
4855
+ var A = arrayFromConstructorAndList(getTypedArrayConstructor(O), O);
4856
+ return sort(A, compareFn);
4857
+ });
1925
4858
 
1926
4859
 
1927
4860
  /***/ }),
1928
4861
 
1929
- /***/ 8721:
4862
+ /***/ 9577:
1930
4863
  /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
1931
4864
 
1932
4865
  "use strict";
1933
4866
 
1934
- var DESCRIPTORS = __webpack_require__(3724);
1935
- var uncurryThis = __webpack_require__(9504);
1936
- var defineBuiltInAccessor = __webpack_require__(2106);
4867
+ var arrayWith = __webpack_require__(9928);
4868
+ var ArrayBufferViewCore = __webpack_require__(4644);
4869
+ var isBigIntArray = __webpack_require__(1108);
4870
+ var toIntegerOrInfinity = __webpack_require__(1291);
4871
+ var toBigInt = __webpack_require__(5854);
1937
4872
 
1938
- var URLSearchParamsPrototype = URLSearchParams.prototype;
1939
- var forEach = uncurryThis(URLSearchParamsPrototype.forEach);
1940
-
1941
- // `URLSearchParams.prototype.size` getter
1942
- // https://github.com/whatwg/url/pull/734
1943
- if (DESCRIPTORS && !('size' in URLSearchParamsPrototype)) {
1944
- defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {
1945
- get: function size() {
1946
- var count = 0;
1947
- forEach(this, function () { count++; });
1948
- return count;
1949
- },
1950
- configurable: true,
1951
- enumerable: true
1952
- });
1953
- }
4873
+ var aTypedArray = ArrayBufferViewCore.aTypedArray;
4874
+ var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor;
4875
+ var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
4876
+
4877
+ var PROPER_ORDER = !!function () {
4878
+ try {
4879
+ // eslint-disable-next-line no-throw-literal, es/no-typed-arrays, es/no-array-prototype-with -- required for testing
4880
+ new Int8Array(1)['with'](2, { valueOf: function () { throw 8; } });
4881
+ } catch (error) {
4882
+ // some early implementations, like WebKit, does not follow the final semantic
4883
+ // https://github.com/tc39/proposal-change-array-by-copy/pull/86
4884
+ return error === 8;
4885
+ }
4886
+ }();
4887
+
4888
+ // `%TypedArray%.prototype.with` method
4889
+ // https://tc39.es/ecma262/#sec-%typedarray%.prototype.with
4890
+ exportTypedArrayMethod('with', { 'with': function (index, value) {
4891
+ var O = aTypedArray(this);
4892
+ var relativeIndex = toIntegerOrInfinity(index);
4893
+ var actualValue = isBigIntArray(O) ? toBigInt(value) : +value;
4894
+ return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue);
4895
+ } }['with'], !PROPER_ORDER);
1954
4896
 
1955
4897
 
1956
4898
  /***/ })
@@ -2083,15 +5025,21 @@ if (typeof window !== 'undefined') {
2083
5025
  var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__(9274);
2084
5026
  // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
2085
5027
  var es_array_push = __webpack_require__(4114);
2086
- // EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.delete.js
2087
- var web_url_search_params_delete = __webpack_require__(4603);
2088
- // EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.has.js
2089
- var web_url_search_params_has = __webpack_require__(7566);
2090
- // EXTERNAL MODULE: ./node_modules/core-js/modules/web.url-search-params.size.js
2091
- var web_url_search_params_size = __webpack_require__(8721);
2092
- // EXTERNAL MODULE: ./node_modules/js-audio-recorder/index.js
2093
- var js_audio_recorder = __webpack_require__(7478);
2094
- var js_audio_recorder_default = /*#__PURE__*/__webpack_require__.n(js_audio_recorder);
5028
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.detached.js
5029
+ var es_array_buffer_detached = __webpack_require__(6573);
5030
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer.js
5031
+ var es_array_buffer_transfer = __webpack_require__(8100);
5032
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array-buffer.transfer-to-fixed-length.js
5033
+ var es_array_buffer_transfer_to_fixed_length = __webpack_require__(7936);
5034
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-reversed.js
5035
+ var es_typed_array_to_reversed = __webpack_require__(7467);
5036
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.to-sorted.js
5037
+ var es_typed_array_to_sorted = __webpack_require__(4732);
5038
+ // EXTERNAL MODULE: ./node_modules/core-js/modules/es.typed-array.with.js
5039
+ var es_typed_array_with = __webpack_require__(9577);
5040
+ // EXTERNAL MODULE: ./node_modules/recorder-core/src/recorder-core.js
5041
+ var recorder_core = __webpack_require__(2346);
5042
+ var recorder_core_default = /*#__PURE__*/__webpack_require__.n(recorder_core);
2095
5043
  ;// CONCATENATED MODULE: ./node_modules/axios/lib/helpers/bind.js
2096
5044
 
2097
5045
 
@@ -6085,7 +9033,7 @@ axios.default = axios;
6085
9033
  const audioConfig = {
6086
9034
  // here: "https://wiki.keepsoft.net:39002/uploadAudio/here.mp3",
6087
9035
  here: "https://saas.keepsoft.net:20003/uploadAudio/here.mp3",
6088
- xiaogui: ['xiaoguixiaogui', ' xiaohuixiaohui', 'xiaoguaixiaoguai', 'xiaokuixiaokui']
9036
+ xiaogui: ["xiaoguixiaogui", " xiaohuixiaohui", "xiaoguaixiaoguai", "xiaokuixiaokui"]
6089
9037
  };
6090
9038
  ;// CONCATENATED MODULE: ./node_modules/pinyin-pro/dist/index.mjs
6091
9039
  const DoubleUnicodePrefixReg = /^[\uD800-\uDBFF]$/;
@@ -31229,13 +34177,113 @@ function segment(word, options) {
31229
34177
 
31230
34178
 
31231
34179
 
34180
+ ;// CONCATENATED MODULE: ./src/package/src/utils/wsconnecter.js
34181
+ /**
34182
+ * Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
34183
+ * Reserved. MIT License (https://opensource.org/licenses/MIT)
34184
+ */
34185
+ /* 2021-2023 by zhaoming,mali aihealthx.com */
34186
+
34187
+ function WebSocketConnectMethod(config) {
34188
+ //定义socket连接方法类
34189
+
34190
+ var speechSokt;
34191
+ var msgHandle = config.msgHandle;
34192
+ var stateHandle = config.stateHandle;
34193
+ var url = config.url || "wss://172.16.103.188:10096/";
34194
+ var mode = "2pass";
34195
+ this.wsStart = function (modeStr = "2pass") {
34196
+ console.log(modeStr);
34197
+ mode = modeStr;
34198
+ if (url.match(/wss:\S*|ws:\S*/)) {
34199
+ console.log("url" + url);
34200
+ } else {
34201
+ alert("请检查wss地址正确性");
34202
+ return 0;
34203
+ }
34204
+ if ("WebSocket" in window) {
34205
+ speechSokt = new WebSocket(url); // 定义socket连接对象
34206
+ speechSokt.onopen = function (e) {
34207
+ onOpen(e);
34208
+ }; // 定义响应函数
34209
+ speechSokt.onclose = function (e) {
34210
+ console.log("onclose ws!", e);
34211
+ onClose(e);
34212
+ };
34213
+ speechSokt.onmessage = function (e) {
34214
+ onMessage(e);
34215
+ };
34216
+ speechSokt.onerror = function (e) {
34217
+ onError(e);
34218
+ };
34219
+ return 1;
34220
+ } else {
34221
+ alert("当前浏览器不支持 WebSocket");
34222
+ return 0;
34223
+ }
34224
+ };
34225
+
34226
+ // 定义停止与发送函数
34227
+ this.wsStop = function () {
34228
+ if (speechSokt != undefined) {
34229
+ console.log("stop ws!");
34230
+ speechSokt.close();
34231
+ }
34232
+ };
34233
+ this.wsSend = function (oneData) {
34234
+ if (speechSokt == undefined) return;
34235
+ if (speechSokt.readyState === 1) {
34236
+ // 0:CONNECTING, 1:OPEN, 2:CLOSING, 3:CLOSED
34237
+
34238
+ speechSokt.send(oneData);
34239
+ }
34240
+ };
34241
+
34242
+ // SOCEKT连接中的消息与状态响应
34243
+ function onOpen(e) {
34244
+ // 发送json
34245
+ var chunk_size = [5, 10, 5];
34246
+ var request = {
34247
+ "chunk_size": chunk_size,
34248
+ "wav_name": "h5",
34249
+ "is_speaking": true,
34250
+ "chunk_interval": 10,
34251
+ "itn": false,
34252
+ "mode": mode
34253
+ };
34254
+ var hotwords = null;
34255
+ if (hotwords != null) {
34256
+ request.hotwords = hotwords;
34257
+ }
34258
+ console.log(JSON.stringify(request));
34259
+ speechSokt.send(JSON.stringify(request));
34260
+ console.log("连接成功");
34261
+ stateHandle(0);
34262
+ }
34263
+ function onClose(e) {
34264
+ // stateHandle(1);
34265
+ }
34266
+ function onMessage(e) {
34267
+ msgHandle(e);
34268
+ }
34269
+ function onError(e) {
34270
+ // info_div.innerHTML = "连接" + e;
34271
+ console.log(e);
34272
+ stateHandle(2);
34273
+ }
34274
+ }
34275
+ // EXTERNAL MODULE: ./node_modules/recorder-core/src/extensions/waveview.js
34276
+ var waveview = __webpack_require__(9243);
31232
34277
  ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-82.use[1]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/package/src/main.vue?vue&type=script&setup=true&lang=js
31233
34278
 
31234
34279
 
31235
34280
 
31236
34281
 
31237
34282
 
31238
- const _withScopeId = n => (_pushScopeId("data-v-7c916d88"), n = n(), _popScopeId(), n);
34283
+
34284
+
34285
+
34286
+ const _withScopeId = n => (_pushScopeId("data-v-16bd8825"), n = n(), _popScopeId(), n);
31239
34287
  const _hoisted_1 = ["src"];
31240
34288
  const _hoisted_2 = {
31241
34289
  key: 0,
@@ -31283,6 +34331,9 @@ const _hoisted_19 = ["src"];
31283
34331
 
31284
34332
 
31285
34333
 
34334
+
34335
+ //可选的插件支持项,这个是波形可视化插件
34336
+
31286
34337
  /* harmony default export */ var mainvue_type_script_setup_true_lang_js = ({
31287
34338
  __name: 'main',
31288
34339
  props: {
@@ -31351,6 +34402,10 @@ const _hoisted_19 = ["src"];
31351
34402
  bot_id: "7431129126334955530"
31352
34403
  })
31353
34404
  },
34405
+ audioWs: {
34406
+ type: String,
34407
+ default: "wss://172.16.103.188:10096/"
34408
+ },
31354
34409
  wsServer: {
31355
34410
  type: String,
31356
34411
  default: "wss://wiki.keepsoft.net:39002/ws"
@@ -31393,14 +34448,8 @@ const _hoisted_19 = ["src"];
31393
34448
  setup(__props, {
31394
34449
  expose: __expose
31395
34450
  }) {
31396
- let pCtx = null;
31397
- let pCanvas = null;
31398
- let drawPlayId = null;
31399
- let wenetWs = null;
34451
+ //必须引入的核心
31400
34452
  let audioSound = null;
31401
- let recognition = null; //浏览器实时监听API
31402
- // let instructWs = null;
31403
-
31404
34453
  const contentRef = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.ref)(null);
31405
34454
  const scrollContainer = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.ref)(null);
31406
34455
  const props = __props;
@@ -31416,26 +34465,26 @@ const _hoisted_19 = ["src"];
31416
34465
  audioSoundType: "",
31417
34466
  recorderCode: 0,
31418
34467
  //1唤醒 0沉睡
31419
- recorder: new (js_audio_recorder_default())({
31420
- sampleBits: 16,
31421
- // 采样位数,支持 8 或 16,默认是16
31422
- sampleRate: 48000,
31423
- // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
31424
- numChannels: 1 // 声道,支持 1 或 2, 默认是1
31425
- // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
31426
- }),
31427
- recorder2: new (js_audio_recorder_default())({
34468
+ recorder: new (recorder_core_default())({
31428
34469
  sampleBits: 16,
31429
34470
  // 采样位数,支持 8 或 16,默认是16
31430
34471
  sampleRate: 48000,
31431
34472
  // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
31432
- numChannels: 1 // 声道,支持 1 或 2, 默认是1
34473
+ numChannels: 1,
34474
+ // 声道,支持 1 或 2, 默认是1
34475
+ onProcess: recProcess
31433
34476
  // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
31434
34477
  })
31435
34478
  });
34479
+ const wave = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.ref)(null);
34480
+ const waveRef = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.ref)(null);
34481
+ const wsconnecter = new WebSocketConnectMethod({
34482
+ url: props.audioWs,
34483
+ msgHandle: getJsonMessage,
34484
+ stateHandle: getConnState
34485
+ });
31436
34486
  (0,external_commonjs_vue_commonjs2_vue_root_Vue_.onMounted)(() => {
31437
- // startApiMonitorAudio();
31438
- setRecording();
34487
+ startApiMonitorAudio();
31439
34488
  });
31440
34489
  const startApiMonitorAudio = () => {
31441
34490
  if (props.mode == "audio") {
@@ -31443,14 +34492,81 @@ const _hoisted_19 = ["src"];
31443
34492
  }
31444
34493
  };
31445
34494
 
34495
+ // 语音识别结果; 对jsonMsg数据解析,将识别结果附加到编辑框中
34496
+ function getJsonMessage(jsonMsg) {
34497
+ const data = JSON.parse(jsonMsg.data);
34498
+ // console.log(data);
34499
+ if (state.isAudio === "start") {
34500
+ state.input = data.text;
34501
+ } else {
34502
+ if (data.mode === "2pass-offline") {
34503
+ //唤醒状态下请求后端
34504
+ if (state.recorderCode === 1) {
34505
+ getAnswer(data.text);
34506
+ } else {
34507
+ //沉睡状态下识别是否是唤醒词
34508
+ discernHere(data.text);
34509
+ }
34510
+ }
34511
+ }
34512
+ }
34513
+
34514
+ // 连接状态响应
34515
+ function getConnState(connState) {
34516
+ if (connState === 0) {//on open
34517
+ } else if (connState === 1) {
34518
+ //close
34519
+ startRecognition();
34520
+ } else if (connState === 2) {
34521
+ //error
34522
+ console.log("connecttion error");
34523
+ startRecognition();
34524
+ }
34525
+ }
34526
+ let sampleBuf = new Int16Array();
34527
+ function recProcess(buffer, powerLevel, bufferDuration, bufferSampleRate) {
34528
+ if (wave.value) wave.value?.input(buffer[buffer.length - 1], powerLevel, bufferSampleRate);
34529
+ var data_48k = buffer[buffer.length - 1];
34530
+ var array_48k = new Array(data_48k);
34531
+ var data_16k = recorder_core_default().SampleData(array_48k, bufferSampleRate, 16000).data;
34532
+ sampleBuf = Int16Array.from([...sampleBuf, ...data_16k]);
34533
+ var chunk_size = 960; // for asr chunk_size [5, 10, 5]
34534
+ while (sampleBuf.length >= chunk_size) {
34535
+ const sendBuf = sampleBuf.slice(0, chunk_size);
34536
+ sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
34537
+ wsconnecter.wsSend(sendBuf);
34538
+ }
34539
+ }
34540
+ const startRecognition = () => {
34541
+ const recognition = wsconnecter.wsStart();
34542
+ if (recognition === 1) {
34543
+ console.log("recognition start");
34544
+ setRecording();
34545
+ } else {
34546
+ startRecognition();
34547
+ console.log("recognition error");
34548
+ }
34549
+ };
34550
+ const closeRecognition = () => {
34551
+ wsconnecter.wsStop();
34552
+ state.recorder.pause();
34553
+ };
34554
+
34555
+ // 开始监听
34556
+ const setRecording = () => {
34557
+ state.recorder.open(() => {
34558
+ console.log("recorder open");
34559
+ state.recorder.start();
34560
+ });
34561
+ };
34562
+
31446
34563
  // 识别小贵
31447
34564
  const discernHere = val => {
31448
34565
  let pinyinStr = pinyin(val, {
31449
34566
  toneType: "none",
31450
34567
  type: "array"
31451
34568
  });
31452
- pinyinStr = pinyinStr.join("");
31453
- // console.log(pinyinStr, "pinyinStr");
34569
+ pinyinStr = pinyinStr.filter(i => i !== "," && i !== "。").join("");
31454
34570
  let {
31455
34571
  xiaogui
31456
34572
  } = audioConfig;
@@ -31460,230 +34576,46 @@ const _hoisted_19 = ["src"];
31460
34576
  }
31461
34577
  if (bol) {
31462
34578
  state.recorderCode = 1;
31463
- // recognition.stop();
31464
34579
  iAmHere();
31465
- window.setTimeout(() => {
31466
- setRecording();
31467
- }, 2500);
31468
34580
  }
31469
34581
  };
31470
- const throttle = (func, wait) => {
31471
- let timeout = null;
31472
- let lastArgs = [];
31473
- return function (...args) {
31474
- if (!timeout) {
31475
- func.apply(this, args);
31476
- lastArgs = args;
31477
- timeout = setTimeout(() => {
31478
- timeout = null;
31479
- }, wait);
31480
- } else {
31481
- lastArgs = args;
31482
- }
31483
- };
31484
- };
31485
- const throttledLogMessage = throttle(discernHere, 2000);
31486
- const startRecognition = () => {
31487
- recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
31488
- recognition.continuous = true; // 设置为 true 以持续监听
31489
- recognition.interimResults = true; // 不显示中间结果
31490
- recognition.lang = "ZH-cn";
31491
- recognition.onresult = function (event) {
31492
- var last = event.results.length - 1;
31493
- var text = event.results[last][0].transcript;
31494
- if (props.isDebug) {
31495
- console.log("你说的是: " + text);
31496
- }
31497
- if (state.recorderCode === 0) {
31498
- discernHere(text);
31499
- }
31500
- };
31501
- recognition.onend = function () {
31502
- console.log("Recognition ended.");
31503
- // 这里可以采取措施,比如重新启动语音识别
31504
- restartRecognition();
31505
- // alert("监听到1分钟未说话,刷新页面后可使用!");
31506
- };
31507
- recognition.onerror = function (event) {
31508
- console.error("Error occurred in recognition: " + event.error);
31509
- // 这里也可以采取措施,比如重新启动语音识别
31510
- restartRecognition();
34582
+ const getAnswer = text => {
34583
+ // 拿到的语音进行问答
34584
+ let option = {
34585
+ searchText: text,
34586
+ use_tts: "True",
34587
+ coze_info: props.cozeInfo || {}
31511
34588
  };
31512
- recognition.start();
31513
- };
31514
- const restartRecognition = () => {
31515
- console.log("Restarting recognition...");
31516
- startRecognition();
31517
- };
31518
-
31519
- // 唤醒后的录音
31520
- const setRecording = () => {
31521
- // state.recorder.stop();
31522
- state.recorder.start().then(() => {
31523
- window.setTimeout(() => {
31524
- let wavBlob = state.recorder.getWAVBlob();
31525
- let newbolb = new Blob([wavBlob], {
31526
- type: "audio/wav"
31527
- });
31528
- //获取当时时间戳作为文件名
31529
- let fileOfBlob = new File([newbolb], new Date().getTime() + ".wav");
31530
-
31531
- // 本地播放录音文件流
31532
- if (props.isDebug) {
31533
- let sound = new Audio();
31534
- let src = URL.createObjectURL(fileOfBlob);
31535
- sound.src = src;
31536
- sound.play();
34589
+ state.recorderCode = 0;
34590
+ searchText(option).then(q => {
34591
+ let data = q.data;
34592
+ if (data && data.code == 200) {
34593
+ // 讲回答后的内容返回给业务系统
34594
+ if (props.searchTextCallback) {
34595
+ props.searchTextCallback(data.detail[0]);
31537
34596
  }
31538
- state.recorder.stop();
31539
- state.recorderCode = 0;
31540
- let formData = new FormData();
31541
- formData.append("modelName", "medium");
31542
- formData.append("audio", fileOfBlob);
31543
- uploadWavFile(formData).then(result => {
31544
- let res = result.data;
31545
- if (res.code == 200) {
31546
- let {
31547
- answer: audioToText
31548
- } = res.detail.content;
31549
- let text = audioToText;
31550
-
31551
- // let text = "回到2023年7月22日时刻";
31552
-
31553
- // 拿到的语音进行问答
31554
- let option = {
31555
- searchText: text,
31556
- use_tts: "True",
31557
- coze_info: props.cozeInfo || {}
31558
- };
31559
- searchText(option).then(q => {
31560
- let data = q.data;
31561
- if (data && data.code == 200) {
31562
- // 检索场景
31563
- // matching(text, data.detail[0]);
31564
-
31565
- // 讲回答后的内容返回给业务系统
31566
- if (props.searchTextCallback) {
31567
- props.searchTextCallback(data.detail[0]);
31568
- }
31569
- let {
31570
- ttsMaleAddress
31571
- } = data.detail[0];
31572
- // 播放回答内容和进行小G动作
31573
- if (ttsMaleAddress) {
31574
- playAudio(ttsMaleAddress, "sys");
31575
- }
31576
- // if (state.findMatch && state.findMatch.fun) {
31577
- // if (state.findMatch.trigger == "together") {
31578
- // state.findMatch.fun({
31579
- // ...data.detail[0],
31580
- // });
31581
- // }
31582
- // }
31583
- }
31584
- }).catch(err => {
31585
- console.error("问答错误");
31586
- console.error(err);
31587
- });
31588
- }
31589
- }).catch(err => {
31590
- console.error("语音识别错误");
31591
- console.error(err);
31592
- });
31593
-
31594
- // recognition.start();
31595
- }, 5 * 1000);
31596
- });
31597
- };
31598
- const sendRecorder = () => {
31599
- let wavBlob = state.recorder.getWAVBlob();
31600
- let newbolb = new Blob([wavBlob], {
31601
- type: "audio/wav"
34597
+ let {
34598
+ ttsMaleAddress
34599
+ } = data.detail[0];
34600
+ // 播放回答内容和进行小G动作
34601
+ if (ttsMaleAddress) {
34602
+ playAudio(ttsMaleAddress, "sys");
34603
+ }
34604
+ }
34605
+ }).catch(err => {
34606
+ console.error("问答错误");
34607
+ console.error(err);
31602
34608
  });
31603
- //获取当时时间戳作为文件名
31604
- let fileOfBlob = new File([newbolb], new Date().getTime() + ".wav");
31605
-
31606
- // 本地播放录音文件流
31607
- // let sound = new Audio();
31608
- // let src = URL.createObjectURL(fileOfBlob);
31609
- // sound.src = src;
31610
- // sound.play();
31611
- // wenetWs.send(fileOfBlob);
31612
-
31613
- if (wenetWs.readyState == 1) {
31614
- wenetWs.send(fileOfBlob);
31615
- }
31616
- state.recorder.start();
31617
34609
  };
31618
34610
  const searchText = data => {
31619
34611
  let url = props.qaServer;
31620
34612
  return lib_axios.post(url, data);
31621
34613
  };
31622
- const uploadWavFile = data => {
31623
- let url = props.audioServer;
31624
- return lib_axios.post(url, data);
31625
- };
31626
34614
  const iAmHere = () => {
31627
34615
  var url = audioConfig.here;
31628
34616
  window.setTimeout(() => {
31629
34617
  playAudio(url);
31630
- }, 1000);
31631
- };
31632
- const componentDidMount = () => {
31633
- pCanvas = document.getElementById("playChart");
31634
- pCtx = pCanvas.getContext("2d");
31635
- };
31636
- const drawPlay = () => {
31637
- // 用requestAnimationFrame稳定60fps绘制
31638
- drawPlayId = requestAnimationFrame(drawPlay);
31639
-
31640
- // 实时获取音频大小数据
31641
- let dataArray = state.recorder2.getRecordAnalyseData(),
31642
- bufferLength = dataArray.length;
31643
-
31644
- // 填充背景色
31645
- pCtx.fillStyle = "rgb(200, 200, 200)";
31646
- pCtx.fillRect(0, 0, pCanvas.width, pCanvas.height);
31647
-
31648
- // 设定波形绘制颜色
31649
- pCtx.lineWidth = 2;
31650
- pCtx.strokeStyle = "rgb(0, 0, 0)";
31651
- pCtx.beginPath();
31652
- var sliceWidth = pCanvas.width * 1.0 / bufferLength,
31653
- // 一个点占多少位置,共有bufferLength个点要绘制
31654
- x = 0; // 绘制点的x轴位置
31655
-
31656
- for (var i = 0; i < bufferLength; i++) {
31657
- var v = dataArray[i] / 128.0;
31658
- var y = v * pCanvas.height / 2;
31659
- if (i === 0) {
31660
- // 第一个点
31661
- pCtx.moveTo(x, y);
31662
- } else {
31663
- // 剩余的点
31664
- pCtx.lineTo(x, y);
31665
- }
31666
- // 依次平移,绘制所有点
31667
- x += sliceWidth;
31668
- }
31669
- pCtx.lineTo(pCanvas.width, pCanvas.height / 2);
31670
- pCtx.stroke();
31671
- };
31672
- const moveElement = event => {
31673
- event.preventDefault();
31674
- let ElWrap = contentRef.value;
31675
- let X = event.clientX - ElWrap.offsetLeft;
31676
- let Y = event.clientY - ElWrap.offsetTop;
31677
- // 添加鼠标移动事件
31678
- document.addEventListener("mousemove", move);
31679
- function move(event) {
31680
- ElWrap.style.left = event.clientX - X + "px";
31681
- ElWrap.style.top = event.clientY - Y + "px";
31682
- }
31683
- // 添加鼠标抬起事件,鼠标抬起,将事件移除
31684
- document.addEventListener("mouseup", () => {
31685
- document.removeEventListener("mousemove", move);
31686
- });
34618
+ }, 500);
31687
34619
  };
31688
34620
  const closeQaDrawer = () => {
31689
34621
  if (state.isRequireIng) {
@@ -31706,15 +34638,12 @@ const _hoisted_19 = ["src"];
31706
34638
  val: text,
31707
34639
  qaType: "local"
31708
34640
  });
31709
- window.setTimeout(() => {
31710
- componentDidMount();
31711
- }, 200);
31712
34641
  } else {
31713
34642
  closeQaDrawer();
31714
34643
  }
31715
34644
  };
31716
34645
  const scrollToBottom = () => {
31717
- scrollContainer.value.scrollTop = scrollContainer.value.scrollHeight;
34646
+ scrollContainer.value.scrollTop = scrollContainer.value?.scrollHeight;
31718
34647
  };
31719
34648
  const resetQa = () => {
31720
34649
  let lastStep = state.list[state.list.length - 2];
@@ -31756,31 +34685,11 @@ const _hoisted_19 = ["src"];
31756
34685
  }
31757
34686
  }, 50);
31758
34687
  };
31759
-
31760
- // 关键字匹配
31761
- const matching = (text, params) => {
31762
- let findMatch = {};
31763
- state.findMatch = {};
31764
- if (props.eventFun && props.eventFun.length) {
31765
- findMatch = props.eventFun.find(q => {
31766
- return q.keywords.some(t => text.indexOf(t) != -1);
31767
- });
31768
- }
31769
- if (findMatch) {
31770
- state.findMatch = {
31771
- ...findMatch,
31772
- params
31773
- };
31774
- }
31775
- };
31776
34688
  const sendAi = () => {
31777
34689
  if (state.isRequireIng) {
31778
34690
  return;
31779
34691
  }
31780
34692
  let text = state.input;
31781
-
31782
- // 执行方法匹配
31783
- matching(text);
31784
34693
  if (text) {
31785
34694
  let param = {
31786
34695
  type: 2,
@@ -31799,7 +34708,7 @@ const _hoisted_19 = ["src"];
31799
34708
  };
31800
34709
  state.list.push({
31801
34710
  type: 1,
31802
- value: `${props.waitTxt} <span class='ellipsisText'></span>`
34711
+ value: `${props.waitTxt} <span class="ellipsisText"></span>`
31803
34712
  });
31804
34713
  scrollToBottom();
31805
34714
  state.isRequireIng = true;
@@ -31822,10 +34731,61 @@ const _hoisted_19 = ["src"];
31822
34731
  state.list.splice(state.list.length - 1, 1);
31823
34732
  state.list.push({
31824
34733
  type: 1,
31825
- value: `<span style='color:red'>问答出现错误,请联系管理员!</span> `
34734
+ value: `<span style="color:red">问答出现错误,请联系管理员!</span> `
31826
34735
  });
31827
34736
  });
31828
34737
  };
34738
+ const startRecording = () => {
34739
+ state.isAudio = "loading";
34740
+ state.recorderCode = 0;
34741
+ closeRecognition();
34742
+ const recognition = wsconnecter.wsStart("offline");
34743
+ if (recognition === 1) {
34744
+ state.isAudio = "start";
34745
+ state.recorder.resume();
34746
+ if (waveRef.value) {
34747
+ //创建音频可视化图形绘制对象
34748
+ wave.value = recorder_core_default().WaveView({
34749
+ elem: waveRef.value
34750
+ });
34751
+ }
34752
+ } else {
34753
+ startRecording();
34754
+ }
34755
+ };
34756
+ const stopRecording = () => {
34757
+ state.isAudio = "end";
34758
+ wave.value = null;
34759
+ closeRecognition();
34760
+ startRecognition();
34761
+ };
34762
+
34763
+ //****************************************公共方法************************************
34764
+ const copyTextToClipboard = text => {
34765
+ const inputElement = document.createElement("input");
34766
+ inputElement.value = text;
34767
+ document.body.appendChild(inputElement);
34768
+ inputElement.select();
34769
+ document.execCommand("copy");
34770
+ document.body.removeChild(inputElement);
34771
+ };
34772
+ const moveElement = event => {
34773
+ event.preventDefault();
34774
+ let ElWrap = contentRef.value;
34775
+ let X = event.clientX - ElWrap.offsetLeft;
34776
+ let Y = event.clientY - ElWrap.offsetTop;
34777
+ // 添加鼠标移动事件
34778
+ document.addEventListener("mousemove", move);
34779
+ function move(event) {
34780
+ ElWrap.style.left = event.clientX - X + "px";
34781
+ ElWrap.style.top = event.clientY - Y + "px";
34782
+ }
34783
+
34784
+ // 添加鼠标抬起事件,鼠标抬起,将事件移除
34785
+ document.addEventListener("mouseup", () => {
34786
+ document.removeEventListener("mousemove", move);
34787
+ });
34788
+ };
31829
34789
 
31830
34790
  // 语音播放
31831
34791
  const playAudio = (audioUrl, type) => {
@@ -31866,74 +34826,8 @@ const _hoisted_19 = ["src"];
31866
34826
  });
31867
34827
  }, 100);
31868
34828
  };
31869
- const startRecording = () => {
31870
- state.isAudio = "loading";
31871
- js_audio_recorder_default().getPermission().then(() => {
31872
- state.recorder2.start().then(() => {
31873
- state.isAudio = "start";
31874
- console.log("开始录音");
31875
- drawPlay();
31876
- // 开始录音
31877
- }, error => {
31878
- state.isAudio = "end";
31879
- // 出错了
31880
- console.log(`${error} : 1`);
31881
- });
31882
- }, error => {
31883
- state.isAudio = "end";
31884
- // this.$message({
31885
- // message: "请先允许该网页使用麦克风",
31886
- // type: "info",
31887
- // });
31888
- console.log(`${error} : 2`);
31889
- });
31890
- };
31891
- const stopRecording = () => {
31892
- state.isAudio = "end";
31893
- uploadWAVData();
31894
- };
31895
- const uploadWAVData = () => {
31896
- var wavBlob = state.recorder2.getWAVBlob();
31897
- var formData = new FormData();
31898
- const newbolb = new Blob([wavBlob], {
31899
- type: "audio/wav"
31900
- });
31901
- //获取当时时间戳作为文件名
31902
- const fileOfBlob = new File([newbolb], new Date().getTime() + ".wav");
31903
-
31904
- // 本地播放录音文件流
31905
- // let sound = new Audio();
31906
- // let src = URL.createObjectURL(fileOfBlob);
31907
- // sound.src = src;
31908
- // sound.play();
31909
- // return;
31910
-
31911
- formData.append("modelName", "medium");
31912
- formData.append("audio", fileOfBlob);
31913
- uploadWavFile(formData).then(result => {
31914
- let res = result.data;
31915
- if (res.code == 200) {
31916
- let {
31917
- answer: audioToText
31918
- } = res.detail.content;
31919
- state.input = audioToText;
31920
- }
31921
- }).catch(err => {
31922
- let info = err.response.data.detail.error;
31923
- state.input = info;
31924
- });
31925
- };
31926
- const copyTextToClipboard = text => {
31927
- const inputElement = document.createElement("input");
31928
- inputElement.value = text;
31929
- document.body.appendChild(inputElement);
31930
- inputElement.select();
31931
- document.execCommand("copy");
31932
- document.body.removeChild(inputElement);
31933
- };
31934
34829
  __expose({
31935
- searchText,
31936
- uploadWavFile
34830
+ searchText
31937
34831
  });
31938
34832
  return (_ctx, _cache) => {
31939
34833
  return (0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementBlock)("div", {
@@ -32014,8 +34908,10 @@ const _hoisted_19 = ["src"];
32014
34908
  maxRows: 4
32015
34909
  },
32016
34910
  onKeyup: (0,external_commonjs_vue_commonjs2_vue_root_Vue_.withKeys)(sendAi, ["enter"])
32017
- }, "\r\n ", 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_.vModelText, state.input]]), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("div", _hoisted_13, [props.useAudio ? ((0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementBlock)("p", _hoisted_14, [(0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("canvas", {
34911
+ }, "\r\n ", 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_.vModelText, state.input]]), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("div", _hoisted_13, [props.useAudio ? ((0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementBlock)("p", _hoisted_14, [(0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("span", {
32018
34912
  id: "playChart",
34913
+ ref_key: "waveRef",
34914
+ ref: waveRef,
32019
34915
  class: (0,external_commonjs_vue_commonjs2_vue_root_Vue_.normalizeClass)([state.isAudio == 'start' ? 'show' : 'hiddle'])
32020
34916
  }, null, 2), state.isAudio == 'end' ? ((0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementBlock)("img", {
32021
34917
  key: 0,
@@ -32048,15 +34944,15 @@ const _hoisted_19 = ["src"];
32048
34944
  });
32049
34945
  ;// CONCATENATED MODULE: ./src/package/src/main.vue?vue&type=script&setup=true&lang=js
32050
34946
 
32051
- ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-54.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-54.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-54.use[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/package/src/main.vue?vue&type=style&index=0&id=7c916d88&lang=css
34947
+ ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-54.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-54.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-54.use[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/package/src/main.vue?vue&type=style&index=0&id=16bd8825&lang=css
32052
34948
  // extracted by mini-css-extract-plugin
32053
34949
 
32054
- ;// CONCATENATED MODULE: ./src/package/src/main.vue?vue&type=style&index=0&id=7c916d88&lang=css
34950
+ ;// CONCATENATED MODULE: ./src/package/src/main.vue?vue&type=style&index=0&id=16bd8825&lang=css
32055
34951
 
32056
- ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-74.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-74.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-74.use[2]!./node_modules/less-loader/dist/cjs.js??clonedRuleSet-74.use[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/package/src/main.vue?vue&type=style&index=1&id=7c916d88&lang=less&scoped=true
34952
+ ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-74.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-74.use[1]!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-74.use[2]!./node_modules/less-loader/dist/cjs.js??clonedRuleSet-74.use[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/package/src/main.vue?vue&type=style&index=1&id=16bd8825&lang=less&scoped=true
32057
34953
  // extracted by mini-css-extract-plugin
32058
34954
 
32059
- ;// CONCATENATED MODULE: ./src/package/src/main.vue?vue&type=style&index=1&id=7c916d88&lang=less&scoped=true
34955
+ ;// CONCATENATED MODULE: ./src/package/src/main.vue?vue&type=style&index=1&id=16bd8825&lang=less&scoped=true
32060
34956
 
32061
34957
  // EXTERNAL MODULE: ./node_modules/vue-loader/dist/exportHelper.js
32062
34958
  var exportHelper = __webpack_require__(6262);
@@ -32068,7 +34964,7 @@ var exportHelper = __webpack_require__(6262);
32068
34964
 
32069
34965
 
32070
34966
 
32071
- const __exports__ = /*#__PURE__*/(0,exportHelper/* default */.A)(mainvue_type_script_setup_true_lang_js, [['__scopeId',"data-v-7c916d88"]])
34967
+ const __exports__ = /*#__PURE__*/(0,exportHelper/* default */.A)(mainvue_type_script_setup_true_lang_js, [['__scopeId',"data-v-16bd8825"]])
32072
34968
 
32073
34969
  /* harmony default export */ var main = (__exports__);
32074
34970
  ;// CONCATENATED MODULE: ./src/package/index.js