thai_indextts2 / test_head.html
williampike's picture
Upload folder using huggingface_hub
4d3248c verified
Raw
History Blame Contribute Delete
3.4 kB
<script>
(function () {
'use strict';
var ctx = null;
var nextTime = 0;
var segNum = 0;
var lastSig = '';
function log(msg) {
console.log('[StreamPlayer]', msg);
var el = document.getElementById('dbg-log');
if (el) {
el.textContent = '[' + new Date().toLocaleTimeString() + '] ' + msg + '
' + el.textContent;
}
}
function getCtx() {
if (!ctx || ctx.state === 'closed') {
ctx = new AudioContext({ sampleRate: 22050 });
nextTime = 0;
segNum = 0;
log('AudioContext created, state=' + ctx.state);
}
if (ctx.state === 'suspended') {
ctx.resume().then(function() { log('AudioContext resumed'); }).catch(function(e) { log('resume error: ' + e); });
}
return ctx;
}
function playChunk(rawPath) {
segNum++;
var seg = segNum;
var url = '/gradio_api/file=' + rawPath.replace(/\\/g, '/').replace(/\/g, '/');
log('seg ' + seg + ' | fetching: ' + url);
var c = getCtx();
if (c.state === 'suspended') c.resume().catch(function(){});
fetch(url)
.then(function(r) {
log('seg ' + seg + ' | HTTP ' + r.status);
if (!r.ok) throw new Error('HTTP ' + r.status + ' for ' + url);
return r.arrayBuffer();
})
.then(function(buf) {
if (buf.byteLength === 0) throw new Error('Received 0 bytes');
log('seg ' + seg + ' | arrayBuffer ' + buf.byteLength + ' bytes, decoding...');
return getCtx().decodeAudioData(buf);
})
.then(function(decoded) {
var ac = getCtx();
var src = ac.createBufferSource();
src.buffer = decoded;
src.connect(ac.destination);
var now = ac.currentTime;
var at = (nextTime > now + 0.05) ? nextTime : (now + 0.05);
src.start(at);
nextTime = at + decoded.duration;
log('seg ' + seg + ' | ' + decoded.duration.toFixed(2) + 's | start@' + at.toFixed(3) + ' end@' + nextTime.toFixed(3));
})
.catch(function(e) {
log('ERROR seg ' + seg + ': ' + e.message);
console.error('[StreamPlayer]', e);
});
}
function checkSignal() {
var sig = document.getElementById('sph-sig');
if (!sig) return;
var val = sig.getAttribute('data-v') || '';
if (val === lastSig) return;
lastSig = val;
log('signal received: ' + val);
if (!val || val === '__idle__') return;
if (val === '__reset__') {
if (ctx && ctx.state !== 'closed') ctx.close().catch(function(){});
ctx = null; nextTime = 0; segNum = 0;
log('player reset');
} else if (val === '__done__') {
log('all chunks sent!');
} else {
playChunk(val);
}
}
document.addEventListener('click', function() {
if (ctx && ctx.state === 'suspended') ctx.resume().catch(function(){});
}, true);
setInterval(checkSignal, 50);
log('StreamPlayer JS loaded, polling every 50ms');
})();
</script>