Я пытаюсь записать звук с микрофона из клиентского веб-браузера, транслировать записанный звук в прямом эфире на сервер Node.js с помощью WebSocket, а затем снова передавать звук обратно на другой клиент веб-браузера.
Пока что на стороне клиента я открыл соединение WebSocket в JavaScript.
const webSocket = new WebSocket('ws://127.0.0.1:8080');
webSocket.binaryType = 'blob';
При подключении к серверу я захватываю аудиопоток с микрофона пользователя и на каждом доступном фрагменте данных, который доступен каждую 1 секунду, отправляю его через WebSocket на сервер.
webSocket.onopen = event => {
console.log('info: connected to server');
navigator.mediaDevices
.getUserMedia({ audio: true, video: false })
.then(stream => {
const mediaRecorder = new MediaRecorder(stream, {
mimeType: 'audio/webm',
});
mediaRecorder.addEventListener('dataavailable', event => {
if (event.data.size > 0) {
webSocket.send(event.data);
}
});
mediaRecorder.start(1000);
});
};
Теперь на стороне сервера, используя модуль ws
, я получаю каждый большой двоичный объект и отправляю его другому клиенту.
wss.on('connection', ws => {
console.log('info: client connected');
ws.on('message', message => {
wss.clients.forEach(client => {
if (client !== ws && client.readyState === webSocket.OPEN) {
client.send(message);
}
});
});
});
На стороне клиента я пытаюсь воспроизвести звук с помощью тега audio
со ссылкой audioEl
webSocket.onmessage = event => {
audioEl.src = window.URL.createObjectURL(event.data);
audioEl.play();
};
Теперь я понимаю, что это будет работать только для первого фрагмента данных (и это действительно работает), потому что audioEl.play();
является асинхронным. В этом случае я пытаюсь изменить URL-адрес большого двоичного объекта для элемента audio
каждую секунду, когда через WebSocket поступает новый большой двоичный объект.
После недельного исследования я нашел решения только в том, как транслировать звук с сервера на клиент, начать запись звука, остановить запись, а затем отправить весь фрагмент в виде капли.
Я также пытался отправить AudioBuffer
, но не знаю, как его обработать, чтобы воспроизвести звук.
const context = new AudioContext();
const source = context.createMediaStreamSource(stream);
const processor = context.createScriptProcessor(1024, 1, 1);
source.connect(processor);
processor.connect(context.destination);
processor.onaudioprocess = function(e) {
webSocket.send(e.inputBuffer);
}
Я пытаюсь добиться того, чтобы пользователь говорил в свой микрофон, а аудиопотоки в реальном времени передавались на сервер, а затем другому пользователю и воспроизводились одновременно.
Если мой подход к отправке капли каждую секунду верен, как я могу заставить код работать для непрерывного воспроизведения звука? Возможно, мне нужно создать какие-то буферы, о которых я не знаю. Или, если подход полностью неверен, подскажите, пожалуйста, правильный.
Использование технологии WebRTC для одноранговой связи для меня не вариант, потому что я не хочу накладных расходов на STUN или сервер TURN.