You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.6 KiB

<!DOCTYPE html>
<html>
<head>
<title>Stream Web App</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial, sans-serif;
}
.streams {
display: flex;
justify-content: center;
background: #ddd;
}
.streams img {
margin: 50px;
outline: 1px solid #000;
}
.stats {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Stream Web App</h1>
<button onclick="connect()">Connect</button>
<input type="text" placeholder="Enter the WebSocket URL" />
<div class="streams">
<img class="stream-1" src="" alt="Original Stream">
<img class="stream-2" src="" alt="Masked Stream">
</div>
<div class="stats">
<h4>Messages received: <label class="message-count">0</label></h4>
<h4>FPS: <label class="fps">0</label></h4>
<h4>Total MB received: <label class="total-mb">0</label></h4>
</div>
<script>
let websocketUrl = 'ws://localhost:9001';
let ws;
const input = document.querySelector('input');
input.value = websocketUrl;
const messageCountElement = document.querySelector('.message-count');
const fpsElement = document.querySelector('.fps');
const totalMBElement = document.querySelector('.total-mb');
let frameTimestamps = [];
let lastFpsUpdateTime = 0;
let totalBytesReceived = 0;
const connect = () => {
websocketUrl = input.value;
console.log('Connecting to the server...', websocketUrl);
ws = new WebSocket(websocketUrl);
ws.onopen = () => {
console.log('Connected to the server');
};
ws.onmessage = (message) => {
messageCountElement.textContent = Number(messageCountElement.textContent) + 1;
handleMessage(message.data);
};
ws.onclose = () => {
console.log('Disconnected from the server');
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
};
const handleMessage = async (blob) => {
try {
const arrayBuffer = await blob.arrayBuffer();
const dataView = new DataView(arrayBuffer);
const type = dataView.getUint8(0);
const size = dataView.getUint32(1, true);
const imageData = arrayBuffer.slice(5, 5 + size);
const imageBlob = new Blob([imageData], { type: 'image/jpeg' });
const imageUrl = URL.createObjectURL(imageBlob);
const streamElement = document.querySelector(type === 0 ? '.stream-1' : '.stream-2');
streamElement.onload = () => {
URL.revokeObjectURL(streamElement.src); // Clean up the old object URL
};
streamElement.src = imageUrl;
// Update total MB received
totalBytesReceived += arrayBuffer.byteLength;
totalMBElement.textContent = (totalBytesReceived / (1024 * 1024)).toFixed(2);
updateFPS();
} catch (error) {
console.error('Error processing message:', error);
}
};
const updateFPS = () => {
const now = performance.now();
frameTimestamps.push(now);
// Keep only the last 30 frame timestamps
if (frameTimestamps.length > 30) {
frameTimestamps.shift();
}
// Update FPS
if (now - lastFpsUpdateTime > 100) {
const timeElapsed = (frameTimestamps[frameTimestamps.length - 1] - frameTimestamps[0]) / 1000; // in seconds
const fps = (frameTimestamps.length - 1) / timeElapsed;
fpsElement.textContent = fps.toFixed(2);
lastFpsUpdateTime = now;
}
};
</script>
</body>
</html>