From 89e875404bc8275a931c350b9031323dfdaccb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Fri, 22 May 2026 21:37:10 +0400 Subject: [PATCH] =?UTF-8?q?v76:=20=D0=BF=D1=80=D0=BE=D0=B8=D0=B3=D1=80?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20trimSilence=20=E2=80=94=20=D0=B1=D0=B5=D0=B7=20=D1=89?= =?UTF-8?q?=D0=B5=D0=BB=D1=87=D0=BA=D0=B0=20=D0=B2=20=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B0=D0=BB=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/audio.js | 31 +++++++++++++++++++++---------- js/main.js | 15 ++++----------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/js/audio.js b/js/audio.js index 8e2fe89..6afc3a5 100644 --- a/js/audio.js +++ b/js/audio.js @@ -90,22 +90,33 @@ function stopRecording() { if (mediaRecorder && mediaRecorder.state === 'recording') mediaRecorder.stop(); } -// ---------- Воспроизведение ---------- +// ---------- Воспроизведение (с обрезкой тишины) ---------- +async function playTrimmed(blob) { + const t = await trimSilence(blob); + const ctx = getAudioCtx(); + let buf; + if (t) { + const offline = new OfflineAudioContext(1, t.data.length, t.sr); + buf = offline.createBuffer(1, t.data.length, t.sr); + buf.getChannelData(0).set(t.data); + } else { + const ab = await blob.arrayBuffer(); + buf = await ctx.decodeAudioData(ab); + } + const src = ctx.createBufferSource(); + src.buffer = buf; + src.connect(ctx.destination); + src.start(); + return new Promise(resolve => { src.onended = resolve; }); +} + async function playRec(id) { 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(id); req.onsuccess = () => r(req.result); }); - if (rec?.blob) { - const url = URL.createObjectURL(rec.blob); - const audio = new Audio(url); - await new Promise((resolve, reject) => { - audio.onended = () => { URL.revokeObjectURL(url); resolve(); }; - audio.onerror = () => { URL.revokeObjectURL(url); reject(); }; - audio.play(); - }); - } + if (rec?.blob) await playTrimmed(rec.blob); } catch(e) { /* тихо */ } } diff --git a/js/main.js b/js/main.js index 2b88e21..1f9815e 100644 --- a/js/main.js +++ b/js/main.js @@ -1,6 +1,6 @@ // ---------- Глобальные переменные и инициализация ---------- const GROQ_API_KEY = ''; -const VERSION = 'v75'; +const VERSION = 'v76'; let mediaRecorder, audioChunks = [], userAudioBlob = null, ttsText = ''; let isRecording = false, isAnalyzing = false, micAnalyser = null, micAnimId = null; @@ -41,19 +41,12 @@ document.getElementById('btnRecord').onclick = async function () { // ---------- Воспроизведение своей записи ---------- document.getElementById('btnPlayUser').onclick = async () => { if (!userAudioBlob) return setStatus('Нет записи!'); - if (userAudioBlob.size === 0) return setStatus('Запись пустая!'); - const url = URL.createObjectURL(userAudioBlob); - const audio = new Audio(url); - audio.volume = 1.0; - audio.onended = () => { URL.revokeObjectURL(url); setStatus('Готово.'); }; - audio.onerror = () => { URL.revokeObjectURL(url); setStatus('Ошибка воспроизведения.'); }; setStatus('🔊 Ваша запись...'); try { - await audio.play(); + await playTrimmed(userAudioBlob); + setStatus('Готово.'); } catch (err) { - URL.revokeObjectURL(url); - setStatus('Ошибка воспроизведения — нажмите ещё раз.'); - return; + setStatus('Ошибка воспроизведения.'); } };