v63: кликабельные слоги — проигрывание сегментов аудио
This commit is contained in:
+48
-1
@@ -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) {
|
||||
'<span>� Артикуляция: ' + phon.voiceClarity + '%</span>' +
|
||||
'</div>';
|
||||
|
||||
// Слоги — кликабельные для прослушивания фрагментов
|
||||
_currentBlob = blob;
|
||||
_currentSylBuf = null;
|
||||
const sy = syllabifyIT(originalText);
|
||||
if (sy && sy.includes('-')) {
|
||||
const syls = sy.split('-');
|
||||
const sylHTML = '<div style="margin-top:8px;font-size:1.2em;letter-spacing:2px">' +
|
||||
syls.map((s, i) =>
|
||||
'<span class="syl-chip" data-syl="' + i + '" data-total="' + syls.length + '"' +
|
||||
' style="cursor:pointer;padding:2px 4px;border-radius:4px;transition:0.15s"' +
|
||||
' onmouseover="this.style.background=\'#e0e0ff\'"' +
|
||||
' onmouseout="this.style.background=\'\'"' +
|
||||
' onclick="playSyllable(' + i + ',' + syls.length + ')">' + s + '</span>'
|
||||
).join('<span style="color:#ccc">·</span>') +
|
||||
'</div>';
|
||||
document.getElementById('diff').innerHTML += sylHTML;
|
||||
}
|
||||
|
||||
setStatus('Готово.');
|
||||
isAnalyzing = false;
|
||||
return whisperResult.text || '';
|
||||
|
||||
Reference in New Issue
Block a user