视频网站弹幕系统简易实现

要实现的是 "历史弹幕 + 实时弹幕" 混合的完整弹幕系统,类似 B 站的做法。

我们来一步步设计并实现它👇


✅ 场景目标

你的视频播放器要支持:

功能 说明
🎞 历史弹幕 视频开始播放时加载过去用户发送的弹幕,按时间同步展示
🧑‍💻 实时弹幕 当前用户或其他用户正在发的弹幕,立即出现在屏幕上

🧠 核心设计理念

🔁 整体流程图

复制代码
                   ┌────────────┐
     ┌────────────▶│ WebSocket  │◀────────────┐
     │             │ 服务器广播 │              │
     │             └─────▲──────┘              │
     │                   │                     │
     ▼             ┌─────┴──────┐              ▼
 [观看者A]        [Spring Boot 后端]       [观看者B]
    │  GET 弹幕历史    ▲        │       GET 弹幕历史 │
    │                 数据库     │                   │
    ▼                            ▼                   ▼
同步播放历史弹幕         接收实时弹幕          接收实时弹幕

🧱 技术实现拆解

🔸 后端

✅ 数据模型(MySQL)
sql 复制代码
CREATE TABLE danmu (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  video_id BIGINT NOT NULL,
  text VARCHAR(255) NOT NULL,
  time_in_video DOUBLE NOT NULL,  -- 出现的时间(秒)
  send_time DATETIME NOT NULL
);
✅ 接口 1:获取历史弹幕
java 复制代码
@GetMapping("/api/danmu/history")
public List<DanmuDto> getHistory(@RequestParam Long videoId) {
    return danmuRepository.findByVideoIdOrderByTimeInVideo(videoId);
}
✅ 接口 2:WebSocket 实时弹幕服务
java 复制代码
@ServerEndpoint("/ws/danmu/{videoId}")
@Component
public class DanmuWebSocket {

    private static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("videoId") String videoId) {
        sessionMap.put(session.getId(), session);
    }

    @OnMessage
    public void onMessage(String msgJson, Session session, @PathParam("videoId") String videoId) {
        // 解析 JSON 为 Danmu 对象
        Danmu danmu = new Gson().fromJson(msgJson, Danmu.class);
        danmu.setSendTime(LocalDateTime.now());

        // 保存弹幕到数据库
        danmuService.save(danmu);

        // 广播给所有客户端
        sessionMap.values().forEach(s -> {
            try {
                s.getBasicRemote().sendText(msgJson);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    @OnClose
    public void onClose(Session session) {
        sessionMap.remove(session.getId());
    }
}

🔸 前端(HTML + JS)

✅ 加载历史弹幕并同步播放
js 复制代码
let historyDanmus = []; // { time: 3.5, text: "弹幕内容" }

fetch("/api/danmu/history?videoId=101")
  .then(res => res.json())
  .then(data => {
    historyDanmus = data.sort((a, b) => a.time - b.time);
  });

setInterval(() => {
  const currentTime = video.currentTime;
  while (historyDanmus.length && historyDanmus[0].time <= currentTime) {
    showDanmu(historyDanmus.shift().text);
  }
}, 200);
✅ 实时弹幕连接
js 复制代码
const socket = new WebSocket("ws://localhost:8080/ws/danmu/101");

socket.onmessage = (event) => {
  const danmu = JSON.parse(event.data);
  showDanmu(danmu.text);
};

function sendDanmu(text) {
  const time = video.currentTime;
  socket.send(JSON.stringify({ videoId: 101, text, time }));
}

🔸 弹幕展示动画(CSS + JS)

js 复制代码
function showDanmu(text) {
  const el = document.createElement("div");
  el.className = "danmu";
  el.innerText = text;
  el.style.top = Math.random() * 80 + "%";
  el.style.color = randomColor();
  document.getElementById("danmu-area").appendChild(el);
  setTimeout(() => el.remove(), 8000);
}

✅ 总结:逻辑分工

功能 负责方 技术
视频播放进度监听 前端 video.currentTime
加载历史弹幕 后端接口 GET /api/danmu/history
弹幕显示同步播放 前端 JS + 定时器 每 200ms 检查一次
实时弹幕收发 WebSocket 后端广播 + 前端展示
数据存储 MySQL timeInVideo + text

✅ 用户视角体验流程

  1. 打开视频页面
  2. 请求并同步播放历史弹幕
  3. 用户点击发送 → 发到 WebSocket
  4. 后端广播 + 存库
  5. 所有在线用户立即看到

相关推荐
colicode1 小时前
语音消息接口应用开发:如何通过API发送个性化音频或TTS语音内容
音视频
程可爱1 小时前
springboot整合mybatis和postgresql
spring boot·postgresql·mybatis
美狐美颜sdk2 小时前
直播美颜sdk与智能美妆技术解析:实时人脸算法如何驱动新一代互动体验
人工智能·音视频·美颜sdk·视频美颜sdk·美狐美颜sdk
李慕婉学姐2 小时前
【开题答辩过程】以《基于Spring Boot的疗养院理疗管理系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring boot·后端
qq_12498707532 小时前
基于协同过滤算法的运动场馆服务平台设计与实现(源码+论文+部署+安装)
java·大数据·数据库·人工智能·spring boot·毕业设计·计算机毕业设计
一路向北⁢2 小时前
Spring Boot 3 整合 SSE (Server-Sent Events) 企业级最佳实践(一)
java·spring boot·后端·sse·通信
风象南2 小时前
JFR:Spring Boot 应用的性能诊断利器
java·spring boot·后端
爱吃山竹的大肚肚2 小时前
微服务间通过Feign传输文件,处理MultipartFile类型
java·spring boot·后端·spring cloud·微服务
qq_12498707533 小时前
基于springboot的尿毒症健康管理系统的设计与实现(源码+论文+部署+安装)
java·spring boot·spring·毕业设计·计算机毕业设计
编程彩机3 小时前
互联网大厂Java面试:从Spring Boot到微服务优化场景解析
spring boot·分布式事务·微服务架构·java面试·技术解析