我们以php的swoole搭建一个websocket服务器
<?php
$server = new Swoole\WebSocket\Server("0.0.0.0", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server->set([
'daemonize' => false,
'ssl_cert_file' => "/data/cert/6284283_web.debug.only.bfw.wiki.pem",
'ssl_key_file' => "/data/cert/6284283_web.debug.only.bfw.wiki.key",
]);
$server->on('open', function($server, $req) {
echo "connection open: {$req->fd}\n";
});
$server->on('message', function($server, $frame) {
//echo "received message: {$frame->data}\n";
// 确保我们处理的是二进制数据
//if ($frame->opcode == WEBSOCKET_OPCODE_BINARY) {
// 广播音频数据到所有其他连接的客户端
// foreach($server->connections as $fd) {
// if($fd != $frame->fd) {
// $server->push($fd, $frame->data, WEBSOCKET_OPCODE_BINARY);
// }
// }
// }
$server->push($frame->fd, $frame->data,WEBSOCKET_OPCODE_BINARY);
});
$server->on('close', function($server, $fd) {
echo "connection close: {$fd}\n";
});
$server->start();html代码如下:<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>实时语音通话</title>
</head>
<body>
<button id="startBtn">开始通话</button>
<button id="stopBtn">结束通话</button>
<script>
let ws;
let mediaStream;
let audioContext;
let mediaStreamSource;
let processor;
document.getElementById('startBtn').onclick = startCall;
document.getElementById('stopBtn').onclick = stopCall;
function startCall() {
ws = new WebSocket('wss://web.debug.only.bfw.wiki:9502');
ws.binaryType = 'arraybuffer'; // 设置WebSocket以接收二进制数据
ws.onmessage = function(event) {
// 处理接收到的音频数据
playAudio(event.data);
};
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
mediaStream = stream;
audioContext = new AudioContext();
mediaStreamSource = audioContext.createMediaStreamSource(stream);
processor = audioContext.createScriptProcessor(1024, 1, 1);
mediaStreamSource.connect(processor);
processor.connect(audioContext.destination);
processor.onaudioprocess = function(e) {
// 发送音频数据到服务器
if (ws.readyState === WebSocket.OPEN) {
// 将音频数据转换为二进制格式
const audioData = e.inputBuffer.getChannelData(0);
const buffer = new Float32Array(audioData);
ws.send(buffer);
}
};
})
.catch(err => console.error('Error accessing microphone:', err));
}
function stopCall() {
if (ws) ws.close();
if (mediaStream) mediaStream.getTracks().forEach(track => track.stop());
if (processor) processor.disconnect();
if (mediaStreamSource) mediaStreamSource.disconnect();
if (audioContext) audioContext.close();
}
let audioQueue = [];
let isPlaying = false;
function playAudio(Audio) {
audioQueue.push(Audio);
if (!isPlaying) {
playNextInQueue();
}
}
function playNextInQueue() {
console.log(audioQueue.length)
if (audioQueue.length === 0) {
isPlaying = false;
return;
}
const audioData = audioQueue.shift();
try {
// 实现音频播放逻辑
// 这里需要将接收到的音频数据(ArrayBuffer)解码并播放
const audioBuffer = audioContext.createBuffer(1, audioData.byteLength / 4, audioContext.sampleRate);
audioBuffer.getChannelData(0).set(new Float32Array(audioData));
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start();
} catch (error) {
console.error('播放音频时发生错误:', error);
playNextInQueue(); // 如果当前音频播放失败,继续播放队列中的下一个
}
}
</script>
</body>
</html>如果出现声音卡顿,可降低声音采样率为单声道24k 网友回复


