diff --git a/index.html b/index.html index 4497c31..b8f5b4b 100644 --- a/index.html +++ b/index.html @@ -53,9 +53,38 @@ let mediaRecorder, audioChunks = [], userAudioBlob = null, ttsText = ''; let isRecording = false, isAnalyzing = false, micAnalyser = null, micAnimId = null; let recordStartTime = 0, recordDuration = 0; // ---------- Версия ---------- -const VERSION = 'v62'; +const VERSION = 'v63'; document.getElementById('ver').textContent = VERSION; +// ---------- AudioContext для проигрывания слогов ---------- +let _audioCtx = null; +function getAudioCtx() { + if (!_audioCtx) _audioCtx = new (window.AudioContext || window.webkitAudioContext)(); + if (_audioCtx.state === 'suspended') _audioCtx.resume(); + return _audioCtx; +} + +let _currentBlob = null; // blob для проигрывания слогов +let _currentSylBuf = null; // декодированный AudioBuffer + +async function playSyllable(sylIdx, total) { + if (!_currentBlob) return; + const ctx = getAudioCtx(); + try { + if (!_currentSylBuf) { + const ab = await _currentBlob.arrayBuffer(); + _currentSylBuf = await ctx.decodeAudioData(ab); + } + const dur = _currentSylBuf.duration; + const start = (dur / total) * sylIdx; + const len = dur / total; + const src = ctx.createBufferSource(); + src.buffer = _currentSylBuf; + src.connect(ctx.destination); + src.start(0, start, len); + } catch(e) { console.log('playSyllable ERR', e); } +} + // ---------- Перевод на русский (Groq) ---------- async function translateToRussian(text) { if (!GROQ_API_KEY) return; @@ -266,6 +295,24 @@ async function doCompare(blob, originalText, duration) { '� Артикуляция: ' + phon.voiceClarity + '%' + ''; + // Слоги — кликабельные для прослушивания фрагментов + _currentBlob = blob; + _currentSylBuf = null; + const sy = syllabifyIT(originalText); + if (sy && sy.includes('-')) { + const syls = sy.split('-'); + const sylHTML = '
' + + syls.map((s, i) => + '' + s + '' + ).join('·') + + '
'; + document.getElementById('diff').innerHTML += sylHTML; + } + setStatus('Готово.'); isAnalyzing = false; return whisperResult.text || '';