v82: trimStartBlob через AudioContext+OfflineRenderer — обрезка 0.2с для Whisper

This commit is contained in:
“Naeel”
2026-05-23 06:26:07 +04:00
parent 6b62ec8dd5
commit dababcf466
4 changed files with 60 additions and 24 deletions
+24 -9
View File
@@ -321,13 +321,28 @@ function encodeWAV(samples, sampleRate) {
// Обрезает первые cutSec секунд, возвращает WAV Blob (для Groq)
async function trimStartBlob(blob, cutSec = 0.2) {
const ctx = new OfflineAudioContext(1, 1, 44100);
const ab = await blob.arrayBuffer();
const buf = await ctx.decodeAudioData(ab);
const sr = buf.sampleRate;
const data = buf.getChannelData(0);
const cutSamples = Math.floor(sr * cutSec);
const trimmed = data.slice(cutSamples);
const wav = encodeWAV(trimmed, sr);
return new Blob([wav], { type: 'audio/wav' });
try {
const ab = await blob.arrayBuffer();
const actx = new AudioContext();
const rawBuf = await actx.decodeAudioData(ab);
const sr = rawBuf.sampleRate;
const cutSamples = Math.floor(sr * cutSec);
const newLen = rawBuf.length - cutSamples;
if (newLen < sr * 0.05) { actx.close(); return blob; }
// Render trimmed via OfflineAudioContext (надёжнее ручного slice)
const offline = new OfflineAudioContext(1, newLen, sr);
const src = offline.createBufferSource();
src.buffer = rawBuf;
src.connect(offline.destination);
src.start(0, cutSec / sr);
const rendered = await offline.startRendering();
actx.close();
const wav = encodeWAV(rendered.getChannelData(0), sr);
return new Blob([wav], { type: 'audio/wav' });
} catch(e) {
console.log('[trimStartBlob] fallback to raw:', e);
return blob;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
// ---------- Глобальные переменные и инициализация ----------
const GROQ_API_KEY = '';
const VERSION = 'v81';
const VERSION = 'v82';
let mediaRecorder, audioChunks = [], userAudioBlob = null, ttsText = '';
let isRecording = false, isAnalyzing = false, micAnalyser = null, micAnimId = null;
+5 -2
View File
@@ -4,12 +4,15 @@ async function transcribe(blob) {
if (!GROQ_API_KEY) return { text: '', error: 'no_key' };
const tStart = performance.now();
// Обрезаем 0.2с в начале (щелчок)
const sendBlob = await trimStartBlob(blob);
const form = new FormData();
form.append('file', blob, 'audio.webm');
form.append('file', sendBlob, sendBlob.type === 'audio/wav' ? 'audio.wav' : 'audio.webm');
form.append('model', 'whisper-large-v3');
form.append('language', 'it');
console.log('[HTTP] blob ' + (blob.size/1024).toFixed(1) + 'KB → multipart POST');
console.log('[HTTP] blob ' + (sendBlob.size/1024).toFixed(1) + 'KB → multipart POST');
try {
const r = await fetch('https://lang.kube5s.ru/openai/v1/audio/transcriptions', {