v70: тире между слогами + onclick — playHistorySyl из IndexedDB
This commit is contained in:
Vendored
+21
-10
@@ -118,11 +118,12 @@ async function renderRecHistory() {
|
||||
r.transcription.split(/\s+/).map(w => {
|
||||
const sy = syllabifyIT(w);
|
||||
if (sy.includes('-')) {
|
||||
return sy.split('-').map(s =>
|
||||
return sy.split('-').map((s,si) =>
|
||||
'<span style="cursor:pointer;padding:0 2px;border-radius:3px"' +
|
||||
' onmouseover="this.style.background=\'#ffeb3b\'"' +
|
||||
' onmouseout="this.style.background=\'\'">' + s + '</span>'
|
||||
).join('<span style="color:#ccc">·</span>');
|
||||
' onmouseout="this.style.background=\'\'"' +
|
||||
' onclick="playHistorySyl(' + r.id + ',' + si + ',' + sy.split('-').length + ')">' + s + '</span>'
|
||||
).join('<span style="color:#ccc">-</span>');
|
||||
}
|
||||
return w;
|
||||
}).join(' ') +
|
||||
@@ -216,15 +217,12 @@ let _currentBlob = null;
|
||||
let _currentSylBuf = null;
|
||||
|
||||
async function playSyllable(sylIdx, total) {
|
||||
console.log('[SYL] click', sylIdx, '/', total, 'blob=', !!_currentBlob);
|
||||
if (!_currentBlob) return;
|
||||
try {
|
||||
const ctx = await getAudioCtx();
|
||||
console.log('[SYL] ctx.state=', ctx.state);
|
||||
if (!_currentSylBuf) {
|
||||
const ab = await _currentBlob.arrayBuffer();
|
||||
_currentSylBuf = await ctx.decodeAudioData(ab);
|
||||
console.log('[SYL] decoded', _currentSylBuf.duration.toFixed(1) + 's');
|
||||
}
|
||||
const dur = _currentSylBuf.duration;
|
||||
const start = (dur / total) * sylIdx;
|
||||
@@ -233,8 +231,21 @@ async function playSyllable(sylIdx, total) {
|
||||
src.buffer = _currentSylBuf;
|
||||
src.connect(ctx.destination);
|
||||
src.start(0, start, len);
|
||||
console.log('[SYL] playing', start.toFixed(2) + 's-' + (start+len).toFixed(2) + 's');
|
||||
} catch(e) { console.log('[SYL] ERR', e); }
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// Проигрывание слога из истории (загрузка blob из IndexedDB)
|
||||
async function playHistorySyl(recId, sylIdx, total) {
|
||||
try {
|
||||
const db = await openRecDB();
|
||||
const tx = db.transaction('recs', 'readonly');
|
||||
const store = tx.objectStore('recs');
|
||||
const rec = await new Promise(r => { const req = store.get(recId); req.onsuccess = () => r(req.result); });
|
||||
if (!rec?.blob) return;
|
||||
_currentBlob = rec.blob;
|
||||
_currentSylBuf = null;
|
||||
await playSyllable(sylIdx, total);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -659,7 +670,7 @@ async function doCompare(blob, originalText, duration) {
|
||||
if (i > 0) {
|
||||
const sep = document.createElement('span');
|
||||
sep.style.cssText = 'color:#ccc;margin:0 1px';
|
||||
sep.textContent = '·';
|
||||
sep.textContent = '-';
|
||||
div.appendChild(sep);
|
||||
}
|
||||
const chip = document.createElement('span');
|
||||
@@ -682,7 +693,7 @@ async function doCompare(blob, originalText, duration) {
|
||||
<script>
|
||||
// ---------- Глобальные переменные и инициализация ----------
|
||||
const GROQ_API_KEY = '';
|
||||
const VERSION = 'v69';
|
||||
const VERSION = 'v70';
|
||||
|
||||
let mediaRecorder, audioChunks = [], userAudioBlob = null, ttsText = '';
|
||||
let isRecording = false, isAnalyzing = false, micAnalyser = null, micAnimId = null;
|
||||
|
||||
Reference in New Issue
Block a user