Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- assets/index-D3BIbg-L.js +0 -0
- assets/worker-GRMiTkkQ.js +1 -0
- index.html +1 -1
assets/index-D3BIbg-L.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/worker-GRMiTkkQ.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
const e=[`$`,...`;:,.!?¡¿—…"«»"" `,...`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`,...`ɑɐɒæɓʙβɔɕçɗɖðʤəɘɚɛɜɝɞɟʄɡɠɢʛɦɧħɥʜɨɪʝɭɬɫɮʟɱɯɰŋɳɲɴøɵɸθœɶʘɹɺɾɻʀʁɽʂʃʈʧʉʊʋⱱʌɣɤʍχʎʏʑʐʒʔʡʕʢǀǁǂǃˈˌːˑʼʴʰʱʲʷˠˤ˞↓↑→↗↘'̩'ᵻ`],t={};for(let n=0;n<e.length;n++)t[e[n]]=n;function n(e){let n=[];for(let r of e){let e=t[r];e!==void 0&&n.push(e)}return n}function r(e){let t=n(e);return t.unshift(0),t.push(10),t.push(0),t}function i(e){if(e[0]!==147||String.fromCharCode(e[1],e[2],e[3],e[4],e[5])!==`NUMPY`)throw Error(`Not a valid .npy file`);let t=e[6],n=new DataView(e.buffer,e.byteOffset,e.byteLength),r,i;t===1?(r=n.getUint16(8,!0),i=10):(r=n.getUint32(8,!0),i=12);let a=new TextDecoder().decode(e.slice(i,i+r)),o=a.match(/'descr'\s*:\s*'([^']+)'/),s=a.match(/'shape'\s*:\s*\(([^)]*)\)/);if(!o)throw Error(`Could not parse dtype from .npy header: `+a);return{descr:o[1],shape:s?s[1].split(`,`).map(e=>parseInt(e.trim(),10)).filter(e=>!isNaN(e)):[],dataOffset:i+r}}function a(e){let{descr:t,shape:n,dataOffset:r}=i(e),a=e.slice(r),o=new ArrayBuffer(a.length);new Uint8Array(o).set(a);let s;if(t===`<f4`||t===`float32`)s=new Float32Array(o);else if(t===`<f8`||t===`float64`){let e=new Float64Array(o);s=new Float32Array(e.length);for(let t=0;t<e.length;t++)s[t]=e[t]}else throw Error(`Unsupported npy dtype: `+t);return{data:s,shape:n}}async function o(e){let t=new Uint8Array(e),n=new DataView(e),r=new Map,i=-1;for(let e=t.length-22;e>=0;e--)if(n.getUint32(e,!0)===101010256){i=e;break}if(i===-1)throw Error(`Could not find End of Central Directory`);let a=n.getUint32(i+16,!0),o=n.getUint16(i+10,!0),s=[],c=a;for(let e=0;e<o&&n.getUint32(c,!0)===33639248;e++){let e=n.getUint16(c+10,!0),r=n.getUint32(c+20,!0),i=n.getUint32(c+24,!0),a=n.getUint16(c+28,!0),o=n.getUint16(c+30,!0),l=n.getUint16(c+32,!0),u=n.getUint32(c+42,!0),d=new TextDecoder().decode(t.slice(c+46,c+46+a));s.push({fileName:d,compressedSize:r,uncompressedSize:i,localHeaderOffset:u,compressionMethod:e}),c+=46+a+o+l}for(let e of s){let i=e.localHeaderOffset,a=n.getUint16(i+26,!0),o=n.getUint16(i+28,!0),s=i+30+a+o,c;if(e.compressionMethod===0)c=t.slice(s,s+e.uncompressedSize);else if(e.compressionMethod===8){let n=t.slice(s,s+e.compressedSize),r=new DecompressionStream(`deflate-raw`),i=r.writable.getWriter();i.write(n),i.close();let a=r.readable.getReader(),o=[],l=0;for(;;){let{done:e,value:t}=await a.read();if(e)break;o.push(t),l+=t.length}c=new Uint8Array(l);let u=0;for(let e of o)c.set(e,u),u+=e.length}else{console.warn(`Skipping ${e.fileName}: unsupported compression ${e.compressionMethod}`);continue}r.set(e.fileName,c)}return r}async function s(e){let t=await fetch(e);if(!t.ok)throw Error(`Failed to fetch voices: ${t.status}`);let n=await o(await t.arrayBuffer()),r={};for(let[e,t]of n){if(!e.endsWith(`.npy`))continue;let n=e.replace(/\.npy$/,``),{data:i,shape:o}=a(t);r[n]={data:i,shape:[o[0]||1,o[1]||i.length]}}return r}let c,l;const u=[`Nano`,`nano`,`fp32`];let d=null,f={},p=null,m=`wasm`;function h(e,t){return`https://huggingface.co/${e}/resolve/main/${t}`}async function g(){try{return`gpu`in navigator?!!await navigator.gpu.requestAdapter():!1}catch{return!1}}async function _(e){self.postMessage({type:`status`,message:`Detecting hardware...`});let t=await g();self.postMessage({type:`status`,message:`Loading runtime...`});let[n,r]=await Promise.all([import(`./ort.bundle.min-DL658BJE.js`),import(`./phonemizer-BgK0uh4o.js`)]);l=n,c=r.phonemize,self.postMessage({type:`status`,message:`Loading config...`});let i=await fetch(h(e,`kitten_config.json`));i.ok||(i=await fetch(h(e,`config.json`))),p=await i.json();let a=p.model||e.split(`/`).pop()||``,o=u.some(e=>a.includes(e));m=t&&o?`webgpu`:`wasm`,t&&!o&&console.log(`[KittenTTS] Using WASM for "${a}" (WebGPU only confirmed for nano-fp32)`),self.postMessage({type:`device`,device:m}),self.postMessage({type:`status`,message:`Downloading model & voices...`});let _=h(e,e.startsWith(`onnx-community/`)?`onnx/model.onnx`:p.model_file),v=(async()=>{let e=await fetch(_);if(!e.ok)throw Error(`Failed to fetch model: ${e.status}`);let t=parseInt(e.headers.get(`content-length`)||`0`,10),n=e.body.getReader(),r=[],i=0;for(;;){let{done:e,value:a}=await n.read();if(e)break;if(r.push(a),i+=a.length,t>0){let e=Math.round(i/t*100),n=(i/1024/1024).toFixed(1);self.postMessage({type:`status`,message:`Downloading model... ${e}% (${n} MB)`})}}let a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.length;return a.buffer})(),y=s(h(e,p.voices)),[b,x]=await Promise.all([v,y]);f=x,self.postMessage({type:`status`,message:`Initializing ${m.toUpperCase()} session...`});let S={executionProviders:m===`webgpu`?[`webgpu`]:[`wasm`]};m===`wasm`&&(l.env.wasm.numThreads=1),d=await l.InferenceSession.create(b,S);let C=p.voice_aliases?Object.keys(p.voice_aliases):Object.keys(f);self.postMessage({type:`ready`,voices:C,device:m,modelName:p.name})}function v(e){return e=e.trim(),e&&(`.!?,;:`.includes(e[e.length-1])||(e+=`.`),e)}function y(e,t=400){let n=e.match(/[^.!?]*[.!?]+|[^.!?]+$/g)||[e],r=[];for(let e of n)if(e=e.trim(),e)if(e.length<=t)r.push(v(e));else{let n=e.split(/\s+/),i=``;for(let e of n)i.length+e.length+1<=t?i+=(i?` `:``)+e:(i&&r.push(v(i)),i=e);i&&r.push(v(i))}return r}function b(e){return e.match(/[\p{L}\p{N}_]+|[^\p{L}\p{N}_\s]/gu)||[]}async function x(e,t,n){if(!d||!p)throw Error(`Model not loaded`);let i=t;p.voice_aliases?.[t]&&(i=p.voice_aliases[t]);let a=f[i];if(!a)throw Error(`Voice "${t}" not found`);p.speed_priors?.[i]&&(n*=p.speed_priors[i]);let o=/(\s*[;:,.!?¡¿—…"«»""()\[\]{}]+\s*)+/g,s=[],u=0;for(let t of e.matchAll(o))u<t.index&&s.push({match:!1,text:e.slice(u,t.index)}),s.push({match:!0,text:t[0]}),u=t.index+t[0].length;u<e.length&&s.push({match:!1,text:e.slice(u)});let h=r(b((await Promise.all(s.map(async e=>e.match?e.text:(await c(e.text,`en-us`)).join(` `)))).join(``)).join(` `)),g=Math.min(e.length,a.shape[0]-1),_=a.shape[1],v=a.data.slice(g*_,(g+1)*_),y=new l.Tensor(`int64`,BigInt64Array.from(h.map(BigInt)),[1,h.length]),x=new l.Tensor(`float32`,v,[1,_]),S=new l.Tensor(`float32`,new Float32Array([n]),[1]),C=(await d.run({input_ids:y,style:x,speed:S}))[d.outputNames[0]].data;return C.length>0&&isNaN(C[0])&&console.warn(`[KittenTTS] Model produced NaN audio — this model may not be compatible with ${m.toUpperCase()}`),C.length>24e3?C.slice(0,C.length-5e3):C}async function S(e,t,n){try{let r=y(e);self.postMessage({type:`status`,message:`Generating (${r.length} chunk${r.length>1?`s`:``})...`});let i=[];for(let e=0;e<r.length;e++){self.postMessage({type:`progress`,current:e+1,total:r.length});let a=await x(r[e],t,n);i.push(a)}let a=i.reduce((e,t)=>e+t.length,0),o=new Float32Array(a),s=0;for(let e of i)o.set(e,s),s+=e.length;self.postMessage({type:`audio`,audio:o.buffer,sampleRate:24e3},{transfer:[o.buffer]})}catch(e){self.postMessage({type:`error`,error:e.message||String(e)})}}self.addEventListener(`message`,async e=>{let{action:t,...n}=e.data;switch(t){case`load`:try{await _(n.repoId)}catch(e){console.error(`[KittenTTS Worker] Load error:`,e),self.postMessage({type:`error`,error:e.message||String(e)})}break;case`generate`:await S(n.text,n.voice,n.speed);break}}),self.addEventListener(`error`,e=>{self.postMessage({type:`error`,error:e.message||`Unknown worker error`})}),self.addEventListener(`unhandledrejection`,e=>{self.postMessage({type:`error`,error:e.reason?.message||String(e.reason)})});
|
index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
<title>KittenTTS — Browser TTS with WebGPU</title>
|
| 7 |
<meta name="description" content="Text-to-speech running entirely in your browser via WebGPU. Powered by KittenML models and Transformers.js v4." />
|
| 8 |
-
<script type="module" crossorigin src="/assets/index-
|
| 9 |
<link rel="stylesheet" crossorigin href="/assets/index-BeBO3FHr.css">
|
| 10 |
</head>
|
| 11 |
<body>
|
|
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
<title>KittenTTS — Browser TTS with WebGPU</title>
|
| 7 |
<meta name="description" content="Text-to-speech running entirely in your browser via WebGPU. Powered by KittenML models and Transformers.js v4." />
|
| 8 |
+
<script type="module" crossorigin src="/assets/index-D3BIbg-L.js"></script>
|
| 9 |
<link rel="stylesheet" crossorigin href="/assets/index-BeBO3FHr.css">
|
| 10 |
</head>
|
| 11 |
<body>
|