mellon 0.0.11 → 0.0.12
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.
- package/dist/mellon.cjs +2 -2
- package/dist/mellon.mjs +98 -101
- package/package.json +1 -1
package/dist/mellon.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Kt="0.0.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Kt="0.0.12",Yt=[1,1,149,64],Qt=`https://cdn.jsdelivr.net/npm/mellon@${Kt}/dist/assets`,st={assetsPath:`${Qt}`};let D=null,q=null,tt=null;function Vt({assetsPath:a}={}){a!==void 0&&(st.assetsPath=a),D=null,q=null,tt=null}async function Xt(a){return D?(a==null||a(1),D):q||(q=(async()=>{const n=st.assetsPath.endsWith("/")?st.assetsPath:st.assetsPath+"/",t=n+"ort.all.min.mjs",e=n+"model.onnx";tt=await new Function("url","return import(url)")(t),tt.env.wasm.wasmPaths=n;const s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch model: ${s.status}`);const i=parseInt(s.headers.get("content-length")||"0",10),o=s.body.getReader(),c=[];let l=0;for(;;){const{done:m,value:f}=await o.read();if(m)break;c.push(f),l+=f.byteLength,i>0&&(a==null||a(l/i))}const h=new Uint8Array(l);let d=0;for(const m of c)h.set(m,d),d+=m.byteLength;return D=await tt.InferenceSession.create(h.buffer,{executionProviders:["wasm"],graphOptimizationLevel:"all"}),a==null||a(1),D})(),q)}async function Nt(a){if(!D)throw new Error("Model not loaded — call loadModel() first");const n=new tt.Tensor("float32",a,Yt),t=await D.run({input:n}),e=Object.keys(t)[0];return t[e].data}function Zt(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var _t,Et;function Ot(){if(Et)return _t;Et=1;function a(n){if(this.size=n|0,this.size<=1||(this.size&this.size-1)!==0)throw new Error("FFT size must be a power of two and bigger than 1");this._csize=n<<1;for(var t=new Array(this.size*2),e=0;e<t.length;e+=2){const l=Math.PI*e/this.size;t[e]=Math.cos(l),t[e+1]=-Math.sin(l)}this.table=t;for(var r=0,s=1;this.size>s;s<<=1)r++;this._width=r%2===0?r-1:r,this._bitrev=new Array(1<<this._width);for(var i=0;i<this._bitrev.length;i++){this._bitrev[i]=0;for(var o=0;o<this._width;o+=2){var c=this._width-o-2;this._bitrev[i]|=(i>>>o&3)<<c}}this._out=null,this._data=null,this._inv=0}return _t=a,a.prototype.fromComplexArray=function(t,e){for(var r=e||new Array(t.length>>>1),s=0;s<t.length;s+=2)r[s>>>1]=t[s];return r},a.prototype.createComplexArray=function(){const t=new Array(this._csize);for(var e=0;e<t.length;e++)t[e]=0;return t},a.prototype.toComplexArray=function(t,e){for(var r=e||this.createComplexArray(),s=0;s<r.length;s+=2)r[s]=t[s>>>1],r[s+1]=0;return r},a.prototype.completeSpectrum=function(t){for(var e=this._csize,r=e>>>1,s=2;s<r;s+=2)t[e-s]=t[s],t[e-s+1]=-t[s+1]},a.prototype.transform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._transform4(),this._out=null,this._data=null},a.prototype.realTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._realTransform4(),this._out=null,this._data=null},a.prototype.inverseTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=1,this._transform4();for(var r=0;r<t.length;r++)t[r]/=this.size;this._out=null,this._data=null},a.prototype._transform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,i=e/s<<1,o,c,l=this._bitrev;if(i===4)for(o=0,c=0;o<e;o+=i,c++){const u=l[c];this._singleTransform2(o,u,s)}else for(o=0,c=0;o<e;o+=i,c++){const u=l[c];this._singleTransform4(o,u,s)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){i=e/s<<1;var m=i>>>2;for(o=0;o<e;o+=i)for(var f=o+m,g=o,_=0;g<f;g+=2,_+=s){const u=g,p=u+m,v=p+m,w=v+m,b=t[u],E=t[u+1],A=t[p],y=t[p+1],M=t[v],F=t[v+1],C=t[w],T=t[w+1],x=b,R=E,S=d[_],z=h*d[_+1],N=A*S-y*z,k=A*z+y*S,P=d[2*_],L=h*d[2*_+1],G=M*P-F*L,H=M*L+F*P,J=d[3*_],K=h*d[3*_+1],Y=C*J-T*K,Q=C*K+T*J,V=x+G,j=R+H,B=x-G,X=R-H,Z=N+Y,U=k+Q,$=h*(N-Y),O=h*(k-Q),et=V+Z,at=j+U,it=V-Z,ct=j-U,lt=B+O,ht=X-$,dt=B-O,ut=X+$;t[u]=et,t[u+1]=at,t[p]=lt,t[p+1]=ht,t[v]=it,t[v+1]=ct,t[w]=dt,t[w+1]=ut}}},a.prototype._singleTransform2=function(t,e,r){const s=this._out,i=this._data,o=i[e],c=i[e+1],l=i[e+r],h=i[e+r+1],d=o+l,m=c+h,f=o-l,g=c-h;s[t]=d,s[t+1]=m,s[t+2]=f,s[t+3]=g},a.prototype._singleTransform4=function(t,e,r){const s=this._out,i=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=i[e],d=i[e+1],m=i[e+r],f=i[e+r+1],g=i[e+c],_=i[e+c+1],u=i[e+l],p=i[e+l+1],v=h+g,w=d+_,b=h-g,E=d-_,A=m+u,y=f+p,M=o*(m-u),F=o*(f-p),C=v+A,T=w+y,x=b+F,R=E-M,S=v-A,z=w-y,N=b-F,k=E+M;s[t]=C,s[t+1]=T,s[t+2]=x,s[t+3]=R,s[t+4]=S,s[t+5]=z,s[t+6]=N,s[t+7]=k},a.prototype._realTransform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,i=e/s<<1,o,c,l=this._bitrev;if(i===4)for(o=0,c=0;o<e;o+=i,c++){const mt=l[c];this._singleRealTransform2(o,mt>>>1,s>>>1)}else for(o=0,c=0;o<e;o+=i,c++){const mt=l[c];this._singleRealTransform4(o,mt>>>1,s>>>1)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){i=e/s<<1;var m=i>>>1,f=m>>>1,g=f>>>1;for(o=0;o<e;o+=i)for(var _=0,u=0;_<=g;_+=2,u+=s){var p=o+_,v=p+f,w=v+f,b=w+f,E=t[p],A=t[p+1],y=t[v],M=t[v+1],F=t[w],C=t[w+1],T=t[b],x=t[b+1],R=E,S=A,z=d[u],N=h*d[u+1],k=y*z-M*N,P=y*N+M*z,L=d[2*u],G=h*d[2*u+1],H=F*L-C*G,J=F*G+C*L,K=d[3*u],Y=h*d[3*u+1],Q=T*K-x*Y,V=T*Y+x*K,j=R+H,B=S+J,X=R-H,Z=S-J,U=k+Q,$=P+V,O=h*(k-Q),et=h*(P-V),at=j+U,it=B+$,ct=X+et,lt=Z-O;if(t[p]=at,t[p+1]=it,t[v]=ct,t[v+1]=lt,_===0){var ht=j-U,dt=B-$;t[w]=ht,t[w+1]=dt;continue}if(_!==g){var ut=X,It=-Z,Wt=j,jt=-B,Bt=-h*et,Ut=-h*O,$t=-h*$,Pt=-h*U,Lt=ut+Bt,Gt=It+Ut,Ht=Wt+Pt,Jt=jt-$t,bt=o+f-_,At=o+m-_;t[bt]=Lt,t[bt+1]=Gt,t[At]=Ht,t[At+1]=Jt}}}},a.prototype._singleRealTransform2=function(t,e,r){const s=this._out,i=this._data,o=i[e],c=i[e+r],l=o+c,h=o-c;s[t]=l,s[t+1]=0,s[t+2]=h,s[t+3]=0},a.prototype._singleRealTransform4=function(t,e,r){const s=this._out,i=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=i[e],d=i[e+r],m=i[e+c],f=i[e+l],g=h+m,_=h-m,u=d+f,p=o*(d-f),v=g+u,w=_,b=-p,E=g-u,A=_,y=p;s[t]=v,s[t+1]=0,s[t+2]=w,s[t+3]=b,s[t+4]=E,s[t+5]=0,s[t+6]=A,s[t+7]=y},_t}var qt=Ot();const te=Zt(qt),nt=16e3,W=512,I=64,Mt=Math.floor(.025*nt),Ft=Math.floor(.01*nt);function Ct(a){return 2595*Math.log10(1+a/700)}function ee(a){return 700*(10**(a/2595)-1)}function se(){const a=Ct(0),n=Ct(nt/2),t=new Float64Array(I+2);for(let o=0;o<I+2;o++)t[o]=a+o*(n-a)/(I+1);const r=t.map(o=>ee(o)).map(o=>Math.floor((W+1)*o/nt)),s=[],i=Math.floor(W/2)+1;for(let o=0;o<I;o++){const c=new Float32Array(i);for(let l=r[o];l<r[o+1];l++)c[l]=(l-r[o])/(r[o+1]-r[o]);for(let l=r[o+1];l<r[o+2];l++)c[l]=(r[o+2]-l)/(r[o+2]-r[o+1]);s.push(c)}return s}const ne=se(),rt=new te(W),ft=new Float32Array(W),Tt=rt.createComplexArray(),pt=rt.createComplexArray(),xt=new Float32Array(Math.floor(W/2)+1);function kt(a){const n=1+Math.ceil((a.length-Mt)/Ft),t=new Float32Array(n*I),e=Math.floor(W/2)+1;for(let r=0;r<n;r++){const s=r*Ft;ft.fill(0);for(let i=0;i<Mt&&s+i<a.length;i++)ft[i]=a[s+i];rt.toComplexArray(ft,Tt),rt.transform(pt,Tt);for(let i=0;i<e;i++){const o=pt[2*i],c=pt[2*i+1],l=(o*o+c*c)/W;xt[i]=l===0?1e-30:l}for(let i=0;i<I;i++){const o=ne[i];let c=0;for(let l=0;l<e;l++)c+=xt[l]*o[l];t[r*I+i]=Math.log(c===0?1e-30:c)}}return t}function re(a,n){let t=0;for(let e=0;e<a.length;e++)t+=a[e]*n[e];return(t+1)/2}function oe(a,n){let t=0;for(const e of n){const r=re(a,e);r>t&&(t=r)}return t}class Rt extends EventTarget{constructor({name:n,refEmbeddings:t,threshold:e=.65,relaxationMs:r=2e3,inferenceGapMs:s=300}){super(),this.name=n,this.refEmbeddings=t,this.threshold=e,this.relaxationMs=r,this.inferenceGapMs=s,this._lastDetectionAt=0,this._lastInferenceAt=0,this._lastScore=0}get lastScore(){return this._lastScore}async scoreFrame(n){const t=Date.now();if(t-this._lastInferenceAt<this.inferenceGapMs)return null;this._lastInferenceAt=t;const e=kt(n),r=await Nt(e),s=oe(r,this.refEmbeddings);return this._lastScore=s,s>=this.threshold&&t-this._lastDetectionAt>=this.relaxationMs&&(this._lastDetectionAt=t,this.dispatchEvent(new CustomEvent("match",{detail:{name:this.name,confidence:s,timestamp:t}}))),s}}const St=16e3,ae=1500,vt=24e3;function zt(a){if(a.length===vt)return a;const n=new Float32Array(vt);return n.set(a.subarray(0,vt)),n}class Dt extends EventTarget{constructor(n){super(),this.wordName=n.trim().toLowerCase(),this.samples=[]}get sampleCount(){return this.samples.length}async recordSample(){const n=await navigator.mediaDevices.getUserMedia({audio:!0});return new Promise((t,e)=>{const r=new AudioContext({sampleRate:St}),s=new MediaRecorder(n),i=[];this.dispatchEvent(new CustomEvent("recording-start")),s.ondataavailable=o=>{o.data.size>0&&i.push(o.data)},s.onstop=async()=>{n.getTracks().forEach(o=>o.stop());try{const c=await new Blob(i,{type:"audio/webm"}).arrayBuffer(),l=await r.decodeAudioData(c);await r.close();const h=l.getChannelData(0),d=zt(new Float32Array(h)),m=this._push(d,`Recorded #${this.samples.length}`);t(m)}catch(o){await r.close().catch(()=>{}),e(o)}},s.start(),setTimeout(()=>s.stop(),ae)})}async addAudioFile(n){const t=await n.arrayBuffer(),e=new AudioContext({sampleRate:St}),r=await e.decodeAudioData(t);await e.close();const s=r.getChannelData(0),i=zt(new Float32Array(s));return this._push(i,n.name)}removeSample(n){this.samples.splice(n,1),this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:this.samples.length}}))}clearSamples(){this.samples=[],this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:0}}))}async generateRef(){if(this.samples.length<3)throw new Error(`Need at least 3 samples (currently have ${this.samples.length})`);this.dispatchEvent(new CustomEvent("generating",{detail:{total:this.samples.length}}));const n=[];for(let t=0;t<this.samples.length;t++){const e=kt(this.samples[t].audioBuffer),r=await Nt(e);n.push(Array.from(r)),this.dispatchEvent(new CustomEvent("progress",{detail:{done:t+1,total:this.samples.length}}))}return{word_name:this.wordName,model_type:"resnet_50_arc",embeddings:n}}_push(n,t){this.samples.push({audioBuffer:n,name:t});const e=this.samples.length;return this.dispatchEvent(new CustomEvent("sample-added",{detail:{count:e,name:t}})),e}}const ie=`/**
|
|
2
2
|
* public/audio-processor.js
|
|
3
3
|
* AudioWorklet that runs at 16 kHz and continuously emits the last
|
|
4
4
|
* 1.5-second window (24 000 samples) via a circular buffer.
|
|
@@ -35,4 +35,4 @@ class AudioProcessor extends AudioWorkletProcessor {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
registerProcessor('audio-processor', AudioProcessor)
|
|
38
|
-
`;let wt=null;function ce(){if(!wt){const
|
|
38
|
+
`;let wt=null;function ce(){if(!wt){const a=new Blob([ie],{type:"application/javascript"});wt=URL.createObjectURL(a)}return wt}const gt="mellon_custom_refs";function yt(){try{const a=localStorage.getItem(gt);return a?JSON.parse(a):[]}catch{return[]}}function le(a){const n=yt().filter(t=>t.word_name!==a.word_name);n.push(a),localStorage.setItem(gt,JSON.stringify(n))}function he(a){const n=yt().filter(t=>t.word_name!==a);localStorage.setItem(gt,JSON.stringify(n))}function de(a){const n=JSON.stringify(a,null,2),t=new Blob([n],{type:"application/json"}),e=URL.createObjectURL(t),r=Object.assign(document.createElement("a"),{href:e,download:`${a.word_name}_ref.json`});document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(e)}async function ue(a){const n=await a.text();let t;try{t=JSON.parse(n)}catch{throw new Error("Invalid JSON")}if(!t.embeddings||!Array.isArray(t.embeddings)||!t.embeddings.length)throw new Error('Missing or empty "embeddings" array');if(!Array.isArray(t.embeddings[0]))throw new Error('"embeddings" must be a 2D array');return t.word_name||(t.word_name=a.name.replace(/_ref\.json$/i,"").replace(/\.json$/i,"")),t}class ot extends EventTarget{constructor(n={}){super(),this._opts={refs:n.refs??[],threshold:n.threshold??.65,relaxationMs:n.relaxationMs??2e3,inferenceGapMs:n.inferenceGapMs??300,matchDebounceMs:n.matchDebounceMs??1e3,assetsPath:n.assetsPath},this._refs=new Map,this._detectors=new Map,this._audioCtx=null,this._workletNode=null,this._stream=null,this._initialized=!1,this._running=!1,this._lastMatchAt=0}get isInitialized(){return this._initialized}get isRunning(){return this._running}async init(n){var e;if(this._initialized){n==null||n(1);return}this._opts.assetsPath&&Vt({assetsPath:this._opts.assetsPath});try{await Xt(n)}catch(r){throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}const t=await ot.loadWords();for(const r of this._opts.refs){const s=(e=r.match(/\/([^/]+?)_ref\.json$/))==null?void 0:e[1],i=t.find(o=>o.word_name===s);try{let o;if(i)continue;if(typeof r=="string"){console.log("fetching ref : ",r);const c=await fetch(r);if(!c.ok)throw new Error(`HTTP ${c.status}`);o=await c.json()}else o=r;ot.saveWord(o),this.addCustomWord(o)}catch(o){const c=typeof r=="string"?r:r.word_name;console.warn(`[Mellon] Failed to load ref "${c}": ${o.message}`)}}t.forEach(r=>this.addCustomWord(r)),this._initialized=!0,this.dispatchEvent(new CustomEvent("ready"))}async start(){this._initialized||await this.init();try{this._stream=await navigator.mediaDevices.getUserMedia({audio:!0})}catch(e){const r=new Error(`Microphone access denied: ${e.message}`);throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}this._audioCtx=new AudioContext({sampleRate:16e3});const n=ce();await this._audioCtx.audioWorklet.addModule(n);const t=this._audioCtx.createMediaStreamSource(this._stream);this._workletNode=new AudioWorkletNode(this._audioCtx,"audio-processor"),t.connect(this._workletNode),this._workletNode.connect(this._audioCtx.destination);for(const[e,r]of this._refs){const s=new Rt({name:e,refEmbeddings:r.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});s.addEventListener("match",i=>this._onMatch(i)),this._detectors.set(e,s)}this._workletNode.port.onmessage=async e=>{const r=[];for(const s of this._detectors.values())r.push(s.scoreFrame(e.data));await Promise.allSettled(r)},this._running=!0}stop(){this._workletNode&&(this._workletNode.port.onmessage=null,this._workletNode.disconnect(),this._workletNode=null),this._stream&&(this._stream.getTracks().forEach(n=>n.stop()),this._stream=null),this._audioCtx&&(this._audioCtx.close(),this._audioCtx=null),this._detectors.clear(),this._running=!1}addCustomWord(n){if(this._refs.set(n.word_name,n),this._running&&this._workletNode){const t=new Rt({name:n.word_name,refEmbeddings:n.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});t.addEventListener("match",e=>this._onMatch(e)),this._detectors.set(n.word_name,t)}}_onMatch(n){const t=Date.now();t-this._lastMatchAt<this._opts.matchDebounceMs||(this._lastMatchAt=t,this.dispatchEvent(new CustomEvent("match",{detail:n.detail})))}enrollWord(n){return new Dt(n)}static loadWords(){return yt()}static saveWord(n){le(n)}static deleteWord(n){he(n)}static importWordFile(n){return ue(n)}static exportWord(n){de(n)}}exports.EnrollmentSession=Dt;exports.Mellon=ot;
|
package/dist/mellon.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
const Jt = "0.0.
|
|
1
|
+
const Jt = "0.0.12", Kt = [1, 1, 149, 64], Yt = `https://cdn.jsdelivr.net/npm/mellon@${Jt}/dist/assets`, st = {
|
|
2
2
|
assetsPath: `${Yt}`
|
|
3
3
|
};
|
|
4
4
|
let D = null, q = null, tt = null;
|
|
5
|
-
function Qt({ assetsPath:
|
|
6
|
-
|
|
5
|
+
function Qt({ assetsPath: a } = {}) {
|
|
6
|
+
a !== void 0 && (st.assetsPath = a), D = null, q = null, tt = null;
|
|
7
7
|
}
|
|
8
|
-
async function Vt(
|
|
9
|
-
return D ? (
|
|
8
|
+
async function Vt(a) {
|
|
9
|
+
return D ? (a == null || a(1), D) : q || (q = (async () => {
|
|
10
10
|
const n = st.assetsPath.endsWith("/") ? st.assetsPath : st.assetsPath + "/", t = n + "ort.all.min.mjs", e = n + "model.onnx";
|
|
11
11
|
tt = await new Function("url", "return import(url)")(t), tt.env.wasm.wasmPaths = n;
|
|
12
12
|
const s = await fetch(e);
|
|
13
13
|
if (!s.ok) throw new Error(`Failed to fetch model: ${s.status}`);
|
|
14
|
-
const
|
|
14
|
+
const i = parseInt(s.headers.get("content-length") || "0", 10), o = s.body.getReader(), c = [];
|
|
15
15
|
let l = 0;
|
|
16
16
|
for (; ; ) {
|
|
17
17
|
const { done: m, value: f } = await o.read();
|
|
18
18
|
if (m) break;
|
|
19
|
-
c.push(f), l += f.byteLength,
|
|
19
|
+
c.push(f), l += f.byteLength, i > 0 && (a == null || a(l / i));
|
|
20
20
|
}
|
|
21
21
|
const h = new Uint8Array(l);
|
|
22
22
|
let d = 0;
|
|
@@ -25,22 +25,22 @@ async function Vt(i) {
|
|
|
25
25
|
return D = await tt.InferenceSession.create(h.buffer, {
|
|
26
26
|
executionProviders: ["wasm"],
|
|
27
27
|
graphOptimizationLevel: "all"
|
|
28
|
-
}),
|
|
28
|
+
}), a == null || a(1), D;
|
|
29
29
|
})(), q);
|
|
30
30
|
}
|
|
31
|
-
async function Nt(
|
|
31
|
+
async function Nt(a) {
|
|
32
32
|
if (!D) throw new Error("Model not loaded — call loadModel() first");
|
|
33
|
-
const n = new tt.Tensor("float32",
|
|
33
|
+
const n = new tt.Tensor("float32", a, Kt), t = await D.run({ input: n }), e = Object.keys(t)[0];
|
|
34
34
|
return t[e].data;
|
|
35
35
|
}
|
|
36
|
-
function Xt(
|
|
37
|
-
return
|
|
36
|
+
function Xt(a) {
|
|
37
|
+
return a && a.__esModule && Object.prototype.hasOwnProperty.call(a, "default") ? a.default : a;
|
|
38
38
|
}
|
|
39
39
|
var mt, Et;
|
|
40
40
|
function Zt() {
|
|
41
41
|
if (Et) return mt;
|
|
42
42
|
Et = 1;
|
|
43
|
-
function
|
|
43
|
+
function a(n) {
|
|
44
44
|
if (this.size = n | 0, this.size <= 1 || (this.size & this.size - 1) !== 0)
|
|
45
45
|
throw new Error("FFT size must be a power of two and bigger than 1");
|
|
46
46
|
this._csize = n << 1;
|
|
@@ -52,91 +52,91 @@ function Zt() {
|
|
|
52
52
|
for (var r = 0, s = 1; this.size > s; s <<= 1)
|
|
53
53
|
r++;
|
|
54
54
|
this._width = r % 2 === 0 ? r - 1 : r, this._bitrev = new Array(1 << this._width);
|
|
55
|
-
for (var
|
|
56
|
-
this._bitrev[
|
|
55
|
+
for (var i = 0; i < this._bitrev.length; i++) {
|
|
56
|
+
this._bitrev[i] = 0;
|
|
57
57
|
for (var o = 0; o < this._width; o += 2) {
|
|
58
58
|
var c = this._width - o - 2;
|
|
59
|
-
this._bitrev[
|
|
59
|
+
this._bitrev[i] |= (i >>> o & 3) << c;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
this._out = null, this._data = null, this._inv = 0;
|
|
63
63
|
}
|
|
64
|
-
return mt =
|
|
64
|
+
return mt = a, a.prototype.fromComplexArray = function(t, e) {
|
|
65
65
|
for (var r = e || new Array(t.length >>> 1), s = 0; s < t.length; s += 2)
|
|
66
66
|
r[s >>> 1] = t[s];
|
|
67
67
|
return r;
|
|
68
|
-
},
|
|
68
|
+
}, a.prototype.createComplexArray = function() {
|
|
69
69
|
const t = new Array(this._csize);
|
|
70
70
|
for (var e = 0; e < t.length; e++)
|
|
71
71
|
t[e] = 0;
|
|
72
72
|
return t;
|
|
73
|
-
},
|
|
73
|
+
}, a.prototype.toComplexArray = function(t, e) {
|
|
74
74
|
for (var r = e || this.createComplexArray(), s = 0; s < r.length; s += 2)
|
|
75
75
|
r[s] = t[s >>> 1], r[s + 1] = 0;
|
|
76
76
|
return r;
|
|
77
|
-
},
|
|
77
|
+
}, a.prototype.completeSpectrum = function(t) {
|
|
78
78
|
for (var e = this._csize, r = e >>> 1, s = 2; s < r; s += 2)
|
|
79
79
|
t[e - s] = t[s], t[e - s + 1] = -t[s + 1];
|
|
80
|
-
},
|
|
80
|
+
}, a.prototype.transform = function(t, e) {
|
|
81
81
|
if (t === e)
|
|
82
82
|
throw new Error("Input and output buffers must be different");
|
|
83
83
|
this._out = t, this._data = e, this._inv = 0, this._transform4(), this._out = null, this._data = null;
|
|
84
|
-
},
|
|
84
|
+
}, a.prototype.realTransform = function(t, e) {
|
|
85
85
|
if (t === e)
|
|
86
86
|
throw new Error("Input and output buffers must be different");
|
|
87
87
|
this._out = t, this._data = e, this._inv = 0, this._realTransform4(), this._out = null, this._data = null;
|
|
88
|
-
},
|
|
88
|
+
}, a.prototype.inverseTransform = function(t, e) {
|
|
89
89
|
if (t === e)
|
|
90
90
|
throw new Error("Input and output buffers must be different");
|
|
91
91
|
this._out = t, this._data = e, this._inv = 1, this._transform4();
|
|
92
92
|
for (var r = 0; r < t.length; r++)
|
|
93
93
|
t[r] /= this.size;
|
|
94
94
|
this._out = null, this._data = null;
|
|
95
|
-
},
|
|
96
|
-
var t = this._out, e = this._csize, r = this._width, s = 1 << r,
|
|
97
|
-
if (
|
|
98
|
-
for (o = 0, c = 0; o < e; o +=
|
|
95
|
+
}, a.prototype._transform4 = function() {
|
|
96
|
+
var t = this._out, e = this._csize, r = this._width, s = 1 << r, i = e / s << 1, o, c, l = this._bitrev;
|
|
97
|
+
if (i === 4)
|
|
98
|
+
for (o = 0, c = 0; o < e; o += i, c++) {
|
|
99
99
|
const u = l[c];
|
|
100
100
|
this._singleTransform2(o, u, s);
|
|
101
101
|
}
|
|
102
102
|
else
|
|
103
|
-
for (o = 0, c = 0; o < e; o +=
|
|
103
|
+
for (o = 0, c = 0; o < e; o += i, c++) {
|
|
104
104
|
const u = l[c];
|
|
105
105
|
this._singleTransform4(o, u, s);
|
|
106
106
|
}
|
|
107
107
|
var h = this._inv ? -1 : 1, d = this.table;
|
|
108
108
|
for (s >>= 2; s >= 2; s >>= 2) {
|
|
109
|
-
|
|
110
|
-
var m =
|
|
111
|
-
for (o = 0; o < e; o +=
|
|
109
|
+
i = e / s << 1;
|
|
110
|
+
var m = i >>> 2;
|
|
111
|
+
for (o = 0; o < e; o += i)
|
|
112
112
|
for (var f = o + m, g = o, _ = 0; g < f; g += 2, _ += s) {
|
|
113
113
|
const u = g, p = u + m, v = p + m, w = v + m, b = t[u], E = t[u + 1], A = t[p], y = t[p + 1], M = t[v], F = t[v + 1], C = t[w], T = t[w + 1], x = b, R = E, z = d[_], S = h * d[_ + 1], N = A * z - y * S, k = A * S + y * z, L = d[2 * _], P = h * d[2 * _ + 1], G = M * L - F * P, H = M * P + F * L, J = d[3 * _], K = h * d[3 * _ + 1], Y = C * J - T * K, Q = C * K + T * J, V = x + G, j = R + H, B = x - G, X = R - H, Z = N + Y, U = k + Q, $ = h * (N - Y), O = h * (k - Q), et = V + Z, ot = j + U, at = V - Z, it = j - U, ct = B + O, lt = X - $, ht = B - O, dt = X + $;
|
|
114
114
|
t[u] = et, t[u + 1] = ot, t[p] = ct, t[p + 1] = lt, t[v] = at, t[v + 1] = it, t[w] = ht, t[w + 1] = dt;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
},
|
|
118
|
-
const s = this._out,
|
|
117
|
+
}, a.prototype._singleTransform2 = function(t, e, r) {
|
|
118
|
+
const s = this._out, i = this._data, o = i[e], c = i[e + 1], l = i[e + r], h = i[e + r + 1], d = o + l, m = c + h, f = o - l, g = c - h;
|
|
119
119
|
s[t] = d, s[t + 1] = m, s[t + 2] = f, s[t + 3] = g;
|
|
120
|
-
},
|
|
121
|
-
const s = this._out,
|
|
120
|
+
}, a.prototype._singleTransform4 = function(t, e, r) {
|
|
121
|
+
const s = this._out, i = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = i[e], d = i[e + 1], m = i[e + r], f = i[e + r + 1], g = i[e + c], _ = i[e + c + 1], u = i[e + l], p = i[e + l + 1], v = h + g, w = d + _, b = h - g, E = d - _, A = m + u, y = f + p, M = o * (m - u), F = o * (f - p), C = v + A, T = w + y, x = b + F, R = E - M, z = v - A, S = w - y, N = b - F, k = E + M;
|
|
122
122
|
s[t] = C, s[t + 1] = T, s[t + 2] = x, s[t + 3] = R, s[t + 4] = z, s[t + 5] = S, s[t + 6] = N, s[t + 7] = k;
|
|
123
|
-
},
|
|
124
|
-
var t = this._out, e = this._csize, r = this._width, s = 1 << r,
|
|
125
|
-
if (
|
|
126
|
-
for (o = 0, c = 0; o < e; o +=
|
|
123
|
+
}, a.prototype._realTransform4 = function() {
|
|
124
|
+
var t = this._out, e = this._csize, r = this._width, s = 1 << r, i = e / s << 1, o, c, l = this._bitrev;
|
|
125
|
+
if (i === 4)
|
|
126
|
+
for (o = 0, c = 0; o < e; o += i, c++) {
|
|
127
127
|
const ut = l[c];
|
|
128
128
|
this._singleRealTransform2(o, ut >>> 1, s >>> 1);
|
|
129
129
|
}
|
|
130
130
|
else
|
|
131
|
-
for (o = 0, c = 0; o < e; o +=
|
|
131
|
+
for (o = 0, c = 0; o < e; o += i, c++) {
|
|
132
132
|
const ut = l[c];
|
|
133
133
|
this._singleRealTransform4(o, ut >>> 1, s >>> 1);
|
|
134
134
|
}
|
|
135
135
|
var h = this._inv ? -1 : 1, d = this.table;
|
|
136
136
|
for (s >>= 2; s >= 2; s >>= 2) {
|
|
137
|
-
|
|
138
|
-
var m =
|
|
139
|
-
for (o = 0; o < e; o +=
|
|
137
|
+
i = e / s << 1;
|
|
138
|
+
var m = i >>> 1, f = m >>> 1, g = f >>> 1;
|
|
139
|
+
for (o = 0; o < e; o += i)
|
|
140
140
|
for (var _ = 0, u = 0; _ <= g; _ += 2, u += s) {
|
|
141
141
|
var p = o + _, v = p + f, w = v + f, b = w + f, E = t[p], A = t[p + 1], y = t[v], M = t[v + 1], F = t[w], C = t[w + 1], T = t[b], x = t[b + 1], R = E, z = A, S = d[u], N = h * d[u + 1], k = y * S - M * N, L = y * N + M * S, P = d[2 * u], G = h * d[2 * u + 1], H = F * P - C * G, J = F * G + C * P, K = d[3 * u], Y = h * d[3 * u + 1], Q = T * K - x * Y, V = T * Y + x * K, j = R + H, B = z + J, X = R - H, Z = z - J, U = k + Q, $ = L + V, O = h * (k - Q), et = h * (L - V), ot = j + U, at = B + $, it = X + et, ct = Z - O;
|
|
142
142
|
if (t[p] = ot, t[p + 1] = at, t[v] = it, t[v + 1] = ct, _ === 0) {
|
|
@@ -150,29 +150,29 @@ function Zt() {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
},
|
|
154
|
-
const s = this._out,
|
|
153
|
+
}, a.prototype._singleRealTransform2 = function(t, e, r) {
|
|
154
|
+
const s = this._out, i = this._data, o = i[e], c = i[e + r], l = o + c, h = o - c;
|
|
155
155
|
s[t] = l, s[t + 1] = 0, s[t + 2] = h, s[t + 3] = 0;
|
|
156
|
-
},
|
|
157
|
-
const s = this._out,
|
|
156
|
+
}, a.prototype._singleRealTransform4 = function(t, e, r) {
|
|
157
|
+
const s = this._out, i = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = i[e], d = i[e + r], m = i[e + c], f = i[e + l], g = h + m, _ = h - m, u = d + f, p = o * (d - f), v = g + u, w = _, b = -p, E = g - u, A = _, y = p;
|
|
158
158
|
s[t] = v, s[t + 1] = 0, s[t + 2] = w, s[t + 3] = b, s[t + 4] = E, s[t + 5] = 0, s[t + 6] = A, s[t + 7] = y;
|
|
159
159
|
}, mt;
|
|
160
160
|
}
|
|
161
161
|
var Ot = Zt();
|
|
162
162
|
const qt = /* @__PURE__ */ Xt(Ot), nt = 16e3, W = 512, I = 64, Mt = Math.floor(0.025 * nt), Ft = Math.floor(0.01 * nt);
|
|
163
|
-
function Ct(
|
|
164
|
-
return 2595 * Math.log10(1 +
|
|
163
|
+
function Ct(a) {
|
|
164
|
+
return 2595 * Math.log10(1 + a / 700);
|
|
165
165
|
}
|
|
166
|
-
function te(
|
|
167
|
-
return 700 * (10 ** (
|
|
166
|
+
function te(a) {
|
|
167
|
+
return 700 * (10 ** (a / 2595) - 1);
|
|
168
168
|
}
|
|
169
169
|
function ee() {
|
|
170
|
-
const
|
|
170
|
+
const a = Ct(0), n = Ct(nt / 2), t = new Float64Array(I + 2);
|
|
171
171
|
for (let o = 0; o < I + 2; o++)
|
|
172
|
-
t[o] =
|
|
173
|
-
const r = t.map((o) => te(o)).map((o) => Math.floor((W + 1) * o / nt)), s = [],
|
|
172
|
+
t[o] = a + o * (n - a) / (I + 1);
|
|
173
|
+
const r = t.map((o) => te(o)).map((o) => Math.floor((W + 1) * o / nt)), s = [], i = Math.floor(W / 2) + 1;
|
|
174
174
|
for (let o = 0; o < I; o++) {
|
|
175
|
-
const c = new Float32Array(
|
|
175
|
+
const c = new Float32Array(i);
|
|
176
176
|
for (let l = r[o]; l < r[o + 1]; l++) c[l] = (l - r[o]) / (r[o + 1] - r[o]);
|
|
177
177
|
for (let l = r[o + 1]; l < r[o + 2]; l++) c[l] = (r[o + 2] - l) / (r[o + 2] - r[o + 1]);
|
|
178
178
|
s.push(c);
|
|
@@ -180,36 +180,36 @@ function ee() {
|
|
|
180
180
|
return s;
|
|
181
181
|
}
|
|
182
182
|
const se = ee(), rt = new qt(W), _t = new Float32Array(W), Tt = rt.createComplexArray(), ft = rt.createComplexArray(), xt = new Float32Array(Math.floor(W / 2) + 1);
|
|
183
|
-
function kt(
|
|
184
|
-
const n = 1 + Math.ceil((
|
|
183
|
+
function kt(a) {
|
|
184
|
+
const n = 1 + Math.ceil((a.length - Mt) / Ft), t = new Float32Array(n * I), e = Math.floor(W / 2) + 1;
|
|
185
185
|
for (let r = 0; r < n; r++) {
|
|
186
186
|
const s = r * Ft;
|
|
187
187
|
_t.fill(0);
|
|
188
|
-
for (let
|
|
189
|
-
_t[
|
|
188
|
+
for (let i = 0; i < Mt && s + i < a.length; i++)
|
|
189
|
+
_t[i] = a[s + i];
|
|
190
190
|
rt.toComplexArray(_t, Tt), rt.transform(ft, Tt);
|
|
191
|
-
for (let
|
|
192
|
-
const o = ft[2 *
|
|
193
|
-
xt[
|
|
191
|
+
for (let i = 0; i < e; i++) {
|
|
192
|
+
const o = ft[2 * i], c = ft[2 * i + 1], l = (o * o + c * c) / W;
|
|
193
|
+
xt[i] = l === 0 ? 1e-30 : l;
|
|
194
194
|
}
|
|
195
|
-
for (let
|
|
196
|
-
const o = se[
|
|
195
|
+
for (let i = 0; i < I; i++) {
|
|
196
|
+
const o = se[i];
|
|
197
197
|
let c = 0;
|
|
198
198
|
for (let l = 0; l < e; l++) c += xt[l] * o[l];
|
|
199
|
-
t[r * I +
|
|
199
|
+
t[r * I + i] = Math.log(c === 0 ? 1e-30 : c);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
return t;
|
|
203
203
|
}
|
|
204
|
-
function ne(
|
|
204
|
+
function ne(a, n) {
|
|
205
205
|
let t = 0;
|
|
206
|
-
for (let e = 0; e <
|
|
206
|
+
for (let e = 0; e < a.length; e++) t += a[e] * n[e];
|
|
207
207
|
return (t + 1) / 2;
|
|
208
208
|
}
|
|
209
|
-
function re(
|
|
209
|
+
function re(a, n) {
|
|
210
210
|
let t = 0;
|
|
211
211
|
for (const e of n) {
|
|
212
|
-
const r = ne(
|
|
212
|
+
const r = ne(a, e);
|
|
213
213
|
r > t && (t = r);
|
|
214
214
|
}
|
|
215
215
|
return t;
|
|
@@ -246,10 +246,10 @@ class Rt extends EventTarget {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
const zt = 16e3, oe = 1500, pt = 24e3;
|
|
249
|
-
function St(
|
|
250
|
-
if (
|
|
249
|
+
function St(a) {
|
|
250
|
+
if (a.length === pt) return a;
|
|
251
251
|
const n = new Float32Array(pt);
|
|
252
|
-
return n.set(
|
|
252
|
+
return n.set(a.subarray(0, pt)), n;
|
|
253
253
|
}
|
|
254
254
|
class ae extends EventTarget {
|
|
255
255
|
/** @param {string} wordName — the wake word label */
|
|
@@ -269,13 +269,13 @@ class ae extends EventTarget {
|
|
|
269
269
|
async recordSample() {
|
|
270
270
|
const n = await navigator.mediaDevices.getUserMedia({ audio: !0 });
|
|
271
271
|
return new Promise((t, e) => {
|
|
272
|
-
const r = new AudioContext({ sampleRate: zt }), s = new MediaRecorder(n),
|
|
272
|
+
const r = new AudioContext({ sampleRate: zt }), s = new MediaRecorder(n), i = [];
|
|
273
273
|
this.dispatchEvent(new CustomEvent("recording-start")), s.ondataavailable = (o) => {
|
|
274
|
-
o.data.size > 0 &&
|
|
274
|
+
o.data.size > 0 && i.push(o.data);
|
|
275
275
|
}, s.onstop = async () => {
|
|
276
276
|
n.getTracks().forEach((o) => o.stop());
|
|
277
277
|
try {
|
|
278
|
-
const c = await new Blob(
|
|
278
|
+
const c = await new Blob(i, { type: "audio/webm" }).arrayBuffer(), l = await r.decodeAudioData(c);
|
|
279
279
|
await r.close();
|
|
280
280
|
const h = l.getChannelData(0), d = St(new Float32Array(h)), m = this._push(d, `Recorded #${this.samples.length}`);
|
|
281
281
|
t(m);
|
|
@@ -296,8 +296,8 @@ class ae extends EventTarget {
|
|
|
296
296
|
async addAudioFile(n) {
|
|
297
297
|
const t = await n.arrayBuffer(), e = new AudioContext({ sampleRate: zt }), r = await e.decodeAudioData(t);
|
|
298
298
|
await e.close();
|
|
299
|
-
const s = r.getChannelData(0),
|
|
300
|
-
return this._push(
|
|
299
|
+
const s = r.getChannelData(0), i = St(new Float32Array(s));
|
|
300
|
+
return this._push(i, n.name);
|
|
301
301
|
}
|
|
302
302
|
// ─── Manage ────────────────────────────────────────────────────────────────
|
|
303
303
|
/**
|
|
@@ -382,37 +382,37 @@ registerProcessor('audio-processor', AudioProcessor)
|
|
|
382
382
|
let vt = null;
|
|
383
383
|
function ce() {
|
|
384
384
|
if (!vt) {
|
|
385
|
-
const
|
|
386
|
-
vt = URL.createObjectURL(
|
|
385
|
+
const a = new Blob([ie], { type: "application/javascript" });
|
|
386
|
+
vt = URL.createObjectURL(a);
|
|
387
387
|
}
|
|
388
388
|
return vt;
|
|
389
389
|
}
|
|
390
390
|
const gt = "mellon_custom_refs";
|
|
391
391
|
function yt() {
|
|
392
392
|
try {
|
|
393
|
-
const
|
|
394
|
-
return
|
|
393
|
+
const a = localStorage.getItem(gt);
|
|
394
|
+
return a ? JSON.parse(a) : [];
|
|
395
395
|
} catch {
|
|
396
396
|
return [];
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
|
-
function le(
|
|
400
|
-
const n = yt().filter((t) => t.word_name !==
|
|
401
|
-
n.push(
|
|
399
|
+
function le(a) {
|
|
400
|
+
const n = yt().filter((t) => t.word_name !== a.word_name);
|
|
401
|
+
n.push(a), localStorage.setItem(gt, JSON.stringify(n));
|
|
402
402
|
}
|
|
403
|
-
function he(
|
|
404
|
-
const n = yt().filter((t) => t.word_name !==
|
|
403
|
+
function he(a) {
|
|
404
|
+
const n = yt().filter((t) => t.word_name !== a);
|
|
405
405
|
localStorage.setItem(gt, JSON.stringify(n));
|
|
406
406
|
}
|
|
407
|
-
function de(
|
|
408
|
-
const n = JSON.stringify(
|
|
407
|
+
function de(a) {
|
|
408
|
+
const n = JSON.stringify(a, null, 2), t = new Blob([n], { type: "application/json" }), e = URL.createObjectURL(t), r = Object.assign(document.createElement("a"), {
|
|
409
409
|
href: e,
|
|
410
|
-
download: `${
|
|
410
|
+
download: `${a.word_name}_ref.json`
|
|
411
411
|
});
|
|
412
412
|
document.body.appendChild(r), r.click(), document.body.removeChild(r), URL.revokeObjectURL(e);
|
|
413
413
|
}
|
|
414
|
-
async function ue(
|
|
415
|
-
const n = await
|
|
414
|
+
async function ue(a) {
|
|
415
|
+
const n = await a.text();
|
|
416
416
|
let t;
|
|
417
417
|
try {
|
|
418
418
|
t = JSON.parse(n);
|
|
@@ -423,7 +423,7 @@ async function ue(i) {
|
|
|
423
423
|
throw new Error('Missing or empty "embeddings" array');
|
|
424
424
|
if (!Array.isArray(t.embeddings[0]))
|
|
425
425
|
throw new Error('"embeddings" must be a 2D array');
|
|
426
|
-
return t.word_name || (t.word_name =
|
|
426
|
+
return t.word_name || (t.word_name = a.name.replace(/_ref\.json$/i, "").replace(/\.json$/i, "")), t;
|
|
427
427
|
}
|
|
428
428
|
class wt extends EventTarget {
|
|
429
429
|
/**
|
|
@@ -476,16 +476,13 @@ class wt extends EventTarget {
|
|
|
476
476
|
throw this.dispatchEvent(new CustomEvent("error", { detail: { error: r } })), r;
|
|
477
477
|
}
|
|
478
478
|
const t = await wt.loadWords();
|
|
479
|
-
console.log("existing refs in localstorage", { exisitngRefs: t });
|
|
480
479
|
for (const r of this._opts.refs) {
|
|
481
|
-
const s = (e = r.match(/\/([^/]+?)_ref\.json$/)) == null ? void 0 : e[1],
|
|
482
|
-
console.log({ word: s, alreadySaveWord: a });
|
|
480
|
+
const s = (e = r.match(/\/([^/]+?)_ref\.json$/)) == null ? void 0 : e[1], i = t.find((o) => o.word_name === s);
|
|
483
481
|
try {
|
|
484
482
|
let o;
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
} else if (typeof r == "string") {
|
|
483
|
+
if (i)
|
|
484
|
+
continue;
|
|
485
|
+
if (typeof r == "string") {
|
|
489
486
|
console.log("fetching ref : ", r);
|
|
490
487
|
const c = await fetch(r);
|
|
491
488
|
if (!c.ok) throw new Error(`HTTP ${c.status}`);
|
|
@@ -498,7 +495,7 @@ class wt extends EventTarget {
|
|
|
498
495
|
console.warn(`[Mellon] Failed to load ref "${c}": ${o.message}`);
|
|
499
496
|
}
|
|
500
497
|
}
|
|
501
|
-
this._initialized = !0, this.dispatchEvent(new CustomEvent("ready"));
|
|
498
|
+
t.forEach((r) => this.addCustomWord(r)), this._initialized = !0, this.dispatchEvent(new CustomEvent("ready"));
|
|
502
499
|
}
|
|
503
500
|
/**
|
|
504
501
|
* Request microphone access and start hotword detection.
|
|
@@ -526,7 +523,7 @@ class wt extends EventTarget {
|
|
|
526
523
|
relaxationMs: this._opts.relaxationMs,
|
|
527
524
|
inferenceGapMs: this._opts.inferenceGapMs
|
|
528
525
|
});
|
|
529
|
-
s.addEventListener("match", (
|
|
526
|
+
s.addEventListener("match", (i) => this._onMatch(i)), this._detectors.set(e, s);
|
|
530
527
|
}
|
|
531
528
|
this._workletNode.port.onmessage = async (e) => {
|
|
532
529
|
const r = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mellon",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Offline, in-browser hotword detection powered by EfficientWord-Net (ResNet-50 ArcFace). Works as a standalone app or npm library.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/mellon.cjs",
|