8.3 KiB
8.3 KiB
直播间下播清空在线人数功能说明
实现时间: 2024-12-29
功能: 主播下播时自动清空在线人数并通知观众
状态: ✅ 已完成
📋 功能概述
当主播关闭直播时,系统会自动执行以下操作:
- ✅ 通知所有观众 - 通过WebSocket发送"主播已下播"消息
- ✅ 清空内存数据 - 清空房间的所有WebSocket连接
- ✅ 重置数据库 - 将数据库中的
online_count字段设置为0 - ✅ 防止数据残留 - 确保下次开播时在线人数从0开始
🔧 实现细节
1. 数据库字段更新
在LiveRoomServiceImpl.setLiveStatus()方法中,当直播关闭时:
// 如果直播关闭,将数据库中的在线人数设置为0
if (!isLive) {
uw.set(LiveRoom::getOnlineCount, 0);
}
SQL执行效果:
UPDATE eb_live_room
SET is_live = 0,
started_at = NULL,
online_count = 0 -- 重置在线人数
WHERE stream_key = ?
2. WebSocket通知观众
在LiveRoomOnlineServiceImpl.clearRoomAndNotify()方法中:
// 创建直播结束通知消息
Map<String, Object> liveEndedMsg = new HashMap<>();
liveEndedMsg.put("type", "live_ended");
liveEndedMsg.put("roomId", roomId);
liveEndedMsg.put("message", "主播已下播");
liveEndedMsg.put("onlineCount", 0);
liveEndedMsg.put("timestamp", System.currentTimeMillis());
前端收到的消息格式:
{
"type": "live_ended",
"roomId": "123",
"message": "主播已下播",
"onlineCount": 0,
"timestamp": 1703836800000
}
3. 清空内存数据
系统会清空以下内存数据:
roomConnections- 房间的所有WebSocket连接roomUserCounts- 房间的在线人数计数器sessionRoomMap- Session到房间的反向映射
🔄 执行流程
主播点击下播
↓
SRS回调 /srs/on_unpublish
↓
LiveRoomService.setLiveStatus(streamKey, false)
↓
1. 更新数据库:is_live=0, online_count=0
↓
2. 获取房间ID
↓
3. 调用 LiveRoomOnlineService.clearRoomAndNotify(roomId, "主播已下播")
↓
4. 发送WebSocket消息给所有观众
↓
5. 关闭所有WebSocket连接
↓
6. 清空内存中的房间数据
↓
完成
📡 前端接收处理
WebSocket消息监听
前端需要监听live_ended类型的消息:
websocket.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.type === 'live_ended') {
// 显示提示
showToast(data.message); // "主播已下播"
// 更新UI
updateOnlineCount(0);
// 关闭直播播放器
stopPlayer();
// 可选:跳转到其他页面
// navigateToLiveList();
}
};
Android端处理示例
when (message.type) {
"live_ended" -> {
// 显示Toast提示
Toast.makeText(context, message.message, Toast.LENGTH_LONG).show()
// 更新在线人数为0
binding.tvOnlineCount.text = "0"
// 停止播放
player.stop()
// 可选:返回直播列表
finish()
}
}
🧪 测试步骤
1. 准备测试环境
# 启动后端服务
cd Zhibo/zhibo-h
mvn spring-boot:run
# 启动SRS服务器
cd live-streaming
./objs/srs -c conf/srs.conf
2. 测试流程
-
创建直播间
POST /api/front/live/room/create { "title": "测试直播", "streamerName": "测试主播", "categoryId": 1 } -
开始推流
- 使用OBS推流到:
rtmp://localhost:1935/live/{streamKey} - 观察数据库:
is_live=1
- 使用OBS推流到:
-
观众加入
- 打开多个浏览器/客户端
- 连接WebSocket:
ws://localhost:8080/ws/live/{roomId}?clientId=user_1 - 观察在线人数增加
-
停止推流
- 在OBS中停止推流
- 观察以下变化:
预期结果:
✅ 数据库变化:
-- 查询直播间状态
SELECT id, is_live, online_count FROM eb_live_room WHERE id = ?;
-- 结果:is_live=0, online_count=0
✅ 前端收到消息:
{
"type": "live_ended",
"roomId": "123",
"message": "主播已下播",
"onlineCount": 0,
"timestamp": 1703836800000
}
✅ WebSocket连接关闭:
- 所有观众的WebSocket连接被服务器主动关闭
- 前端显示"主播已下播"提示
✅ 内存数据清空:
// 查询在线人数(应该返回0)
GET /api/live/online/count/{roomId}
// 返回:{"code":200,"data":0}
3. 验证下次开播
-
再次推流
- 使用相同的streamKey推流
- 观察在线人数从0开始
-
观众重新加入
- 观众重新连接WebSocket
- 在线人数从1开始递增
📊 数据库表结构
eb_live_room 表
| 字段 | 类型 | 说明 | 下播时的值 |
|---|---|---|---|
| id | INT | 主键 | 不变 |
| is_live | TINYINT | 是否直播中 | 0 |
| online_count | INT | 在线人数 | 0 ← 重置 |
| started_at | DATETIME | 开始时间 | NULL |
| stream_key | VARCHAR | 推流密钥 | 不变 |
🔍 日志输出
正常流程日志
[INFO] 直播间关闭,清空房间 123 的在线人数并通知观众
[INFO] 清空房间 123 的所有在线用户,当前人数: 5
[INFO] 已通知客户端 session-001 直播结束: 主播已下播
[INFO] 已通知客户端 session-002 直播结束: 主播已下播
[INFO] 已通知客户端 session-003 直播结束: 主播已下播
[INFO] 已通知客户端 session-004 直播结束: 主播已下播
[INFO] 已通知客户端 session-005 直播结束: 主播已下播
[INFO] 房间 123 已清空,所有用户已断开连接
异常情况日志
[WARN] Invalid roomId, cannot clear room
[ERROR] 发送直播结束通知失败: session-001
[ERROR] 关闭session失败: session-002
[ERROR] 清空房间失败: roomId=123
⚠️ 注意事项
1. 消息发送延迟
为确保消息发送完成,代码中添加了500ms延迟:
// 等待消息发送完成
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
2. 并发安全
使用ConcurrentHashMap和synchronized确保线程安全:
synchronized (session) {
session.sendMessage(new TextMessage(endMessage));
}
3. 异常处理
所有操作都包含异常处理,确保部分失败不影响整体流程:
try {
// 发送消息
} catch (Exception e) {
log.error("发送直播结束通知失败", e);
// 继续处理其他客户端
}
🚀 扩展功能建议
1. 自定义下播消息
可以在创建直播间时设置自定义下播消息:
// LiveRoom实体类添加字段
@Column(name = "end_message")
private String endMessage; // "感谢观看,下次再见!"
// 下播时使用自定义消息
String message = room.getEndMessage() != null
? room.getEndMessage()
: "主播已下播";
2. 下播统计
记录每次直播的统计数据:
// 创建直播统计表
CREATE TABLE eb_live_statistics (
id INT PRIMARY KEY AUTO_INCREMENT,
room_id INT,
start_time DATETIME,
end_time DATETIME,
max_online_count INT, -- 最高在线人数
total_viewers INT, -- 总观看人数
duration INT -- 直播时长(秒)
);
3. 推送通知
给关注主播的用户发送推送通知:
// 下播时通知关注者
notificationService.sendToFollowers(
streamerId,
"您关注的主播已下播",
"感谢观看,下次再见!"
);
📝 相关文件
修改的文件
LiveRoomService.java- 添加getRoomIdByStreamKey()方法LiveRoomServiceImpl.java- 实现下播时重置在线人数LiveRoomOnlineService.java- 添加clearRoomAndNotify()方法LiveRoomOnlineServiceImpl.java- 实现清空房间并通知功能
涉及的表
eb_live_room- 直播间表(更新online_count字段)
✅ 功能检查清单
- 数据库在线人数重置为0
- WebSocket通知所有观众
- 清空内存中的连接数据
- 关闭所有WebSocket连接
- 日志记录完整
- 异常处理完善
- 并发安全保证
- 下次开播人数从0开始
实现完成时间: 2024-12-29
开发者: Kiro AI Assistant
状态: ✅ 生产就绪