frnsharp/FRNWebSocket/bin/Debug/net8.0/websocket.html
2024-11-22 16:55:57 +01:00

128 lines
4.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FRN Websocket</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #121212;
color: #ffffff;
}
.vu-meter {
width: 100%;
height: 20px;
background-color: #444;
position: relative;
}
.vu-meter-fill {
height: 100%;
background-color: #0f0;
width: 0%;
}
</style>
</head>
<body class="container py-5">
<h1 class="mb-4">FRN WebSocket</h1>
<button id="connectButton" class="btn btn-primary mb-3">Connect to Audio Stream</button>
<p id="status" class="mb-3">Status: Disconnected</p>
<div class="vu-meter mb-3">
<div id="vuMeterFill" class="vu-meter-fill"></div>
</div>
<script>
const connectButton = document.getElementById('connectButton');
const statusElement = document.getElementById('status');
const vuMeterFill = document.getElementById('vuMeterFill');
let audioContext;
let websocket;
let analyser;
let dataArray;
let isPlayingAudio = false;
connectButton.addEventListener('click', () => {
if (websocket && websocket.readyState === WebSocket.OPEN) {
websocket.close();
connectButton.textContent = 'Connect to Audio Stream';
statusElement.textContent = 'Status: Disconnected';
isPlayingAudio = false;
} else {
startWebSocketConnection();
}
});
function startWebSocketConnection() {
websocket = new WebSocket('ws://192.168.1.50/ws/');
websocket.binaryType = 'arraybuffer';
websocket.onopen = () => {
connectButton.textContent = 'Disconnect from Audio Stream';
statusElement.textContent = 'Status: Connected';
audioContext = new (window.AudioContext || window.webkitAudioContext)();
analyser = audioContext.createAnalyser();
analyser.fftSize = 256;
const bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
};
websocket.onmessage = (event) => {
playAudioChunk(event.data);
};
websocket.onclose = () => {
connectButton.textContent = 'Connect to Audio Stream';
statusElement.textContent = 'Status: Disconnected';
isPlayingAudio = false;
vuMeterFill.style.width = '0%';
};
websocket.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
function playAudioChunk(arrayBuffer) {
try {
const audioBuffer = audioContext.createBuffer(1, arrayBuffer.byteLength / 2, audioContext.sampleRate);
const audioData = new Float32Array(arrayBuffer.byteLength / 2);
const dataView = new DataView(arrayBuffer);
for (let i = 0; i < audioData.length; i++) {
audioData[i] = dataView.getInt16(i * 2, true) / 32768;
}
audioBuffer.copyToChannel(audioData, 0);
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(analyser);
analyser.connect(audioContext.destination);
source.start(0);
isPlayingAudio = true;
visualizeAudio();
source.onended = () => {
isPlayingAudio = false;
vuMeterFill.style.width = '0%';
};
} catch (error) {
console.error('Error processing audio data:', error);
}
}
function visualizeAudio() {
if (isPlayingAudio) {
analyser.getByteFrequencyData(dataArray);
let sum = 0;
for (let i = 0; i < dataArray.length; i++) {
sum += dataArray[i];
}
const average = sum / dataArray.length;
const percentage = (average / 256) * 100;
vuMeterFill.style.width = percentage + '%';
requestAnimationFrame(visualizeAudio);
}
}
</script>
</body>
</html>