intiial
This commit is contained in:
129
templates/call.html
Normal file
129
templates/call.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
microOn = false;
|
||||
function changeMicro() {
|
||||
microOn = !microOn;
|
||||
const micOn = document.getElementById("micOn");
|
||||
const micOff = document.getElementById("micOff");
|
||||
if (microOn) {
|
||||
micOn.hidden = false;
|
||||
micOff.hidden = true;
|
||||
} else {
|
||||
micOn.hidden = true;
|
||||
micOff.hidden = false;
|
||||
}
|
||||
}
|
||||
async function getMicrophoneStream() {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: true,
|
||||
video: false
|
||||
});
|
||||
console.log("Microphone access granted, stream object:", stream);
|
||||
return stream;
|
||||
} catch (err) {
|
||||
console.error(`Error accessing microphone: ${err}`);
|
||||
// Handle cases where the user denies permission or no mic is available
|
||||
}
|
||||
}
|
||||
async function connect() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const callId = urlParams.get('call_id');
|
||||
const socket = new WebSocket("/connect?call_id=" + callId);
|
||||
socket.addEventListener("open", async () => {
|
||||
console.log("WebSocket открыт");
|
||||
|
||||
// Запрашиваем доступ к микрофону
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
|
||||
// Создаём AudioContext
|
||||
const audioContext = new AudioContext();
|
||||
|
||||
// Создаём источник из микрофона
|
||||
const source = audioContext.createMediaStreamSource(stream);
|
||||
|
||||
// ScriptProcessorNode является устаревшим, но всё ещё работает
|
||||
const processor = audioContext.createScriptProcessor(4096, 1, 1);
|
||||
|
||||
source.connect(processor);
|
||||
processor.connect(audioContext.destination); // необязательно, но нужно для запуска
|
||||
|
||||
processor.onaudioprocess = (audioEvent) => {
|
||||
const input = audioEvent.inputBuffer.getChannelData(0); // Float32Array
|
||||
|
||||
// Конвертируем в 16-bit PCM (часто требуется серверам)
|
||||
const pcm = floatTo16BitPCM(input);
|
||||
|
||||
// Отправляем через WebSocket
|
||||
if (socket.readyState === WebSocket.OPEN) {
|
||||
socket.send(pcm);
|
||||
}
|
||||
};
|
||||
});
|
||||
socket.binaryType = "arraybuffer";
|
||||
|
||||
socket.onmessage = (msg) => {
|
||||
const int16 = new Int16Array(msg.data);
|
||||
playPCM(int16);
|
||||
};
|
||||
|
||||
// Функция конвертации Float32 → Int16
|
||||
function floatTo16BitPCM(float32Array) {
|
||||
const buffer = new ArrayBuffer(float32Array.length * 2);
|
||||
const view = new DataView(buffer);
|
||||
|
||||
for (let i = 0; i < float32Array.length; i++) {
|
||||
let s = Math.max(-1, Math.min(1, float32Array[i]));
|
||||
view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const audioContext = new AudioContext();
|
||||
|
||||
// Очередь буферов, чтобы звук шел плавно
|
||||
const playQueue = [];
|
||||
|
||||
// Функция для воспроизведения PCM
|
||||
function playPCM(int16Array) {
|
||||
const float32 = new Float32Array(int16Array.length);
|
||||
|
||||
for (let i = 0; i < int16Array.length; i++) {
|
||||
float32[i] = int16Array[i] / 0x7fff;
|
||||
}
|
||||
|
||||
const audioBuffer = audioContext.createBuffer(1, float32.length, audioContext.sampleRate);
|
||||
audioBuffer.getChannelData(0).set(float32);
|
||||
|
||||
playQueue.push(audioBuffer);
|
||||
|
||||
if (playQueue.length === 1) {
|
||||
playNext();
|
||||
}
|
||||
}
|
||||
|
||||
function playNext() {
|
||||
if (playQueue.length === 0) return;
|
||||
|
||||
const buffer = playQueue[0];
|
||||
const source = audioContext.createBufferSource();
|
||||
source.buffer = buffer;
|
||||
source.connect(audioContext.destination);
|
||||
|
||||
source.onended = () => {
|
||||
playQueue.shift();
|
||||
playNext();
|
||||
};
|
||||
|
||||
source.start();
|
||||
}
|
||||
}
|
||||
connect();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="micOff">Micro is off</p> <p hidden id="micOn">Micro is on</p> <button onclick="changeMicro();">change</button>
|
||||
</body>
|
||||
</html>
|
||||
25
templates/index.html
Normal file
25
templates/index.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function startCall() {
|
||||
fetch("/call", {
|
||||
method: "POST",
|
||||
}).then(response => response.json()).then(
|
||||
(data) => {
|
||||
const element = document.getElementById("call");
|
||||
element.href = "/call?call_id=" + data.call_id;
|
||||
element.hidden = false;
|
||||
}
|
||||
)
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="startCall();">
|
||||
Start call
|
||||
</button>
|
||||
<a hidden id="call">
|
||||
Go to call
|
||||
</a>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user