Download audio_preprocessing.js from anmol-unitmole/streaming-speech-recognition-whisper-encoder-decoder: direct link, hf CLI and curl.
- Browser
- Download file 2.24 kB
-
https://huggingface.co/spaces/anmol-unitmole/streaming-speech-recognition-whisper-encoder-decoder/resolve/main/audio_preprocessing.js
- Command line
-
hf download hf://spaces/anmol-unitmole/streaming-speech-recognition-whisper-encoder-decoder/audio_preprocessing.js
-
curl -L -o audio_preprocessing.js https://huggingface.co/spaces/anmol-unitmole/streaming-speech-recognition-whisper-encoder-decoder/resolve/main/audio_preprocessing.js
2.24 kB
| export const TARGET_SAMPLE_RATE = 16000; | |
| export async function decodeAudioBlob(blob) { | |
| if (!(blob instanceof Blob)) throw new TypeError('Expected an audio Blob.'); | |
| const AudioContextClass = window.AudioContext || window.webkitAudioContext; | |
| if (!AudioContextClass) throw new Error('Web Audio API is not supported in this browser.'); | |
| const context = new AudioContextClass(); | |
| try { | |
| const buffer = await context.decodeAudioData(await blob.arrayBuffer()); | |
| const mono = mixToMono(buffer); | |
| const samples = resampleLinear(mono, buffer.sampleRate, TARGET_SAMPLE_RATE); | |
| return { samples, samplingRate: TARGET_SAMPLE_RATE, duration: samples.length / TARGET_SAMPLE_RATE, originalSamplingRate: buffer.sampleRate, channels: buffer.numberOfChannels }; | |
| } catch (error) { | |
| throw new Error(`The browser could not decode this audio file: ${error.message}`); | |
| } finally { | |
| await context.close(); | |
| } | |
| } | |
| export function mixToMono(audioBuffer) { | |
| const output = new Float32Array(audioBuffer.length); | |
| for (let channel = 0; channel < audioBuffer.numberOfChannels; channel += 1) { | |
| const data = audioBuffer.getChannelData(channel); | |
| for (let i = 0; i < data.length; i += 1) output[i] += data[i] / audioBuffer.numberOfChannels; | |
| } | |
| return output; | |
| } | |
| export function resampleLinear(samples, sourceRate, targetRate = TARGET_SAMPLE_RATE) { | |
| if (sourceRate === targetRate) return new Float32Array(samples); | |
| if (sourceRate <= 0 || targetRate <= 0) throw new Error('Sampling rates must be positive.'); | |
| const ratio = sourceRate / targetRate; | |
| const length = Math.max(1, Math.round(samples.length / ratio)); | |
| const output = new Float32Array(length); | |
| for (let i = 0; i < length; i += 1) { | |
| const position = i * ratio; | |
| const left = Math.floor(position); | |
| const right = Math.min(left + 1, samples.length - 1); | |
| const weight = position - left; | |
| output[i] = samples[left] * (1 - weight) + samples[right] * weight; | |
| } | |
| return output; | |
| } | |
| export function formatDuration(seconds) { | |
| const safe = Math.max(0, Number(seconds) || 0); | |
| const minutes = Math.floor(safe / 60); | |
| const remainder = Math.floor(safe % 60); | |
| return `${String(minutes).padStart(2, '0')}:${String(remainder).padStart(2, '0')}`; | |
| } | |