+ + +

Waiting for Video Stream

@@ -481,7 +484,8 @@ return; } - const wsUrl = `ws://${window.location.hostname}:{{ server_port }}/ws/admin/${sessionId}`; + const wsProto = window.location.protocol === 'https:' ? 'wss' : 'ws'; + const wsUrl = `${wsProto}://${window.location.hostname}:{{ server_port }}/ws/admin/${sessionId}`; try { ws = new WebSocket(wsUrl); @@ -497,10 +501,17 @@ ws.onmessage = function(event) { try { - const data = JSON.parse(event.data); - handleWebSocketMessage(data); + // Проверяем, это бинарные данные (видеокадр) или текст (JSON) + if (event.data instanceof Blob) { + // Это видеокадр - отображаем на canvas + handleVideoFrame(event.data); + } else if (typeof event.data === 'string') { + // Это текстовое сообщение JSON + const data = JSON.parse(event.data); + handleWebSocketMessage(data); + } } catch (error) { - console.error('Error parsing WebSocket message:', error); + console.error('Error processing WebSocket message:', error); } }; @@ -659,6 +670,39 @@ } } + // Handle video frame from admin WebSocket + function handleVideoFrame(blob) { + const canvas = document.getElementById('videoCanvas'); + const placeholder = document.getElementById('videoPlaceholder'); + + // Show canvas, hide placeholder + if (canvas.style.display === 'none') { + canvas.style.display = 'block'; + placeholder.style.display = 'none'; + } + + // Create image from blob and draw on canvas + const img = new Image(); + img.onload = function() { + const ctx = canvas.getContext('2d'); + // Set canvas size to match image + canvas.width = img.width; + canvas.height = img.height; + // Draw image + ctx.drawImage(img, 0, 0); + // Revoke the object URL to free memory + URL.revokeObjectURL(img.src); + }; + + img.onerror = function() { + console.error('Failed to load image from blob'); + URL.revokeObjectURL(img.src); + }; + + // Create object URL from blob and load as image + img.src = URL.createObjectURL(blob); + } + // Initialize sliders function initializeSliders() { // Quality slider