const timeInput = document.getElementById('time-input'); const startBtn = document.getElementById('start-btn'); const videoElement = document.getElementById('video'); const statusElement = document.getElementById('status'); const stressLevelElement = document.getElementById('stress-level'); const countdownElement = document.getElementById('countdown'); const showResultBtn = document.getElementById('show-result-btn'); let stream; let interval; let countdownInterval; let totalTime; let frameCount = 0; let countdownTime; let sessionId = Date.now().toString(); async function startCamera() { try { stream = await navigator.mediaDevices.getUserMedia({ video: true, }); videoElement.srcObject = stream; } catch (err) { console.error("Error accessing the camera", err); statusElement.textContent = "Gagal mengakses kamera."; } } function stopCamera() { if (stream) { let tracks = stream.getTracks(); tracks.forEach(track => track.stop()); videoElement.srcObject = null; } } async function sendFrameToBackend(dataUrl) { try { console.log("Preparing to send frame to backend..."); const formData = new FormData(); formData.append('image', dataUrl); formData.append('sessionId', sessionId); console.log("Sending request to backend..."); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const apiResponse = await fetch('https://PatriciaWening-emoapi.hf.space/api/deteksi-emosi', { method: 'POST', body: formData, signal: controller.signal }); clearTimeout(timeoutId); if (!apiResponse.ok) { const errorText = await apiResponse.text(); console.error(`Server returned error ${apiResponse.status}: ${errorText}`); throw new Error(`HTTP error! Status: ${apiResponse.status}`); } const data = await apiResponse.json(); console.log("API response:", data); if (data.faceDetected) { drawFaceRectangle(data.faceRegion); updateStressLevel(data.stressLevel, data.emotion); statusElement.textContent = `Emosi terdeteksi: ${data.emotion}, Tingkat stres: ${data.stressLevel}%`; } else { statusElement.textContent = data.error || "Wajah tidak terdeteksi, mohon cek posisi kamera."; } } catch (error) { console.error('Error sending frame to backend:', error); statusElement.textContent = "Kesalahan saat memproses data: " + error.message; } } function drawFaceRectangle(region) { const canvas = document.createElement('canvas'); canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; const context = canvas.getContext('2d'); context.drawImage(videoElement, 0, 0, canvas.width, canvas.height); context.strokeStyle = '#00FF00'; context.lineWidth = 3; context.strokeRect(region.x, region.y, region.width, region.height); const dataURL = canvas.toDataURL('image/png'); const tempImg = document.createElement('img'); tempImg.src = dataURL; tempImg.style.width = '100%'; tempImg.style.height = 'auto'; tempImg.style.border = '2px solid #ccc'; tempImg.style.borderRadius = '8px'; const videoParent = videoElement.parentNode; videoParent.insertBefore(tempImg, videoElement); videoElement.style.display = 'none'; setTimeout(() => { tempImg.remove(); videoElement.style.display = 'block'; }, 200); } function updateStressLevel(stressLevel, emotion) { stressLevelElement.textContent = `Tingkat Stres: ${stressLevel} (${emotion})`; if (stressLevel >= 80) { stressLevelElement.classList.remove('text-green-600', 'text-yellow-600'); stressLevelElement.classList.add('text-red-600'); } else if (stressLevel >= 50) { stressLevelElement.classList.remove('text-green-600', 'text-red-600'); stressLevelElement.classList.add('text-yellow-600'); } else { stressLevelElement.classList.remove('text-yellow-600', 'text-red-600'); stressLevelElement.classList.add('text-green-600'); } localStorage.setItem('currentSessionId', sessionId); } async function captureAndAnalyze() { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; context.drawImage(videoElement, 0, 0, canvas.width, canvas.height); const frame = canvas.toDataURL('image/jpeg'); sendFrameToBackend(frame); frameCount++; } function updateCountdown() { const minutes = Math.floor(countdownTime / 60); const seconds = countdownTime % 60; countdownElement.textContent = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; countdownTime--; if (countdownTime < 0) { clearInterval(countdownInterval); } } function startDetection() { totalTime = parseInt(timeInput.value) * 1000; if (isNaN(totalTime) || totalTime <= 0) { statusElement.textContent = "Waktu input tidak valid."; return; } countdownTime = totalTime / 1000; countdownInterval = setInterval(updateCountdown, 1000); statusElement.textContent = `Kamera aktif selama ${totalTime / 1000} detik.`; startCamera(); interval = setInterval(captureAndAnalyze, 1000); setTimeout(() => { clearInterval(interval); stopCamera(); statusElement.textContent = "Proses selesai!"; showResultBtn.classList.remove('hidden'); }, totalTime); } startBtn.addEventListener('click', startDetection);