| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Whisper AI Transcription</title> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| :root { |
| --primary: #6e48aa; |
| --primary-dark: #4a2d8a; |
| --secondary: #9d50bb; |
| --gradient-start: #4776e6; |
| --gradient-end: #8e54e9; |
| --light: #f8f9fa; |
| --dark: #2d3748; |
| --gray: #edf2f7; |
| --success: #48bb78; |
| --danger: #e53e3e; |
| --warning: #ed8936; |
| } |
| |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| } |
| |
| body { |
| background-color: #f0f4f8; |
| color: var(--dark); |
| line-height: 1.6; |
| } |
| |
| .container { |
| max-width: 1000px; |
| margin: 2rem auto; |
| padding: 0 1rem; |
| } |
| |
| header { |
| text-align: center; |
| margin-bottom: 2rem; |
| } |
| |
| .logo { |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| gap: 0.5rem; |
| margin-bottom: 1rem; |
| } |
| |
| .logo i { |
| font-size: 2.5rem; |
| color: var(--primary); |
| } |
| |
| h1 { |
| font-size: 2.5rem; |
| background: linear-gradient(to right, var(--gradient-start), var(--gradient-end)); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| font-weight: 700; |
| margin-bottom: 0.5rem; |
| } |
| |
| .subtitle { |
| color: #718096; |
| font-size: 1.1rem; |
| max-width: 600px; |
| margin: 0 auto; |
| } |
| |
| .card { |
| background: white; |
| border-radius: 12px; |
| box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); |
| padding: 2rem; |
| margin-bottom: 2rem; |
| } |
| |
| .card-title { |
| font-size: 1.4rem; |
| margin-bottom: 1.5rem; |
| color: var(--primary-dark); |
| display: flex; |
| align-items: center; |
| gap: 0.8rem; |
| } |
| |
| .card-title i { |
| font-size: 1.8rem; |
| color: var(--secondary); |
| } |
| |
| .controls { |
| display: flex; |
| flex-direction: column; |
| gap: 1.5rem; |
| } |
| |
| .input-group { |
| display: flex; |
| gap: 1rem; |
| } |
| |
| @media (max-width: 768px) { |
| .input-group { |
| flex-direction: column; |
| } |
| } |
| |
| .btn { |
| padding: 0.8rem 1.5rem; |
| border-radius: 8px; |
| border: none; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| gap: 0.5rem; |
| font-size: 1rem; |
| } |
| |
| .btn-primary { |
| background-color: var(--primary); |
| color: white; |
| } |
| |
| .btn-primary:hover { |
| background-color: var(--primary-dark); |
| transform: translateY(-2px); |
| box-shadow: 0 4px 12px rgba(110, 72, 170, 0.3); |
| } |
| |
| .btn-outline { |
| background-color: transparent; |
| border: 2px solid var(--primary); |
| color: var(--primary); |
| } |
| |
| .btn-outline:hover { |
| background-color: var(--primary); |
| color: white; |
| } |
| |
| .btn-danger { |
| background-color: var(--danger); |
| color: white; |
| } |
| |
| .btn-danger:hover { |
| background-color: #c53030; |
| transform: translateY(-2px); |
| box-shadow: 0 4px 12px rgba(229, 62, 62, 0.3); |
| } |
| |
| .btn:disabled { |
| opacity: 0.7; |
| cursor: not-allowed; |
| transform: none !important; |
| box-shadow: none !important; |
| } |
| |
| .file-upload { |
| display: none; |
| } |
| |
| .audio-visualizer { |
| width: 100%; |
| height: 100px; |
| background-color: #f5f3ff; |
| border-radius: 8px; |
| margin: 1rem 0; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| .visualizer-bars { |
| display: flex; |
| align-items: flex-end; |
| justify-content: space-around; |
| height: 100%; |
| width: 100%; |
| padding: 0.5rem; |
| } |
| |
| .bar { |
| background-color: var(--primary); |
| width: 6px; |
| border-radius: 3px; |
| transition: height 0.1s ease; |
| } |
| |
| .recording-indicator { |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| color: var(--danger); |
| font-weight: 600; |
| margin-bottom: 1rem; |
| } |
| |
| .pulse { |
| width: 12px; |
| height: 12px; |
| border-radius: 50%; |
| background-color: var(--danger); |
| animation: pulse 1.5s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { |
| transform: scale(0.95); |
| box-shadow: 0 0 0 0 rgba(229, 62, 62, 0.7); |
| } |
| 70% { |
| transform: scale(1); |
| box-shadow: 0 0 0 10px rgba(229, 62, 62, 0); |
| } |
| 100% { |
| transform: scale(0.95); |
| box-shadow: 0 0 0 0 rgba(229, 62, 62, 0); |
| } |
| } |
| |
| .timer { |
| font-family: 'Courier New', monospace; |
| font-size: 1.2rem; |
| } |
| |
| .transcription-card { |
| position: relative; |
| } |
| |
| .transcription-content { |
| min-height: 200px; |
| max-height: 400px; |
| overflow-y: auto; |
| padding: 1rem; |
| background-color: var(--gray); |
| border-radius: 8px; |
| white-space: pre-wrap; |
| line-height: 1.8; |
| font-size: 1.1rem; |
| } |
| |
| .copy-btn { |
| position: absolute; |
| top: 1rem; |
| right: 1rem; |
| background-color: rgba(255, 255, 255, 0.8); |
| border-radius: 6px; |
| padding: 0.5rem; |
| cursor: pointer; |
| transition: all 0.2s ease; |
| } |
| |
| .copy-btn:hover { |
| background-color: white; |
| transform: scale(1.05); |
| } |
| |
| .copy-btn i { |
| color: var(--primary); |
| font-size: 1.2rem; |
| } |
| |
| .language-selector { |
| display: flex; |
| flex-direction: column; |
| gap: 0.5rem; |
| } |
| |
| select { |
| padding: 0.8rem; |
| border-radius: 8px; |
| border: 1px solid #cbd5e0; |
| background-color: white; |
| font-size: 1rem; |
| color: var(--dark); |
| cursor: pointer; |
| } |
| |
| select:focus { |
| outline: none; |
| border-color: var(--primary); |
| box-shadow: 0 0 0 3px rgba(110, 72, 170, 0.2); |
| } |
| |
| .file-info { |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| margin-top: 0.5rem; |
| color: #4a5568; |
| } |
| |
| .file-info i { |
| color: var(--primary); |
| } |
| |
| .status-message { |
| padding: 1rem; |
| border-radius: 8px; |
| margin-bottom: 1rem; |
| display: flex; |
| align-items: center; |
| gap: 0.8rem; |
| } |
| |
| .status-processing { |
| background-color: #feebc8; |
| color: #b7791f; |
| } |
| |
| .status-success { |
| background-color: #c6f6d5; |
| color: #25855a; |
| } |
| |
| .status-error { |
| background-color: #fed7d7; |
| color: #c53030; |
| } |
| |
| .progress-container { |
| width: 100%; |
| height: 8px; |
| background-color: #e2e8f0; |
| border-radius: 4px; |
| margin-top: 1rem; |
| overflow: hidden; |
| } |
| |
| .progress-bar { |
| height: 100%; |
| background: linear-gradient(to right, var(--gradient-start), var(--gradient-end)); |
| border-radius: 4px; |
| width: 0%; |
| transition: width 0.3s ease; |
| } |
| |
| .settings-toggle { |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| color: #4a5568; |
| cursor: pointer; |
| margin-bottom: 1rem; |
| } |
| |
| .settings-toggle i { |
| transition: transform 0.3s ease; |
| } |
| |
| .settings-container { |
| max-height: 0; |
| overflow: hidden; |
| transition: max-height 0.3s ease; |
| background-color: #f8f9fa; |
| border-radius: 8px; |
| margin-bottom: 1rem; |
| } |
| |
| .settings-container.open { |
| max-height: 300px; |
| padding: 1rem; |
| margin-bottom: 1rem; |
| } |
| |
| .setting-item { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 1rem; |
| } |
| |
| .checkbox-container { |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| } |
| |
| input[type="checkbox"] { |
| -webkit-appearance: none; |
| appearance: none; |
| width: 20px; |
| height: 20px; |
| border: 2px solid #cbd5e0; |
| border-radius: 4px; |
| cursor: pointer; |
| position: relative; |
| transition: all 0.2s ease; |
| } |
| |
| input[type="checkbox"]:checked { |
| background-color: var(--primary); |
| border-color: var(--primary); |
| } |
| |
| input[type="checkbox"]:checked::after { |
| content: '\f00c'; |
| font-family: 'Font Awesome 6 Free'; |
| font-weight: 900; |
| position: absolute; |
| top: 50%; |
| left: 50%; |
| transform: translate(-50%, -50%); |
| color: white; |
| font-size: 12px; |
| } |
| |
| .history-item { |
| padding: 1rem; |
| border-bottom: 1px solid #e2e8f0; |
| cursor: pointer; |
| transition: background-color 0.2s ease; |
| } |
| |
| .history-item:hover { |
| background-color: #f7fafc; |
| } |
| |
| .history-item-time { |
| font-size: 0.9rem; |
| color: #718096; |
| } |
| |
| .history-item-preview { |
| display: -webkit-box; |
| -webkit-line-clamp: 2; |
| -webkit-box-orient: vertical; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| margin-top: 0.3rem; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <header> |
| <div class="logo"> |
| <i class="fas fa-comment-dots"></i> |
| <h1>Whisper AI</h1> |
| </div> |
| <p class="subtitle">Advanced speech recognition powered by OpenAI's Whisper model. Convert speech to text with remarkable accuracy.</p> |
| </header> |
|
|
| <div class="card"> |
| <h2 class="card-title"> |
| <i class="fas fa-microphone"></i> |
| Audio Input |
| </h2> |
| |
| <div class="controls"> |
| <div class="input-group"> |
| <button id="recordBtn" class="btn btn-primary"> |
| <i class="fas fa-microphone"></i> Start Recording |
| </button> |
| <button id="uploadBtn" class="btn btn-outline"> |
| <i class="fas fa-upload"></i> Upload Audio |
| </button> |
| <input type="file" id="fileInput" class="file-upload" accept="audio/*,video/*,.wav,.mp3,.ogg,.m4a,.mp4,.webm"> |
| </div> |
|
|
| <div class="language-selector"> |
| <label for="language">Select Language</label> |
| <select id="language"> |
| <option value="auto">Auto-detect</option> |
| <option value="en">English</option> |
| <option value="es">Spanish</option> |
| <option value="fr">French</option> |
| <option value="de">German</option> |
| <option value="it">Italian</option> |
| <option value="pt">Portuguese</option> |
| <option value="ru">Russian</option> |
| <option value="ja">Japanese</option> |
| <option value="zh">Chinese</option> |
| <option value="hi">Hindi</option> |
| <option value="ar">Arabic</option> |
| </select> |
| </div> |
|
|
| <div class="audio-visualizer" id="visualizer"> |
| <div class="visualizer-bars" id="visualizerBars"></div> |
| </div> |
|
|
| <div id="recordingUI" style="display: none;"> |
| <div class="recording-indicator"> |
| <div class="pulse"></div> |
| <span>Recording</span> |
| <span class="timer" id="timer">00:00</span> |
| </div> |
| <button id="stopBtn" class="btn btn-danger"> |
| <i class="fas fa-stop"></i> Stop & Process |
| </button> |
| </div> |
|
|
| <div id="fileInfo" style="display: none;"> |
| <div class="file-info"> |
| <i class="fas fa-file-audio"></i> |
| <span id="fileName"></span> |
| </div> |
| <button id="processFileBtn" class="btn btn-primary"> |
| <i class="fas fa-cog"></i> Process File |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="settings-toggle" id="settingsToggle"> |
| <i class="fas fa-cog"></i> |
| <span>Advanced Settings</span> |
| </div> |
|
|
| <div class="settings-container" id="settingsContainer"> |
| <div class="setting-item"> |
| <span>Transcription Task</span> |
| <select id="taskType"> |
| <option value="transcribe">Transcribe (default)</option> |
| <option value="translate">Translate to English</option> |
| </select> |
| </div> |
| <div class="setting-item"> |
| <span>Temperature</span> |
| <input type="range" id="temperature" min="0" max="1" step="0.1" value="0"> |
| <span id="temperatureValue">0</span> |
| </div> |
| <div class="checkbox-container"> |
| <input type="checkbox" id="timestamps" checked> |
| <label for="timestamps">Include timestamps</label> |
| </div> |
| <div class="checkbox-container"> |
| <input type="checkbox" id="diarization"> |
| <label for="diarization">Speaker diarization (beta)</label> |
| </div> |
| </div> |
|
|
| <div class="card transcription-card"> |
| <h2 class="card-title"> |
| <i class="fas fa-keyboard"></i> |
| Transcription |
| </h2> |
| |
| <div id="statusMessage" style="display: none;"></div> |
| |
| <div class="progress-container" id="progressContainer" style="display: none;"> |
| <div class="progress-bar" id="progressBar"></div> |
| </div> |
| |
| <div class="transcription-content" id="transcriptionResult"> |
| <div style="text-align: center; padding: 4rem 0; color: #a0aec0;"> |
| <i class="fas fa-comment-slash" style="font-size: 3rem; margin-bottom: 1rem;"></i> |
| <h3>No transcription yet</h3> |
| <p>Record audio or upload a file to get started</p> |
| </div> |
| </div> |
| |
| <div class="copy-btn" id="copyBtn" title="Copy to clipboard" style="display: none;"> |
| <i class="fas fa-copy"></i> |
| </div> |
| </div> |
|
|
| <div class="card"> |
| <h2 class="card-title"> |
| <i class="fas fa-history"></i> |
| Recent Transcripts |
| </h2> |
| |
| <div id="historyList"> |
| <div class="history-item"> |
| <div class="history-item-time">5 minutes ago</div> |
| <div class="history-item-preview">Lorem ipsum dolor sit amet, consectetur adipiscing elit...</div> |
| </div> |
| <div class="history-item"> |
| <div class="history-item-time">2 hours ago</div> |
| <div class="history-item-preview">Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const recordBtn = document.getElementById('recordBtn'); |
| const stopBtn = document.getElementById('stopBtn'); |
| const uploadBtn = document.getElementById('uploadBtn'); |
| const fileInput = document.getElementById('fileInput'); |
| const processFileBtn = document.getElementById('processFileBtn'); |
| const fileName = document.getElementById('fileName'); |
| const fileInfo = document.getElementById('fileInfo'); |
| const recordingUI = document.getElementById('recordingUI'); |
| const timer = document.getElementById('timer'); |
| const visualizer = document.getElementById('visualizer'); |
| const visualizerBars = document.getElementById('visualizerBars'); |
| const transcriptionResult = document.getElementById('transcriptionResult'); |
| const statusMessage = document.getElementById('statusMessage'); |
| const progressContainer = document.getElementById('progressContainer'); |
| const progressBar = document.getElementById('progressBar'); |
| const copyBtn = document.getElementById('copyBtn'); |
| const settingsToggle = document.getElementById('settingsToggle'); |
| const settingsContainer = document.getElementById('settingsContainer'); |
| const temperature = document.getElementById('temperature'); |
| const temperatureValue = document.getElementById('temperatureValue'); |
| |
| |
| let mediaRecorder; |
| let audioChunks = []; |
| let audioContext; |
| let analyser; |
| let timerInterval; |
| let seconds = 0; |
| let isRecording = false; |
| |
| |
| for (let i = 0; i < 40; i++) { |
| const bar = document.createElement('div'); |
| bar.className = 'bar'; |
| bar.style.height = '0%'; |
| visualizerBars.appendChild(bar); |
| } |
| const bars = document.querySelectorAll('.bar'); |
| |
| |
| recordBtn.addEventListener('click', startRecording); |
| stopBtn.addEventListener('click', stopRecording); |
| uploadBtn.addEventListener('click', () => fileInput.click()); |
| fileInput.addEventListener('change', handleFileUpload); |
| processFileBtn.addEventListener('click', processUploadedFile); |
| copyBtn.addEventListener('click', copyTranscription); |
| settingsToggle.addEventListener('click', toggleSettings); |
| temperature.addEventListener('input', updateTemperatureValue); |
| |
| |
| updateTemperatureValue(); |
| |
| async function startRecording() { |
| try { |
| |
| recordBtn.style.display = 'none'; |
| recordingUI.style.display = 'block'; |
| |
| |
| seconds = 0; |
| updateTimer(); |
| timerInterval = setInterval(updateTimer, 1000); |
| |
| |
| const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
| mediaRecorder = new MediaRecorder(stream); |
| isRecording = true; |
| |
| |
| audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
| const source = audioContext.createMediaStreamSource(stream); |
| analyser = audioContext.createAnalyser(); |
| analyser.fftSize = 64; |
| source.connect(analyser); |
| |
| |
| visualize(); |
| |
| |
| mediaRecorder.ondataavailable = event => { |
| audioChunks.push(event.data); |
| }; |
| |
| mediaRecorder.onstop = async () => { |
| clearInterval(timerInterval); |
| |
| |
| const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); |
| audioChunks = []; |
| |
| |
| await processAudio(audioBlob, 'recording.wav'); |
| }; |
| |
| mediaRecorder.start(100); |
| |
| |
| showStatus('Processing your recording...', 'processing'); |
| |
| } catch (error) { |
| console.error('Error accessing microphone:', error); |
| stopRecording(); |
| showStatus('Error accessing microphone. Please check permissions.', 'error'); |
| recordBtn.style.display = 'block'; |
| recordingUI.style.display = 'none'; |
| } |
| } |
| |
| function stopRecording() { |
| if (mediaRecorder && isRecording) { |
| mediaRecorder.stop(); |
| isRecording = false; |
| |
| |
| mediaRecorder.stream.getTracks().forEach(track => track.stop()); |
| |
| |
| cancelAnimationFrame(visualize); |
| |
| clearInterval(timerInterval); |
| } |
| } |
| |
| function updateTimer() { |
| seconds++; |
| const minutes = Math.floor(seconds / 60); |
| const remainingSeconds = seconds % 60; |
| timer.textContent = `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; |
| } |
| |
| function visualize() { |
| if (!isRecording) return; |
| |
| const bufferLength = analyser.frequencyBinCount; |
| const dataArray = new Uint8Array(bufferLength); |
| analyser.getByteFrequencyData(dataArray); |
| |
| for (let i = 0; i < bars.length; i++) { |
| const barHeight = (dataArray[i % bufferLength] / 255) * 100; |
| bars[i].style.height = `${barHeight}%`; |
| } |
| |
| requestAnimationFrame(visualize); |
| } |
| |
| function handleFileUpload(event) { |
| const file = event.target.files[0]; |
| if (file) { |
| fileName.textContent = file.name; |
| fileInfo.style.display = 'block'; |
| |
| |
| fileInput.value = ''; |
| } else { |
| fileInfo.style.display = 'none'; |
| } |
| } |
| |
| async function processUploadedFile() { |
| const file = fileInput.files[0]; |
| if (!file) return; |
| |
| showStatus('Processing uploaded file...', 'processing'); |
| progressContainer.style.display = 'block'; |
| |
| |
| simulateProcessing(() => { |
| processAudio(file, file.name); |
| }); |
| } |
| |
| async function processAudio(audioBlob, fileName) { |
| try { |
| |
| |
| |
| |
| progressBar.style.width = '40%'; |
| |
| |
| await new Promise(resolve => setTimeout(resolve, 1500)); |
| |
| progressBar.style.width = '70%'; |
| |
| |
| setTimeout(() => { |
| const mockResults = getMockTranscription(fileName); |
| displayResults(mockResults); |
| showStatus('Transcription completed successfully!', 'success'); |
| }, 1000); |
| |
| } catch (error) { |
| console.error('Error processing audio:', error); |
| showStatus('Error processing audio. Please try again.', 'error'); |
| } finally { |
| |
| recordBtn.style.display = 'block'; |
| recordingUI.style.display = 'none'; |
| fileInfo.style.display = 'none'; |
| progressBar.style.width = '100%'; |
| } |
| } |
| |
| function displayResults(results) { |
| transcriptionResult.innerHTML = results; |
| |
| |
| const isEmpty = results.includes('No transcription yet'); |
| copyBtn.style.display = isEmpty ? 'none' : 'block'; |
| } |
| |
| function showStatus(message, type) { |
| statusMessage.style.display = 'block'; |
| statusMessage.textContent = message; |
| statusMessage.className = 'status-message'; |
| |
| switch (type) { |
| case 'processing': |
| statusMessage.classList.add('status-processing'); |
| progressContainer.style.display = 'block'; |
| progressBar.style.width = '10%'; |
| break; |
| case 'success': |
| statusMessage.classList.add('status-success'); |
| progressContainer.style.display = 'none'; |
| break; |
| case 'error': |
| statusMessage.classList.add('status-error'); |
| progressContainer.style.display = 'none'; |
| break; |
| } |
| } |
| |
| function copyTranscription() { |
| const text = transcriptionResult.innerText; |
| navigator.clipboard.writeText(text).then(() => { |
| |
| const originalIcon = copyBtn.innerHTML; |
| copyBtn.innerHTML = '<i class="fas fa-check"></i>'; |
| |
| setTimeout(() => { |
| copyBtn.innerHTML = originalIcon; |
| }, 2000); |
| }).catch(err => { |
| console.error('Failed to copy text: ', err); |
| }); |
| } |
| |
| function toggleSettings() { |
| settingsContainer.classList.toggle('open'); |
| const icon = settingsToggle.querySelector('i'); |
| icon.style.transform = settingsContainer.classList.contains('open') ? 'rotate(90deg)' : 'rotate(0)'; |
| } |
| |
| function updateTemperatureValue() { |
| temperatureValue.textContent = temperature.value; |
| } |
| |
| function simulateProcessing(callback) { |
| let progress = 0; |
| const interval = setInterval(() => { |
| progress += Math.random() * 10; |
| if (progress >= 90) { |
| progress = 90; |
| clearInterval(interval); |
| callback(); |
| } |
| progressBar.style.width = `${progress}%`; |
| }, 300); |
| } |
| |
| function getMockTranscription(filename) { |
| const now = new Date(); |
| const languages = ['English', 'Spanish', 'French', 'German']; |
| const randomLanguage = languages[Math.floor(Math.random() * languages.length)]; |
| |
| return `Filename: ${filename}\n` + |
| `Detected language: ${randomLanguage}\n` + |
| `Transcribed at: ${now.toLocaleString()}\n\n` + |
| `[00:00:00 --> 00:00:03] Hello there! This is a mock transcription from the Whisper speech recognition model.\n` + |
| `[00:00:03 --> 00:00:07] It demonstrates what the real output would look like when using the actual Whisper API.\n` + |
| `[00:00:07 --> 00:00:12] In a real implementation, this text would come from OpenAI's Whisper model processing your audio.\n` + |
| `[00:00:12 --> 00:00:15] Whisper is great for transcribing meetings, lectures, interviews, and more.\n` + |
| `[00:00:15 --> 00:00:18] Thank you for trying out this demo interface!\n`; |
| } |
| }); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body> |
| </html> |