基于Swoole实现视频弹幕功能(实战小练习)
这篇练习记录是基于Swoole实现一个视频弹幕功能。此篇文章涵盖3个文件,一个是后端WebSocket服务器文件,一个是前端静态页面文件,另一个是js弹幕文件。
前端页面
文件:websocket.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="./canvasBarrage.js"></script>
<title>基于Swoole实现视频弹幕功能</title>
<style>
.container {
width: 700px;
margin: 0 auto;
}
.canvas-barrage {
position: absolute;
width: 700px;
height: 500px;
pointer-events: none;
z-index: 1;
}
.box {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.barrage-msg {
width: 700px;
height: 20px;
line-height: 20px;
border: 1px solid gray;
border-radius: 5px;
padding: 6px 2px;
}
.barrage-btn {
display: inline-block;
background: pink;
line-height: 20px;
border-radius: 5px;
color: rgb(146, 46, 46);
font-size: 16px;
border: none;
}
</style>
</head>
<body>
<div class="container">
<canvas id="canvasBarrage" class="canvas-barrage"></canvas>
<video src="./test.mp4" width="700" height="500" id="video" controls></video>
<div class="box">
<input type="text" class="barrage-msg" id="msg" name="value" value="" required>
<input type="button" class="barrage-btn" id="sendBtn" value="发送弹幕">
</div>
</div>
<script>
// 弹幕数据
let barrageData = [{}];
// 获取元素对象
let canvasEle = document.getElementById('canvasBarrage');
let videoEle = document.getElementById('video');
// 实例化弹幕
const barrage = new CanvasBarrage(canvasEle, videoEle, {
data:barrageData
});
// 实例化WebSocket对象
const ws = new WebSocket('ws://192.168.172.130:9506');
// 连接
ws.onopen = function (event) {
if (ws.readyState == 1) {
console.log('WebSocket 连接成功...');
} else {
console.log('WebSocket 连接失败...');
}
};
// 接收消息
ws.onmessage = function (evt) {
barrage.add({
value: evt.data,
time: videoEle.currentTime,
speed: 5
});
}
ws.onerror = function (evt) {
console.log('WebSocket 连接失败...');
};
ws.onclose = function() {
console.log('WebSocket 连接关闭...');
};
let msg;
let sendBtn = document.getElementById('sendBtn');
// 发送弹幕
sendBtn.onclick = function(){
if (ws.readyState == 1) {
msg = document.getElementById('msg').value;
ws.send(msg);
} else {
alert('WebSocket 连接失败');
}
};
</script>
</body>
</html>
弹幕js文件
文件:canvasBarrage.js
关于此文件,请到这个链接中获取
后端处理
文件:WebSocket.php
<?php
/**
*WebSocket服务器
**/
class WebSockerServ
{
private $serv;
public function __construct()
{
$this->serv = new Swoole\WebSocket\Server("192.168.172.130", 9506);
$this->serv->set([
'worker_num' => 2, //开启2个worker进程
'max_request' => 4, //每个worker进程 max_request设置为4次
'task_worker_num' => 4, //开启4个task进程
'dispatch_mode' => 4, //数据包分发策略 - IP分配
'daemonize' => false, //守护进程(true/false)
]);
$this->serv->on('Start', [$this, 'onStart']);
$this->serv->on('Open', [$this, 'onOpen']);
$this->serv->on("Message", [$this, 'onMessage']);
$this->serv->on("Close", [$this, 'onClose']);
$this->serv->on("Task", [$this, 'onTask']);
$this->serv->on("Finish", [$this, 'onFinish']);
$this->serv->start();
}
// 启动进程
public function onStart($serv)
{
echo "onStart SWOOLE ".SWOOLE_VERSION . " 服务已启动".PHP_EOL;
}
// 连接
public function onOpen($serv, $request) {
echo "onOpen...客户端..." . $request->fd . ' 连接成功...'.PHP_EOL;
// 投递异步任务
$serv->task([
'type' => 'login'
]);
}
// 异步任务
public function onTask($serv, $task_id, $from_id, $data) {
echo "#### onTask ####".PHP_EOL;
echo "#{$serv->worker_id} onTask: [PID={$serv->worker_pid}]: task_id={$task_id}".PHP_EOL;
$msg = '';
switch ($data['type']) {
case 'login':
$msg = '自如初...';
break;
case 'speak':
$msg = $data['msg'];
break;
}
// 推送消息给客户端
foreach ($serv->connections as $fd) {
$connectionInfo = $serv->connection_info($fd);
if ($connectionInfo['websocket_status'] == 3) {
$serv->push($fd, $msg);
}
}
// 任务完成
$serv->finish($data);
}
public function onFinish($serv, $task_id, $data)
{
echo 'onFinished task ' . $task_id . '已完成' . PHP_EOL;
}
// 接收消息
public function onMessage($serv, $frame)
{
$serv->task(['type' => 'speak', 'msg' => $frame->data]);
}
public function onClose($serv, $fd)
{
echo 'onClosed...' . $fd . '连接关闭' . PHP_EOL;
}
}
$server = new WebSockerServ();
至此,弹幕完成
2021-04-27
请登录后再评论