Upload 4 files
Browse files- SNAC-Decoder-in-browser.html +389 -0
- snac_flattened (1).txt +1 -0
- snac_flattened_stream.txt +1 -0
SNAC-Decoder-in-browser.html
ADDED
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!doctype html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8" />
|
5 |
+
<title>SNAC 24k — Click-free Streaming (Robust scheduler + Cache)</title>
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
+
<style>
|
8 |
+
:root { color-scheme: dark light; }
|
9 |
+
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, "Helvetica Neue", Arial; margin:0 }
|
10 |
+
header { padding:16px 20px; background:#111827; color:#f9fafb }
|
11 |
+
main { padding:16px; display:grid; gap:16px; grid-template-columns:1fr 380px }
|
12 |
+
section { border:1px solid #e5e7eb20; border-radius:12px; padding:12px 14px; background:#0b1220; color:#e5e7eb }
|
13 |
+
h1{ margin:0 0 6px 0; font-size:20px } h2{ margin:8px 0; font-size:16px }
|
14 |
+
.row{ display:flex; gap:8px; align-items:center; flex-wrap:wrap }
|
15 |
+
.btn{ padding:8px 12px; border-radius:10px; border:1px solid #475569; background:#1f2937; color:#e5e7eb; cursor:pointer }
|
16 |
+
.btn:disabled{ opacity:.5; cursor:not-allowed }
|
17 |
+
.mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace }
|
18 |
+
textarea{ width:100%; min-height:160px; border-radius:10px; border:1px solid #334155; background:#0b1220; color:#e5e7eb; padding:10px }
|
19 |
+
input[type="number"],input[type="text"],select{ padding:6px 8px; border-radius:8px; border:1px solid #334155; background:#0b1220; color:#e5e7eb }
|
20 |
+
.grid{ display:grid; gap:10px; grid-template-columns:repeat(2,1fr) }
|
21 |
+
.log{ height:180px; overflow:auto; background:#0a0f1c; border-radius:8px; padding:8px; border:1px solid #1f2937 }
|
22 |
+
.small{ font-size:12px; opacity:.9 } .muted{ opacity:.7 }
|
23 |
+
.pill{ display:inline-block; padding:4px 8px; border-radius:999px; background:#0b132b; border:1px solid #334155; margin:2px }
|
24 |
+
.progress{ width:100%; height:8px; background:#111827; border-radius:999px; overflow:hidden; border:1px solid #374151 }
|
25 |
+
.progress>div{ height:100%; background:#22c55e; width:0% }
|
26 |
+
audio{ width:100%; margin-top:8px }
|
27 |
+
</style>
|
28 |
+
</head>
|
29 |
+
<body>
|
30 |
+
<header>
|
31 |
+
<h1>SNAC 24 kHz — Click-free Streaming (Robust scheduler + Cache)</h1>
|
32 |
+
<div class="small muted">Streaming uses 48-frame windows, default hop 40, center-keep & equal-power crossfade. Preloads model into IndexedDB cache.</div>
|
33 |
+
</header>
|
34 |
+
|
35 |
+
<main>
|
36 |
+
<section>
|
37 |
+
<h2>1) Inputs</h2>
|
38 |
+
<div class="grid">
|
39 |
+
<div>
|
40 |
+
<div class="small muted">Model URL (int→wav ONNX)</div>
|
41 |
+
<input id="modelUrl" class="mono" type="text" style="width:100%"
|
42 |
+
value="https://huggingface.co/laion/SNAC-24khz-decoder-onnx/resolve/main/snac24_int2wav_static.onnx">
|
43 |
+
</div>
|
44 |
+
<div>
|
45 |
+
<div class="small muted">Codes URL (flattened JSON)</div>
|
46 |
+
<input id="codesUrl" class="mono" type="text" style="width:100%"
|
47 |
+
value="https://huggingface.co/laion/SNAC-24khz-decoder-onnx/resolve/main/snac_flattened_stream.txt">
|
48 |
+
</div>
|
49 |
+
</div>
|
50 |
+
<div class="row" style="margin-top:8px;gap:12px;">
|
51 |
+
<button id="preloadBtn" class="btn">Preload model (and cache)</button>
|
52 |
+
<button id="loadCodesBtn" class="btn">Load codes into textbox</button>
|
53 |
+
<button id="clearCacheBtn" class="btn">Clear cache</button>
|
54 |
+
<span id="preloadStatus" class="small pill">idle</span>
|
55 |
+
</div>
|
56 |
+
<div class="progress" style="margin:8px 0;"><div id="dlBar"></div></div>
|
57 |
+
<div class="small" id="dlText"></div>
|
58 |
+
</section>
|
59 |
+
|
60 |
+
<section>
|
61 |
+
<h2>2) Decode options</h2>
|
62 |
+
<div class="grid">
|
63 |
+
<div>
|
64 |
+
<div class="small muted">Execution Provider</div>
|
65 |
+
<select id="providerSel">
|
66 |
+
<option value="webgpu">webgpu (if available)</option>
|
67 |
+
<option value="wasm">wasm</option>
|
68 |
+
</select>
|
69 |
+
</div>
|
70 |
+
<div>
|
71 |
+
<div class="small muted">Streaming mode</div>
|
72 |
+
<select id="modeSel">
|
73 |
+
<option value="stream">Streaming (center-keep)</option>
|
74 |
+
<option value="whole">Whole file (assemble then play)</option>
|
75 |
+
<option value="fixed">Fixed windows (butt-join; for comparison)</option>
|
76 |
+
</select>
|
77 |
+
</div>
|
78 |
+
<div>
|
79 |
+
<div class="small muted">Hop (L2 frames)</div>
|
80 |
+
<input id="hopFrames" type="number" min="8" max="48" step="4" value="40">
|
81 |
+
</div>
|
82 |
+
<div>
|
83 |
+
<div class="small muted">Crossfade (ms)</div>
|
84 |
+
<input id="xfadeMs" type="number" min="0" max="40" step="2" value="12">
|
85 |
+
</div>
|
86 |
+
<div>
|
87 |
+
<div class="small muted">Keep center (L2 frames)</div>
|
88 |
+
<input id="keepFrames" type="number" min="8" max="48" step="4" value="40">
|
89 |
+
</div>
|
90 |
+
<div>
|
91 |
+
<div class="small muted">Window (L2 frames)</div>
|
92 |
+
<input id="winFrames" type="number" min="48" max="48" step="0" value="48" disabled>
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
<div class="row" style="margin-top:8px; gap:12px;">
|
96 |
+
<label class="small"><input id="sequentialChk" type="checkbox"> Sequential playback (no overlap)</label>
|
97 |
+
<span class="small muted">Sample rate 24,000 Hz</span>
|
98 |
+
</div>
|
99 |
+
<div class="row" style="margin-top:8px; gap:12px;">
|
100 |
+
<button id="generateBtn" class="btn">Generate</button>
|
101 |
+
</div>
|
102 |
+
</section>
|
103 |
+
|
104 |
+
<section style="grid-column:1 / span 2;">
|
105 |
+
<h2>3) Flattened SNAC JSON</h2>
|
106 |
+
<textarea id="snacIn" class="mono" spellcheck="false"
|
107 |
+
placeholder='Paste the single-line JSON (with "flattened","lengths", optional "streaming") here…'></textarea>
|
108 |
+
</section>
|
109 |
+
|
110 |
+
<section>
|
111 |
+
<h2>4) Output</h2>
|
112 |
+
<div class="small">Player</div>
|
113 |
+
<audio id="player" controls></audio>
|
114 |
+
<div class="small" style="margin-top:8px;">Metrics</div>
|
115 |
+
<pre id="metrics" class="log mono"></pre>
|
116 |
+
</section>
|
117 |
+
|
118 |
+
<section>
|
119 |
+
<h2>5) Logs & Info</h2>
|
120 |
+
<pre id="log" class="log mono"></pre>
|
121 |
+
<div class="small muted">
|
122 |
+
<p><b>WebGPU</b> runs operations on your GPU (fast when supported). <b>WASM</b> runs on CPU; SIMD is automatic; multithreading needs cross-origin isolation (COOP/COEP). Without COI, WASM uses 1 thread.</p>
|
123 |
+
<p>Streaming: 48-frame windows, hop 40, keep center 40. Equal-power crossfade removes seams. “Sequential” forces no overlap and starts each chunk only after the previous ended (sets crossfade to 0).</p>
|
124 |
+
</div>
|
125 |
+
</section>
|
126 |
+
</main>
|
127 |
+
|
128 |
+
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
|
129 |
+
<script>
|
130 |
+
(async () => {
|
131 |
+
const el = id => document.getElementById(id);
|
132 |
+
const modelUrl = el('modelUrl'), codesUrl = el('codesUrl');
|
133 |
+
const preloadBtn = el('preloadBtn'), loadCodesBtn = el('loadCodesBtn'), clearCacheBtn = el('clearCacheBtn');
|
134 |
+
const preloadStatus = el('preloadStatus'), dlBar = el('dlBar'), dlText = el('dlText');
|
135 |
+
const providerSel = el('providerSel'), modeSel = el('modeSel');
|
136 |
+
const hopFrames = el('hopFrames'), keepFrames = el('keepFrames'), xfadeMs = el('xfadeMs'), winFrames = el('winFrames');
|
137 |
+
const sequentialChk = el('sequentialChk');
|
138 |
+
const snacIn = el('snacIn'), player = el('player'), metrics = el('metrics'), logbox = el('log');
|
139 |
+
const genBtn = el('generateBtn');
|
140 |
+
|
141 |
+
const log = (...a)=>{ console.log(...a); logbox.textContent += a.join(' ') + '\n'; logbox.scrollTop = logbox.scrollHeight; }
|
142 |
+
const fmt = o => JSON.stringify(o, null, 2);
|
143 |
+
|
144 |
+
// ===== IndexedDB tiny cache =====
|
145 |
+
const DB='snac-cache', STORE='files';
|
146 |
+
function idb(){ return new Promise((res,rej)=>{ const r=indexedDB.open(DB,1); r.onupgradeneeded=()=>r.result.createObjectStore(STORE); r.onsuccess=()=>res(r.result); r.onerror=()=>rej(r.error); }); }
|
147 |
+
async function idbGet(k){ const db=await idb(); return new Promise((res,rej)=>{ const tx=db.transaction(STORE,'readonly'); const rq=tx.objectStore(STORE).get(k); rq.onsuccess=()=>res(rq.result||null); rq.onerror=()=>rej(rq.error); }); }
|
148 |
+
async function idbSet(k,v){ const db=await idb(); return new Promise((res,rej)=>{ const tx=db.transaction(STORE,'readwrite'); tx.objectStore(STORE).put(v,k); tx.oncomplete=()=>res(true); tx.onerror=()=>rej(tx.error); }); }
|
149 |
+
async function idbDel(k){ const db=await idb(); return new Promise((res,rej)=>{ const tx=db.transaction(STORE,'readwrite'); tx.objectStore(STORE).delete(k); tx.oncomplete=()=>res(true); tx.onerror=()=>rej(tx.error); }); }
|
150 |
+
clearCacheBtn.onclick = async () => { await idbDel(modelUrl.value.trim()); log('Cache cleared for', modelUrl.value.trim()); };
|
151 |
+
|
152 |
+
// ===== network with progress =====
|
153 |
+
async function fetchWithProgress(url, onProg){
|
154 |
+
const r = await fetch(url); if(!r.ok) throw new Error(`HTTP ${r.status} for ${url}`);
|
155 |
+
const len = Number(r.headers.get('Content-Length'))||0;
|
156 |
+
if(!r.body || !window.ReadableStream){ const buf=await r.arrayBuffer(); onProg?.(buf.byteLength,len); return buf; }
|
157 |
+
const reader=r.body.getReader(); const chunks=[]; let got=0;
|
158 |
+
for(;;){ const {done,value}=await reader.read(); if(done) break; chunks.push(value); got+=value.byteLength; onProg?.(got,len); }
|
159 |
+
const out=new Uint8Array(got); let off=0; for(const c of chunks){ out.set(c,off); off+=c.byteLength; } return out.buffer;
|
160 |
+
}
|
161 |
+
|
162 |
+
// ===== ORT env =====
|
163 |
+
const coi = (typeof crossOriginIsolated!=='undefined') ? crossOriginIsolated : false;
|
164 |
+
ort.env.wasm.simd = true;
|
165 |
+
ort.env.wasm.numThreads = coi ? (navigator.hardwareConcurrency||4) : 1;
|
166 |
+
|
167 |
+
// ===== preload model (with cache) =====
|
168 |
+
let session=null, sessionEP=null;
|
169 |
+
async function preloadModel(){
|
170 |
+
try{
|
171 |
+
const url = modelUrl.value.trim();
|
172 |
+
preloadBtn.disabled = true; dlBar.style.width='0%'; dlText.textContent=''; preloadStatus.textContent='checking cache…';
|
173 |
+
let buf = await idbGet(url);
|
174 |
+
if(buf){ preloadStatus.textContent='cache hit'; dlBar.style.width='100%'; dlText.textContent='Loaded from IndexedDB'; }
|
175 |
+
else{
|
176 |
+
preloadStatus.textContent='downloading…';
|
177 |
+
buf = await fetchWithProgress(url, (got,total)=>{
|
178 |
+
const pct = total ? Math.round(100*got/total) : 0;
|
179 |
+
dlBar.style.width = `${pct}%`;
|
180 |
+
dlText.textContent = total ? `Downloading: ${pct}% (${(got/1e6).toFixed(1)} / ${(total/1e6).toFixed(1)} MB)` :
|
181 |
+
`Downloading: ${(got/1e6).toFixed(1)} MB`;
|
182 |
+
});
|
183 |
+
await idbSet(url, buf); log('Cached model to IndexedDB');
|
184 |
+
}
|
185 |
+
const want = (providerSel.value==='webgpu' && 'gpu' in navigator) ? ['webgpu','wasm'] : ['wasm'];
|
186 |
+
const t0=performance.now();
|
187 |
+
preloadStatus.textContent='compiling…';
|
188 |
+
session = await ort.InferenceSession.create(buf, { executionProviders: want, graphOptimizationLevel: 'all' });
|
189 |
+
const t1=performance.now(); sessionEP = session.executionProvider ?? want[0];
|
190 |
+
preloadStatus.textContent=`ready (${(t1-t0).toFixed(1)} ms) via ${sessionEP}`;
|
191 |
+
log('Session ready. EP:', sessionEP, 'compile_ms:', (t1-t0).toFixed(1));
|
192 |
+
}catch(e){ log('Preload error:', e); }
|
193 |
+
finally{ preloadBtn.disabled=false; }
|
194 |
+
}
|
195 |
+
preloadBtn.onclick = preloadModel;
|
196 |
+
window.addEventListener('load', ()=>preloadModel().catch(e=>log('Preload error:',e)));
|
197 |
+
|
198 |
+
// ===== load codes =====
|
199 |
+
loadCodesBtn.onclick = async ()=>{
|
200 |
+
try{ const r=await fetch(codesUrl.value.trim()); if(!r.ok) throw new Error(`HTTP ${r.status}`);
|
201 |
+
const txt=await r.text(); snacIn.value = txt.trim(); log('Loaded codes text.'); }
|
202 |
+
catch(e){ log('Load codes error:', e); }
|
203 |
+
};
|
204 |
+
|
205 |
+
// ===== SNAC helpers =====
|
206 |
+
const SPF = 512, SR = 24000;
|
207 |
+
function unflatten(flat,L0,A=0,K=4096){
|
208 |
+
const L1=2*L0, L2=4*L0;
|
209 |
+
const c0=new BigInt64Array(L0), c1=new BigInt64Array(L1), c2=new BigInt64Array(L2);
|
210 |
+
const bA=BigInt(A), bK=BigInt(K), mod=v=>((v%bK)+bK)%bK;
|
211 |
+
for(let i=0;i<L0;i++){
|
212 |
+
const v0=BigInt(flat[7*i+0])-(bA+0n*bK), v1=BigInt(flat[7*i+1])-(bA+1n*bK);
|
213 |
+
const v2=BigInt(flat[7*i+2])-(bA+2n*bK), v3=BigInt(flat[7*i+3])-(bA+3n*bK);
|
214 |
+
const v4=BigInt(flat[7*i+4])-(bA+4n*bK), v5=BigInt(flat[7*i+5])-(bA+5n*bK), v6=BigInt(flat[7*i+6])-(bA+6n*bK);
|
215 |
+
c0[i]=mod(v0); c1[2*i]=mod(v1); c2[4*i]=mod(v2); c2[4*i+1]=mod(v3);
|
216 |
+
c1[2*i+1]=mod(v4); c2[4*i+2]=mod(v5); c2[4*i+3]=mod(v6);
|
217 |
+
}
|
218 |
+
return {c0,c1,c2};
|
219 |
+
}
|
220 |
+
function sliceEdgePad(src,start,len){
|
221 |
+
const T=src.length, out=new BigInt64Array(len);
|
222 |
+
for(let i=0;i<len;i++){ let j=start+i; if(j<0) j=0; if(j>=T) j=T-1; out[i]=src[j]; }
|
223 |
+
return out;
|
224 |
+
}
|
225 |
+
function concatFloat32(a,b){ const out=new Float32Array(a.length+b.length); out.set(a,0); out.set(b,a.length); return out; }
|
226 |
+
|
227 |
+
// ===== robust scheduler: gain-node crossfades + safety headroom + detailed logging =====
|
228 |
+
async function generate(){
|
229 |
+
try{
|
230 |
+
genBtn.disabled=true; metrics.textContent=''; logbox.textContent='';
|
231 |
+
if(!session) await preloadModel();
|
232 |
+
|
233 |
+
const blob = JSON.parse(snacIn.value.trim());
|
234 |
+
const A = blob.audio_tokens_start ?? 0;
|
235 |
+
const K = blob.codebook_size ?? 4096;
|
236 |
+
const L0 = blob.lengths?.L0 ?? Math.floor((blob.flattened.length)/7);
|
237 |
+
const flat = blob.flattened; if(!Array.isArray(flat)) throw new Error("flattened missing");
|
238 |
+
const {c0,c1,c2} = unflatten(flat, L0, A, K);
|
239 |
+
const L2=c2.length, T_true=L2*SPF;
|
240 |
+
log(`Parsed L0/L1/L2 = ${L0}/${c1.length}/${L2} -> true samples ${T_true}`);
|
241 |
+
|
242 |
+
// streaming params (with sane defaults)
|
243 |
+
const s = blob.streaming || {};
|
244 |
+
const K2 = Number(winFrames.value)||48;
|
245 |
+
const H2 = Number(hopFrames.value)||Number(s.hop_frames||40);
|
246 |
+
const keepF = Number(keepFrames.value)||Number(s.center_keep_frames||40);
|
247 |
+
const leftCtx = Number(s.left_ctx_frames ?? ((K2-keepF)/2));
|
248 |
+
const xfade = Number(xfadeMs.value ?? s.xfade_ms_default ?? 12);
|
249 |
+
const sequential = !!sequentialChk.checked;
|
250 |
+
const overlapSec = sequential ? 0 : (xfade/1000);
|
251 |
+
|
252 |
+
const SAFETY = 0.040; // 40 ms safety to avoid underschedule
|
253 |
+
const ctx = new (window.AudioContext||window.webkitAudioContext)({sampleRate: SR});
|
254 |
+
let playClock = ctx.currentTime + 0.10; // first chunk start
|
255 |
+
let scheduledEnd = null; // end time of last scheduled chunk (audio time)
|
256 |
+
let windows=0, samples=0; const t0=performance.now();
|
257 |
+
|
258 |
+
async function runWindow(c0w,c1w,c2w, keepStart, keepEnd){
|
259 |
+
const feeds = {
|
260 |
+
codes0: new ort.Tensor('int64', c0w,[1,c0w.length]),
|
261 |
+
codes1: new ort.Tensor('int64', c1w,[1,c1w.length]),
|
262 |
+
codes2: new ort.Tensor('int64', c2w,[1,c2w.length]),
|
263 |
+
};
|
264 |
+
const tA=performance.now();
|
265 |
+
const out = await session.run(feeds);
|
266 |
+
const tB=performance.now();
|
267 |
+
const audio = out.audio.data; // Float32 [24576]
|
268 |
+
const kept = audio.subarray(keepStart, keepEnd);
|
269 |
+
const segSec = kept.length / SR;
|
270 |
+
samples += kept.length;
|
271 |
+
|
272 |
+
// Build nodes
|
273 |
+
const buf = ctx.createBuffer(1, kept.length, SR);
|
274 |
+
buf.copyToChannel(kept, 0, 0);
|
275 |
+
const src = ctx.createBufferSource(); src.buffer = buf;
|
276 |
+
const g = ctx.createGain(); g.gain.setValueAtTime(1, ctx.currentTime);
|
277 |
+
src.connect(g).connect(ctx.destination);
|
278 |
+
|
279 |
+
// Decide start time
|
280 |
+
const desiredStart = (scheduledEnd==null) ? playClock : (sequential ? scheduledEnd : scheduledEnd - overlapSec);
|
281 |
+
const now = ctx.currentTime;
|
282 |
+
const startAt = Math.max(desiredStart, now + SAFETY);
|
283 |
+
const endAt = startAt + segSec;
|
284 |
+
|
285 |
+
// Apply equal-power crossfade via gains (if overlapping)
|
286 |
+
if(!sequential && scheduledEnd!==null && overlapSec>0){
|
287 |
+
const prevDropStart = startAt;
|
288 |
+
const prevDropEnd = Math.min(startAt + overlapSec, scheduledEnd);
|
289 |
+
// fade previous node down if we have a handle:
|
290 |
+
const prev = lastGainNode;
|
291 |
+
if(prev){
|
292 |
+
prev.gain.setValueAtTime(1, prevDropStart);
|
293 |
+
prev.gain.linearRampToValueAtTime(0, prevDropEnd);
|
294 |
+
}
|
295 |
+
// fade current node up
|
296 |
+
g.gain.setValueAtTime(0, startAt);
|
297 |
+
g.gain.linearRampToValueAtTime(1, startAt + overlapSec);
|
298 |
+
}
|
299 |
+
|
300 |
+
src.start(startAt);
|
301 |
+
windows += 1;
|
302 |
+
scheduledEnd = endAt;
|
303 |
+
lastGainNode = g;
|
304 |
+
|
305 |
+
const late = Math.max(0, (now + SAFETY) - desiredStart);
|
306 |
+
log(`win#${windows} infer ${(tB-tA).toFixed(2)} ms now ${now.toFixed(3)} desired ${desiredStart.toFixed(3)} start ${startAt.toFixed(3)} end ${endAt.toFixed(3)} overlap ${sequential?0:(overlapSec*1000)} ms late ${ (late*1000).toFixed(1)} ms`);
|
307 |
+
}
|
308 |
+
|
309 |
+
// window generators
|
310 |
+
function* fixedWindows(){
|
311 |
+
const nWin=Math.ceil(L2/48);
|
312 |
+
for(let i=0;i<nWin;i++){
|
313 |
+
const s2=i*48,s1=i*24,s0=i*12;
|
314 |
+
yield { c0w:sliceEdgePad(c0,s0,12), c1w:sliceEdgePad(c1,s1,24), c2w:sliceEdgePad(c2,s2,48),
|
315 |
+
keepStart:0, keepEnd:48*SPF };
|
316 |
+
}
|
317 |
+
}
|
318 |
+
function* slidingCenterWindows(){
|
319 |
+
let s2=0,i=0; const keepStart = ((K2-keepF)/2)*SPF, keepEnd=((K2-keepF)/2+keepF)*SPF;
|
320 |
+
while(s2 < L2 || i===0){
|
321 |
+
const s1=Math.floor(s2/2), s0=Math.floor(s2/4);
|
322 |
+
yield { c0w:sliceEdgePad(c0,s0,K2/4), c1w:sliceEdgePad(c1,s1,K2/2), c2w:sliceEdgePad(c2,s2,K2),
|
323 |
+
keepStart, keepEnd };
|
324 |
+
s2 += (modeSel.value==='fixed'?48:H2); i++; if(s2>=L2 && modeSel.value!=='fixed') break;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
// choose mode
|
329 |
+
const mode=modeSel.value;
|
330 |
+
let gen;
|
331 |
+
if(mode==='fixed') gen = fixedWindows;
|
332 |
+
else gen = slidingCenterWindows;
|
333 |
+
|
334 |
+
// scheduling
|
335 |
+
let lastGainNode = null;
|
336 |
+
if(mode==='whole'){
|
337 |
+
// assemble then play (still center-keep in sliding path)
|
338 |
+
let full = new Float32Array(0);
|
339 |
+
for(const {c0w,c1w,c2w,keepStart,keepEnd} of slidingCenterWindows()){
|
340 |
+
const out = await session.run({
|
341 |
+
codes0:new ort.Tensor('int64', c0w,[1,c0w.length]),
|
342 |
+
codes1:new ort.Tensor('int64', c1w,[1,c1w.length]),
|
343 |
+
codes2:new ort.Tensor('int64', c2w,[1,c2w.length]),
|
344 |
+
});
|
345 |
+
const a = out.audio.data.subarray(keepStart, keepEnd);
|
346 |
+
full = concatFloat32(full, a);
|
347 |
+
windows++; samples += a.length;
|
348 |
+
}
|
349 |
+
full = full.subarray(0, T_true);
|
350 |
+
const wav = pcm16Wav(full, SR);
|
351 |
+
player.src = URL.createObjectURL(new Blob([wav], {type:'audio/wav'}));
|
352 |
+
await player.play().catch(()=>{});
|
353 |
+
} else {
|
354 |
+
for(const w of gen()){
|
355 |
+
await runWindow(w.c0w, w.c1w, w.c2w, w.keepStart, w.keepEnd);
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
+
const t1=performance.now();
|
360 |
+
const r = {
|
361 |
+
usedEP: sessionEP || providerSel.value,
|
362 |
+
threads: ort.env.wasm.numThreads||1,
|
363 |
+
simd: ort.env.wasm.simd===true,
|
364 |
+
coi, windows, samples,
|
365 |
+
audio_seconds: samples/SR,
|
366 |
+
inference_ms: (t1-t0),
|
367 |
+
rtf: ( (samples/SR) / ((t1-t0)/1000) ).toFixed(3)
|
368 |
+
};
|
369 |
+
metrics.textContent = fmt({env:{coi, hwc:navigator.hardwareConcurrency||1}, providers:['webgpu','wasm']}) + "\n" + fmt(r);
|
370 |
+
log('Done.', r);
|
371 |
+
|
372 |
+
function pcm16Wav(float32, sr){
|
373 |
+
const clamp=v=>Math.max(-1,Math.min(1,v));
|
374 |
+
const pcm=new Int16Array(float32.length); for(let i=0;i<float32.length;i++) pcm[i]=Math.round(clamp(float32[i])*32767);
|
375 |
+
const bytes=44+pcm.length*2, buf=new ArrayBuffer(bytes), dv=new DataView(buf); let p=0, w=s=>{ for(let i=0;i<s.length;i++) dv.setUint8(p++, s.charCodeAt(i)); };
|
376 |
+
w('RIFF'); dv.setUint32(p,bytes-8,true); p+=4; w('WAVE'); w('fmt '); dv.setUint32(p,16,true); p+=4;
|
377 |
+
dv.setUint16(p,1,true); p+=2; dv.setUint16(p,1,true); p+=2; dv.setUint32(p,sr,true); p+=4;
|
378 |
+
dv.setUint32(p,sr*2,true); p+=4; dv.setUint16(p,2,true); p+=2; dv.setUint16(p,16,true); p+=2;
|
379 |
+
w('data'); dv.setUint32(p, pcm.length*2, true); p+=4; new Uint8Array(buf).set(new Uint8Array(pcm.buffer),44); return new Uint8Array(buf);
|
380 |
+
}
|
381 |
+
}catch(e){ console.error(e); log('ERROR:', e.message||e); }
|
382 |
+
finally{ genBtn.disabled=false; }
|
383 |
+
}
|
384 |
+
|
385 |
+
genBtn.onclick = generate;
|
386 |
+
})();
|
387 |
+
</script>
|
388 |
+
</body>
|
389 |
+
</html>
|
snac_flattened (1).txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"format":"SNAC24K-Flat7","sr":24000,"audio_tokens_start":0,"codebook_size":4096,"order":["c0","c1_even","c2_0","c2_1","c1_odd","c2_2","c2_3"],"lengths":{"L0":197,"L1":394,"L2":788},"flattened":[2731,6650,9152,12795,16388,24357,25107,3155,5489,8615,15875,17077,23744,27904,850,7304,9248,15322,18356,22770,26568,2563,5218,10463,15053,16717,22487,26461,386,5264,9906,14876,18055,21835,27865,1899,5387,10716,13654,17134,20638,25382,1747,6957,8998,15680,19260,22563,26410,415,7513,9862,15760,18604,24284,25310,1828,7254,9441,13474,16413,21044,27826,2156,6675,10415,16068,17529,23820,28458,2968,5717,11994,13073,18106,20722,28663,1684,4908,8781,13019,19477,22181,28311,294,4895,12159,13831,18617,22430,26079,2191,5709,10301,14281,19261,24009,25226,490,6594,10515,13524,18774,21530,27384,2396,6803,10016,12919,19890,23534,25816,294,5370,11241,13890,17925,20984,25248,1309,6848,12242,12642,19991,20552,27155,3399,7392,12131,15104,16443,22804,25352,3182,8191,10445,14872,19521,22574,24618,3556,7239,9233,14804,19489,20645,24709,3641,7108,10816,13847,18908,22861,26609,3020,6479,11239,14313,19846,23122,27499,2169,7501,8892,14571,19091,21852,24632,1884,5618,11050,12835,20419,23618,26533,2684,5917,11421,12547,17083,20520,25040,104,7234,11110,14919,19474,22926,27822,2819,4472,9975,15505,16703,24007,25631,3744,7754,10534,15657,16612,21913,25754,3005,7590,10841,14781,20455,20535,28432,530,6793,11437,13923,19578,23616,28317,1576,4795,8422,16303,17809,23627,26423,2870,8102,8544,13767,20211,21516,24709,1455,6413,8451,15942,18761,24444,25983,2683,5603,11468,14122,17563,24012,25065,424,7532,12067,13456,17623,20531,25626,3906,5376,11490,14454,18951,20825,28449,318,5462,9415,13328,18400,24565,27053,2244,7387,11877,14939,17793,24167,27846,359,8116,8700,12372,20062,24406,27400,167,4465,8999,14692,17776,21825,28543,2723,4230,11483,15486,18402,23931,27483,2776,5397,10261,15051,19568,23809,25171,1319,7569,11034,13758,18559,22880,28202,1163,5248,12234,16004,18018,23944,26048,306,6352,9699,14865,16806,23912,25872,132,4919,9339,15208,19695,23071,28180,2342,7418,9281,12770,17901,23350,26914,1178,5843,9870,12848,19993,24207,25369,1874,7961,9022,12410,19940,24005,27882,1693,4409,10979,14784,19558,22610,25480,3005,5575,8255,13562,18211,22331,27139,3181,7150,9808,15965,17834,21150,27133,3414,6174,10619,15629,16797,22998,27560,293,8093,9218,15521,18995,21851,26626,466,7064,11008,15067,17088,24357,28266,2781,6967,9312,13545,20049,22626,25648,2275,4135,11835,15012,20092,21183,25925,512,6906,11077,12348,17110,24387,28396,1884,4368,8778,14019,17621,20885,27257,3993,7437,12202,15440,20262,23579,26780,331,6442,10951,15540,16787,23110,28327,2770,4202,9485,12394,19684,23235,25962,3239,5026,11549,14153,16820,22936,24653,3347,5940,8508,13990,19551,21341,26418,2723,7003,11130,14825,19087,24555,26999,3510,7003,11739,12867,17314,20583,24962,331,5544,8748,14033,18324,22381,26418,806,7050,9154,15972,16806,24340,28101,3057,4671,8374,12840,19675,21496,27644,2497,7387,10417,14301,16446,23095,28503,3268,7794,9738,14237,17795,24047,25590,2791,5979,11820,13302,17970,23659,28101,2870,7057,10026,15216,16789,20556,25125,3593,4987,8667,15546,19156,23976,25470,1342,7577,10520,12295,19926,21761,26011,166,4684,10553,15055,18824,20628,25278,2851,6519,10847,13271,20085,20766,27055,2019,4561,9699,15491,17445,22508,27836,4075,5491,9182,13790,18940,22887,25831,3090,4104,12027,13125,18299,24519,27497,926,4912,10639,14904,20095,21419,24835,3397,7558,9095,15465,20083,23274,25634,2930,6232,10119,13571,20100,20516,26103,1669,5019,9491,14974,19230,21168,26812,3264,4325,12197,16207,17012,22360,27913,3706,5756,8571,15187,16974,23067,26726,1653,4343,10768,14692,18355,24474,27023,1536,7523,11825,14537,18976,23932,25949,1913,5598,8895,13144,17775,22279,27625,819,4809,10981,15209,16733,22085,28102,1840,6930,8336,12962,18041,24218,24702,218,5599,10957,15891,19382,22701,28079,1765,7965,11451,13064,20402,20758,25128,991,4618,9208,15696,17597,22001,24986,1980,7280,10106,14534,19568,23225,27269,1080,5753,11923,16270,19622,21298,28321,2479,7178,8321,15613,18044,22990,27861,1913,6926,12235,14616,18060,21872,28322,342,4946,9154,12829,20232,23225,26622,2922,7897,9481,16050,19684,21101,26765,2207,5019,12081,14239,18812,23225,27032,2055,7212,8410,15533,18804,23435,28008,1723,5385,11856,14343,17138,23872,26179,1432,4357,11781,15201,17710,21768,26236,3894,6906,11335,13227,19194,22046,24697,1372,4807,11029,14734,17795,23024,25152,946,5439,8969,12878,19602,21465,27911,850,5270,11721,15817,16969,23424,27172,3906,6663,11825,14177,19449,23075,25319,3906,6710,8984,12703,17385,23186,27740,2723,7189,10764,13108,20464,20531,24646,293,8162,10338,15499,16797,23056,26417,384,7172,11690,15946,19137,23330,28448,4068,8093,10462,14267,17450,21753,27442,2156,7231,8864,15645,19880,23540,26108,2676,4131,10906,13871,19137,22520,26425,2612,8056,11343,12501,17046,23964,28252,1036,6775,9557,16215,19136,23019,26027,3208,4851,10501,12935,18780,20909,26386,3181,6131,8776,15156,18060,23607,26441,2338,7523,10857,16346,20420,22712,24826,2296,5753,11920,13513,16613,24052,26893,2684,5207,11604,13324,16845,22432,27464,1238,4848,10400,16364,19573,24567,26847,424,5439,10930,12825,17714,22053,28650,2158,5602,10075,13396,18343,23710,25439,3880,4114,9802,14338,17745,23817,26233,331,7754,8448,15274,20278,21437,27756,1884,4583,11829,13051,19575,24305,28472,1286,6093,8437,13408,18584,20498,27335,2002,4351,10692,13831,17677,22275,25601,1183,5491,8286,15353,16639,22232,26619,2967,6139,10648,15757,16499,24144,28045,3572,6723,8370,15243,18621,22236,26851,850,6456,11398,13556,20092,22277,26373,3880,7518,8247,13883,17741,23605,26719,979,7960,8496,12733,18101,22170,25091,1577,5207,8682,15012,18976,23155,26626,2934,4800,8913,13139,18640,23022,26620,386,5511,11312,15234,16781,22719,26468,438,7549,9816,12706,16556,21439,27426,1119,5855,9061,15737,17863,20952,28247,218,5815,11560,15173,16476,23347,27807,820,6942,11724,13651,17002,20971,26266,3497,6919,8560,15811,20247,22922,24734,1913,5162,9987,13476,19470,22848,26870,2507,6036,8323,16095,16777,20562,24964,166,4125,11127,14621,16413,20698,27120,3057,7960,11717,13957,17143,21462,27433,1409,4501,11644,16053,19207,20850,25053,3052,7209,11210,13831,16874,22934,27335,1455,7864,12073,16169,18706,20897,26653,384,4795,11885,15981,19884,24173,28506,132,6642,10610,13228,19606,23532,27155,1328,4427,12017,15184,19609,23191,28442,243,4822,8814,14212,19757,22376,26441,3043,6457,10648,13700,16556,23235,25966,3114,6977,10281,14293,17067,21211,27411,3876,6995,11877,13067,20017,21608,25533,2948,4324,8478,12495,17132,21737,25390,2375,8126,9677,16138,18806,20945,25336,293,6594,11845,14518,18459,22676,28621,1743,5502,11577,16092,17202,22459,27731,693,7878,11820,16297,19869,23668,25707,2844,6110,11281,13866,17772,23197,26321,3020,8109,9845,15116,17018,23564,27771,1881,4730,11112,15925,17657,22763,26821,3880,6603,9339,12752,18129,21254,26159,1884,4593,11241,15385,18751,23468,26151,401,6684,8781,12677,19899,23606,28136,166,8017,11762,14534,17693,20872,28307,166,6255,12132,13620,19882,21039,26571,3529,5505,8780,15033,19846,21180,25489,29,4675,10315,12665,16741,24422,27934,3964,7161,10077,16243,17972,21078,26876,1304,6701,10587,14241,18204,21150,25428,1980,4266,10796,12701,19675,24208,28518,3075,4524,12143,16068,18812,24337,25988,2002,7887,8676,13571,17779,23809,25415,1913,8162,9696,15977,20450,23395,24757,293,7010,11180,16238,19298,20829,28399,344,7206,11738,13595,20247,23339,27626,1980,7280,11077,15688,19846,24320,26723,2396,7823,10372,12796,18611,23769,26297,2460,6849,8573,16328,18548,23483,28478,3025,5488,8217,16309,16471,22729,28196,3579,6333,8818,13486,19120,20698,27968,3022,8038,11395,13486,19741,22083,28301,1980,7189,9893,15617,19207,21880,27851,2295,5753,11562,16136,17541,22956,25175,2002,7731,9742,12953,17823,20926,27288,218,7447,10288,14976,16809,23972,27160,2690,5502,8728,15324,19878,23552,25666,2723,6900,9745,12769,19188,23934,26148,1455,7535,9523,14477,19506,23828,24758,602,5875,10913,13291,18120,24457,26431]}
|
snac_flattened_stream.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"format":"SNAC24K-Flat7","sr":24000,"audio_tokens_start":0,"codebook_size":4096,"order":["c0","c1_even","c2_0","c2_1","c1_odd","c2_2","c2_3"],"lengths":{"L0":139,"L1":278,"L2":556},"flattened":[1048,6127,11017,15787,19113,21048,28559,850,5561,10065,15609,19512,20684,28469,1547,6372,9618,13053,20261,20997,27840,3555,7973,8333,12371,18688,21733,28458,703,7023,9591,14346,16547,23229,27854,703,7487,8386,14195,17769,23740,28539,1206,6077,8862,14898,17143,23929,28235,4058,5886,10441,16228,18167,24547,27591,3181,7850,9967,13256,19954,21620,26236,2506,5553,11009,13191,18768,21029,24731,3234,7856,12169,15435,18538,24481,26262,76,4851,10325,15350,16911,23491,27833,298,4356,9677,15704,18642,21646,25506,1526,6278,10043,13149,19074,21855,26839,3497,6080,10718,13323,19295,21187,26020,1483,7706,11893,16328,18199,21381,26184,196,5003,12135,13160,18698,22018,27501,229,6002,9715,13903,19733,23860,27310,3894,8034,8982,13621,17478,23716,25373,3160,6770,11203,14529,17747,23268,27089,475,7888,10457,15873,18854,21313,25541,4062,7839,11284,15172,18106,21281,26749,2637,6129,9785,14336,19064,22088,25888,3003,7468,11022,12679,18592,21947,26425,2984,5541,11395,15348,16865,21079,26392,2952,4577,8766,15577,16865,21054,28616,2984,7403,11462,13175,18057,21793,26709,1703,6190,11042,13984,19769,21195,25259,1671,4290,8641,14711,19690,20874,27100,2142,8081,11050,14628,18177,21197,24814,4017,5042,11969,12540,19803,22237,27755,3097,6455,10216,13414,18880,21065,25567,756,6533,9019,15105,17216,21109,24955,3022,4793,9428,13178,16668,22866,26839,3840,7957,9714,15740,19875,23960,24638,3135,5235,8429,14963,19883,22941,25735,627,5745,10968,13998,16847,23580,27030,779,4501,8730,14139,17630,21383,25065,2898,5429,8595,14852,17387,23725,24734,492,5654,10451,12967,17942,22818,25384,1157,5044,11510,13490,19556,24242,28359,900,7472,9498,14207,16717,23058,27749,3538,5677,9080,13140,18292,21023,26395,2716,4661,8367,14278,17229,22351,28668,3020,7438,9569,15101,16978,21769,27731,1717,7856,10232,14646,19790,24359,26579,229,5034,10025,13209,18117,22837,24611,627,7310,8352,16168,19726,23078,26066,1730,4096,11297,13651,17412,22165,27960,900,6735,11315,14718,19733,21853,25570,703,5749,12100,15700,17772,21018,26045,324,6543,8723,13665,18292,24472,27184,1206,7518,10693,13859,17852,22282,27771,386,5308,8838,12484,16929,23338,26869,2698,7117,11479,15392,19480,22244,28340,1024,6434,8905,13694,17047,21273,26192,1122,5628,12072,15245,19267,21365,25570,3370,6282,10360,14376,17120,22431,27141,1579,4641,12217,15146,18914,20538,26941,3297,6273,9711,16114,17120,24422,26028,686,5876,10112,15963,16670,23702,27079,2960,6668,10796,12564,16594,24483,27503,2634,6448,11700,14330,17194,21643,25245,2498,6793,8691,15873,17280,22548,24912,1106,7099,10265,16165,18627,23266,26820,2968,4329,11806,16137,19520,23507,26665,2162,5447,12069,12819,18008,24557,28355,431,6495,12232,12355,19883,24483,27308,1957,5527,11218,15863,19709,22227,28504,814,4407,9967,12484,18408,22161,28110,468,5368,9653,14491,18414,22955,26415,3785,4766,10430,15802,17221,21197,26555,538,7369,8877,15178,19341,20569,25969,934,5221,8211,14251,18364,21110,24736,524,7255,10626,12983,17548,20634,27729,3840,5506,8536,16380,20049,24300,27764,334,6250,9354,15541,16721,23433,24595,3438,4485,11432,12784,18744,23641,28291,3022,4457,11638,12667,19788,21330,25179,1318,7948,10194,15560,18519,21075,28046,679,6334,9841,14276,16703,21141,24729,3880,7754,11662,14628,20039,20632,25290,1206,5291,9345,12579,16588,21641,26937,3560,8143,9565,12991,18914,20553,25887,727,6059,8490,12345,17218,22731,25919,3390,7392,10401,12470,19535,20763,27394,2930,6305,11980,13348,20183,21801,27196,2794,7311,9172,13267,19598,21193,24686,1074,4980,9630,13856,17268,23959,28561,515,5405,9287,12978,19994,21596,25217,3097,4737,11149,12874,18985,22338,27200,2821,7972,10978,16137,20198,23725,26154,104,6406,11620,12289,19546,24138,25028,2848,5650,9719,13618,18909,20633,26178,2273,4146,8632,16169,16974,24337,27868,3927,4223,11135,14281,20424,22707,26646,3760,6923,9855,14260,20200,24337,27610,3927,5590,8211,12887,18745,21207,24736,538,5193,10887,12320,16698,23041,27310,3837,4887,9998,14291,19891,21802,26320,2292,6640,9470,14160,20376,23268,25237,2715,8141,10937,13972,19516,22904,26696,3509,6231,9024,13271,18700,21627,24747,632,4726,9156,12945,19210,21510,25716,900,6026,11672,14565,19469,21242,28340,1637,6445,11917,15076,19069,22046,27253,3894,4831,10029,12881,17137,22826,27423,3894,8081,10359,13503,18215,20778,24794,1452,7825,10956,15492,19097,21682,25773,2581,7183,10556,15592,19324,23938,27436,1018,7883,11615,13760,16592,22088,27572,2794,7854,8898,12398,20251,24444,27676,1278,5193,10208,15267,19265,21318,26408,579,5562,10539,16183,20002,21355,28591,1333,5598,11551,15798,16601,21011,28086,2646,8099,10816,14377,18051,23720,27256,3022,5357,9967,16021,19598,21468,25476,3974,6410,8523,15891,19845,23394,24912,3626,4529,9169,13383,16408,23162,25378,1501,4810,9481,15655,18928,24509,25058,900,6576,8782,14184,17878,23991,25995,3509,7662,11008,12539,17177,22206,28362,2129,6436,8889,14591,17472,23169,27420,386,6004,9415,15186,20150,21787,24585,2716,6576,9297,15061,18005,22810,25285,326,5511,10723,12538,19246,23428,25892,1422,6543,10129,12978,20113,23896,25560,657,7423,10656,15535,19787,22950,26103,3235,7335,8946,15528,17258,24302,26951,1483,7116,9353,12470,19520,24361,27708,2900,7423,9835,16033,18118,23835,26260,1101,7610,9378,13874,18979,20975,27521,3305,6205,9399,14183,20431,20609,25671,1881,4935,9604,14104,20018,23550,25532,1490,5773,10522,12462,16662,23603,25672,2380,7539,11514,14076,17791,21239,26389,2794,6953,9511,16306,19598,23006,28594,1278,5562,10753,14365,19498,21276,27132,602,5180,12095,14240,18993,22102,25854],"streaming":{"strategy":"sliding_center","win_frames":48,"hop_frames":40,"center_keep_frames":40,"left_ctx_frames":4,"right_ctx_frames":4,"xfade_ms_default":12,"pad_strategy":"edge_repeat"}}
|