document.addEventListener('DOMContentLoaded', () => { const startBtn = document.getElementById('start-mic-btn'); const stopBtn = document.getElementById('stop-mic-btn'); const clearBtn = document.getElementById('clear-btn'); const serviceSelect = document.getElementById('service-select'); const langSelect = document.getElementById('lang-select'); const deeplKeyInput = document.getElementById('deepl-key'); const deeplLabel = document.getElementById('deepl-label'); const englishOutput = document.getElementById('english-output'); const realtimeOutput = document.getElementById('realtime-output'); const detailedOutput = document.getElementById('detailed-output'); const statusLabel = document.getElementById('status-label'); let isRecording = false; let audioContext; let processor; let eventSource = null; let lastEnglishText = ""; // Tamamlanmış son İngilizce metin let lastRealtimeText = ""; // Tamamlanmış son çeviri metni // DeepL API key girişini göster/gizle serviceSelect.addEventListener('change', (e) => { if (e.target.value === 'DeepL') { deeplKeyInput.style.display = 'inline-block'; deeplLabel.style.display = 'inline-block'; } else { deeplKeyInput.style.display = 'none'; deeplLabel.style.display = 'none'; } }); // Ses verisini sunucuya gönderme function sendAudioToServer(data) { if (!isRecording) return; fetch('/upload_audio', { method: 'POST', body: data, headers: { 'Content-Type': 'application/octet-stream' } }).catch(error => console.error('Error sending audio:', error)); } // SSE bağlantısını başlat function startEventSource() { const params = new URLSearchParams({ target_lang: langSelect.value, service: serviceSelect.value, deepl_key: deeplKeyInput.value }); eventSource = new EventSource(`/stream_results?${params.toString()}`); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); const asrText = data.english; const asrType = data.type; const translation = data.translation; if (asrType === "partial") { // Anlık İngilizce ve çeviri metnini güncelle englishOutput.textContent = lastEnglishText + asrText; realtimeOutput.textContent = lastRealtimeText + translation; } else if (asrType === "final") { // Final cümle geldiğinde alt satıra geç ve metinleri sakla lastEnglishText += asrText + "\n"; lastRealtimeText += translation + "\n"; // Detaylı çeviriye ekle detailedOutput.textContent += asrText + " --> " + translation + "\n"; // Anlık çeviri kutusunu sıfırla englishOutput.textContent = lastEnglishText; realtimeOutput.textContent = lastRealtimeText; } englishOutput.scrollTop = englishOutput.scrollHeight; realtimeOutput.scrollTop = realtimeOutput.scrollHeight; detailedOutput.scrollTop = detailedOutput.scrollHeight; }; eventSource.onerror = (err) => { console.error("EventSource hatası:", err); statusLabel.textContent = "🔴 Hata: Bağlantı kesildi!"; statusLabel.style.color = "#ff453a"; if (eventSource) eventSource.close(); stopRecording(); }; } function stopEventSource() { if (eventSource) { eventSource.close(); eventSource = null; } } // Olay Dinleyicileri startBtn.addEventListener('click', async () => { if (isRecording) return; isRecording = true; startBtn.style.display = 'none'; stopBtn.style.display = 'block'; statusLabel.textContent = "🟢 Kaydediyor..."; statusLabel.style.color = "#30d158"; // Metin alanlarını temizle englishOutput.textContent = ""; realtimeOutput.textContent = ""; detailedOutput.textContent = ""; lastEnglishText = ""; lastRealtimeText = ""; try { const stream = await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: 16000 } }); audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: 16000 }); const source = audioContext.createMediaStreamSource(stream); const bufferSize = 4096; processor = audioContext.createScriptProcessor(bufferSize, 1, 1); source.connect(processor); processor.connect(audioContext.destination); processor.onaudioprocess = (e) => { if (!isRecording) return; const pcmData = e.inputBuffer.getChannelData(0); const pcm16 = new Int16Array(pcmData.length); for (let i = 0; i < pcmData.length; i++) { pcm16[i] = Math.max(-1, Math.min(1, pcmData[i])) * 0x7FFF; } sendAudioToServer(pcm16.buffer); }; await fetch('/start', { method: 'POST' }); startEventSource(); } catch (err) { console.error('Mikrofon erişimi reddedildi veya hata oluştu:', err); statusLabel.textContent = "🔴 Hata: Mikrofon erişimi reddedildi!"; statusLabel.style.color = "#ff453a"; isRecording = false; startBtn.style.display = 'block'; stopBtn.style.display = 'none'; } }); stopBtn.addEventListener('click', () => { stopRecording(); }); function stopRecording() { if (!isRecording) return; isRecording = false; if (audioContext) { audioContext.close(); audioContext = null; } startBtn.style.display = 'block'; stopBtn.style.display = 'none'; statusLabel.textContent = "🔴 Hazır - 'Başlat' butonuna basın"; statusLabel.style.color = "#30d158"; stopEventSource(); fetch('/stop', { method: 'POST' }); } clearBtn.addEventListener('click', () => { englishOutput.textContent = ""; realtimeOutput.textContent = ""; detailedOutput.textContent = ""; lastEnglishText = ""; lastRealtimeText = ""; statusLabel.textContent = "🟢 Tüm veriler temizlendi."; }); });