v82: trimStartBlob через AudioContext+OfflineRenderer — обрезка 0.2с для Whisper
This commit is contained in:
+24
-9
@@ -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
@@ -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
@@ -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', {
|
||||
|
||||
Reference in New Issue
Block a user