import { pipeline } from '@huggingface/transformers'; // Global variables let transcriber = null; let audioData = null; let mediaRecorder = null; let audioChunks = []; let isModelLoading = true; // DOM Elements const audioInput = document.getElementById('audioInput'); const recordBtn = document.getElementById('recordBtn'); const stopBtn = document.getElementById('stopBtn'); const useTimestamps = document.getElementById('useTimestamps'); const useWordTimestamps = document.getElementById('useWordTimestamps'); const transcribeBtn = document.getElementById('transcribeBtn'); const audioPlayer = document.getElementById('audioPlayer'); const audioPlayerContainer = document.querySelector('.audio-player'); const resultDiv = document.getElementById('result'); const loadingSpinner = document.getElementById('loading'); // Load the model on startup async function loadModel() { try { loadingSpinner.hidden = false; transcriber = await pipeline( 'automatic-speech-recognition', 'Xenova/whisper-tiny.en' ); isModelLoading = false; loadingSpinner.hidden = true; transcribeBtn.disabled = false; console.log('Model loaded successfully'); } catch (error) { console.error('Failed to load model:', error); resultDiv.innerHTML = `

❌ Failed to load model. Check console for details.

`; loadingSpinner.hidden = true; } } // Handle file upload audioInput.addEventListener('change', (event) => { const file = event.target.files[0]; if (!file) return; const objectUrl = URL.createObjectURL(file); audioData = objectUrl; setAudioSource(objectUrl); }); // Setup recording recordBtn.addEventListener('click', async () => { audioChunks = []; try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); mediaRecorder.addEventListener('dataavailable', (event) => { audioChunks.push(event.data); }); mediaRecorder.addEventListener('stop', () => { const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); const audioUrl = URL.createObjectURL(audioBlob); audioData = audioUrl; setAudioSource(audioUrl); }); mediaRecorder.start(); recordBtn.disabled = true; stopBtn.disabled = false; } catch (err) { resultDiv.innerHTML = `

❌ Error accessing microphone: ${err.message}

`; } }); stopBtn.addEventListener('click', () => { mediaRecorder.stop(); recordBtn.disabled = false; stopBtn.disabled = true; // Stop all audio tracks mediaRecorder.stream.getTracks().forEach(track => track.stop()); }); // Toggle timestamp options useTimestamps.addEventListener('change', () => { useWordTimestamps.disabled = !useTimestamps.checked; }); // Set audio player source function setAudioSource(src) { audioPlayer.src = src; audioPlayerContainer.hidden = false; transcribeBtn.disabled = false; } // Transcribe audio transcribeBtn.addEventListener('click', async () => { if (!transcriber || isModelLoading || !audioData) return; resultDiv.innerHTML = ''; loadingSpinner.hidden = false; try { const options = {}; if (useTimestamps.checked) { options.return_timestamps = useWordTimestamps.checked ? 'word' : true; } const output = await transcriber(audioData, options); // Display result if (options.return_timestamps === 'word') { resultDiv.innerHTML = `

Transcription (Word-level timestamps):

Text: ${output.text}

Words:

`; } else if (options.return_timestamps === true) { resultDiv.innerHTML = `

Transcription (Segment-level timestamps):

Text: ${output.text}

Segments:

`; } else { resultDiv.innerHTML = `

Transcription:

${output.text}

`; } } catch (error) { resultDiv.innerHTML = `

❌ Transcription failed: ${error.message}

`; console.error(error); } finally { loadingSpinner.hidden = true; } }); // Preload example audio on page load window.addEventListener('DOMContentLoaded', () => { // Default example audio (optional, can be removed if only file/upload) const defaultAudioUrl = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav'; audioData = defaultAudioUrl; setAudioSource(defaultAudioUrl); loadModel(); // Start model loading when app starts });