锦上添花的视频弹幕模块开发

简介: 锦上添花的视频弹幕模块开发
  • 非实时弹幕
  • image.png
  • 多节点实时弹幕
  • image.png
add: async (req) => {
    let { content, episodeId, playTime, productId } = req.body
    if (!(content && episodeId && Number(playTime) >= 0 && productId)) {
        return BackCode.buildError({ msg: '缺少必要参数' })
    }
    let token = req.headers.authorization.split(' ').pop()
    let userInfo = SecretTool.jwtVerify(token)
    let barrageItem = {
        episode_id: episodeId,
        product_id: productId,
        play_time: playTime,
        content: content,
        account_id: userInfo.id,
        head_img: userInfo.head_img,
        username: userInfo.username,
        del: 0,
    }
    await DB.BulletScreen.create(barrageItem)
    return BackCode.buildSuccess()
},

具体解释如下:

  1. let { content, episodeId, playTime, productId } = req.body;: 这行代码从请求的 body 中解构出弹幕的内容 (content)、集数 ID (episodeId)、播放时间 (playTime) 和产品 ID (productId)。这些参数都是客户端传来的。
  2. if (!(content && episodeId && Number(playTime) >= 0 && productId)) { return BackCode.buildError({ msg: '缺少必要参数' }) }: 这行代码用于判断是否缺少必要参数。如果其中任何一个参数为空或播放时间小于零,就会返回一个错误响应,提示缺少必要参数。
  3. let token = req.headers.authorization.split(' ').pop();: 这行代码从请求头中获取授权令牌 (authorization),然后将其拆分为两部分,取第二部分作为 token。
  4. let userInfo = SecretTool.jwtVerify(token);: 这行代码使用 SecretTool 工具类的 jwtVerify 方法对 token 进行解析,并返回包含用户信息的对象。
  5. let barrageItem = { ... }: 这是一个对象字面量,用于存储要添加到数据库的弹幕数据。其中包含集数 ID、产品 ID、播放时间、内容、账户 ID、头像、用户名和删除标志等信息。
  6. await DB.BulletScreen.create(barrageItem);: 这行代码使用模型 BulletScreen 的 create 方法创建一个新的弹幕实例,并将前面构建的 barrageItem 对象作为参数传递给它。通过这个操作,弹幕数据被写入到数据库中。
  7. return BackCode.buildSuccess();: 最后,返回一个成功的响应。

弹幕查询

list_by_episode: async (req) => {
  let { beginTime, endTime, episodeId, productId } = req.body
  if (!(productId && episodeId && Number(beginTime) >= 0 && endTime)) {
    return BackCode.buildError({ msg: '缺少必要参数' })
  }
  let barrageList = await DB.BulletScreen.findAll({
    where: { play_time: { [Op.between]: [beginTime, endTime] }, episode_id: episodeId, product_id: productId    }
  })
  return BackCode.buildSuccessAndData({ data: barrageList })
},

现阶段浏览器网页主要的请求方式

用户如何在浏览器上不作任何操作的情况下接收到服务器的消息?

定时短轮询

定时1-3秒请求服务器接口查询状态

场景:扫码登录、扫码支付等等

缺点:

1.虽然是用户无感知得从服务器获取消息,但是控制台上会有一堆的网络请求; 2.而且定时频繁地请求服务器接口,会消耗带宽,增加服务器的负担; 3.用户扫码后需要等待几秒时间,页面才能跳转,会有明显的卡顿;

长轮询

将http接口请求的超时时间设置大些(满足用户扫码所需的时间),如果超时就发起下一次请求

场景:百度云网盘app扫码登录等

特点:

1.用户扫码之后,在电脑端网页就秒跳转,用户不需要等待

以上两种方式称为服务器推送技术本质上还是客户端主动请求数据,只不过在用户无感知的情况下,也叫comet技术

为什么使用websocket?

像轮询的机制还是以客户端发起的请求,对于简单的扫码登录状态查询可以适用,但是遇到数据传输量大的场景就不行了,同时不能保证及时接受到消息,类似视频会议、网页游戏等业务场景,需要两端互相传输大量的数据,因此就需要使用websocket

  • 由来

现在使用最广泛的应用层协议HTTP1.1基于TCP协议,同一时间内客户端和服务端只能有一方主动发送数据,称为半双工

而TCP协议是全双工的,同一时间内两端都可以同时像对方发送数据,称为全双工

为了满足两端相互发送大量的场景,兴起了基于TCP协议的应用层协议websocket

 

  • 什么websocket?
  • 定义

是一种在单个TCP连接上进行全双工通信的协议使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据

在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

-   优点
    -   节省资源:对比客户端轮询请求后端接口,更加节省服务器资源和宽带
    -   更强实时性:由于协议是全双工的,所以服务器可以随时主动给客户端下发数据,延迟更小
    -   保持连接状态:HTTP请求建立一次链接就断开,而websocket是持久性链接
-   使用场景
    -   弹幕
    -   多玩家游戏
    -   视频会议
    -   股票基金报价实时更新
    -   体育实况更新
    -   音视频聊天
    -   在线教育
    -   社交订阅

弹幕获取-前端模块编码实战开发

自定义封装websocket

/**
 * 弹幕逻辑配置
 */
import { useRef, useState } from "react";
import { io } from "socket.io-client";
const useSocket = () => {
  // 弹幕实例变量名
  const socket = useRef<any>(null);
  // 发送的弹幕
  const videoDanmuList = useRef<any[]>([]);
  const initialize = () => {
    // 建立传输链接 http://127.0.0.1:8081
    socket.current = io("ws://127.0.0.1:8081");
    socket.current.on("connect", () => {
      console.log("socketio已连接");
    });
    onBulletChat();
  };
  // 发送弹幕事件
  const handleAddDanmu = (data: any) => {
    socket.current.emit("bulletChat", data);
  };
  // 监听bulletChat事件
  const onBulletChat = () => {
    socket.current.on("message", (data: any) => {
      videoDanmuList.current.push(data);
    });
  };
  return {
    videoDanmuList,
    initialize,
    handleAddDanmu,
    onBulletChat,
  };
};
export default useSocket;

后段启动websocket

app.js

const express = require('express');
const app = express();
const { createServer } = require('http');
const server = createServer(app)
server.listen(8081, () => {
  console.log('服务启动在:http://127.0.0.1:8081')
})

websocket.js

const { Server } = require('socket.io')
const Redis = require("ioredis");
// redis发布的api
const clientPublish = new Redis({ port: 6379, host: '8.130.120.189', password: 'xdclass.net' });
// redis订阅api
const clientSubscribe = new Redis({ port: 6379, host: '8.130.120.189', password: 'xdclass.net' });
clientSubscribe.subscribe('chat');
const websocket = (server) => {
    // 实例化socket
    const io = new Server(server, { cors: { origin: '*' } })
    // websocket建立链接
    io.on('connection', (socket) => {
        console.log('有客户端链接进来了')
        // 监听bulletChat事件
        socket.on('bulletChat', (info) => {
            clientPublish.publish('chat', JSON.stringify(info))
        })
    })
    // 订阅redis收到消息后,执行websocket的消息推送客户端
    clientSubscribe.on('message', (channel, message) => {
        io.emit('message', JSON.parse(message))
    })
}
module.exports = websocket

websocket使用模式

-   单播:点对点 私信私聊
-   多播:也叫组播(特定人群) 多人聊天,发布订阅
-   广播:游戏公告
如果你使用Node.js做服务端,那么该选择Socket.IO
目录
相关文章
|
前端开发 JavaScript 定位技术
threejs绘制风羽
threejs绘制风羽
1608 0
|
Web App开发 弹性计算
阿里云ECS云服务器系统盘不够用怎么办?磁盘扩容功能了解一下
阿里云ECS云服务器默认搭配的是40G的系统盘,系统盘不够用怎么办?云服务器吧告诉大家ECS系统盘支持磁盘扩容更能,无需更换系统盘,一键扩容: ECS云服务器磁盘扩容 以前ECS云服务器系统盘不够用,是通过更换系统盘来实现的,更换系统盘时通过更换一个新的磁盘,选择一个镜像的方式来扩容,老的磁盘会被释放,十分麻烦。
15874 1
|
自然语言处理 搜索推荐 Python
中文文本处理高手指南:从零到高手掌握Python中jieba库
中文文本处理高手指南:从零到高手掌握Python中jieba库
1064 0
|
人工智能 运维 云计算
飞天技术观丨开放的Autonomous Cloud,开启AI崭新时代
面向智能时代,阿里云将通过从底层算力到AI平台再到模型服务的全栈技术创新,升级云计算体系,打造一朵AI时代最开放的云。2023年,AI和云计算也终于走在一起,融合出更有生命力的广阔空间。
飞天技术观丨开放的Autonomous Cloud,开启AI崭新时代
|
Web App开发 JavaScript 前端开发
WebRTC 和 RTC 有什么区别?
【10月更文挑战第25天】WebRTC是RTC的一种具体实现方式,侧重于网页端的实时通信,具有便捷性和跨平台性等特点;而RTC则是一个更广泛的概念,包括了各种不同平台和技术实现的实时通信方式,应用场景更加丰富多样。在实际应用中,需要根据具体的需求和场景选择合适的实时通信技术。
|
开发框架 前端开发 JavaScript
跨平台应用开发技术的深度探讨
【7月更文挑战第26天】 跨平台应用开发技术已成为当前软件开发领域的重要趋势。通过合理使用跨平台开发框架和工具,开发者可以更加高效地构建适用于多个平台的应用程序,提高开发效率和用户体验。然而,跨平台开发也面临着性能优化、兼容性问题等挑战,需要开发者不断学习和实践,以应对不断变化的市场需求和技术挑战。
|
API
STM32速成笔记(九)—RTC
本文详细介绍了RTC模块,介绍了STM32的RTC的特性,框图,配置步骤,并给出了详细的程序设计。最后,针对实际使用时可能遇到的问题给出了解决方法以及程序。
1271 0
STM32速成笔记(九)—RTC
|
关系型数据库 Java 数据库
实时计算 Flink版操作报错合集之flinksql采PG数据库时报错,该如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
机器学习/深度学习 算法 计算机视觉
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
783 0
没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络
|
UED
带您一步步构建一个具有复杂布局的电商详情页,涵盖页面结构规划、样式设计以及交互效果的实现
【6月更文挑战第14天】构建复杂布局的电商详情页涉及页面结构规划、样式设计和交互效果实现。首先,规划页面结构,包括顶部导航栏、商品图片展示区、商品信息区、用户评价区和相关商品推荐区。接着,进行样式设计,注重色彩搭配、字体选择、布局与间距以及图片处理。例如,使用固定顶部导航栏,轮播图展示商品图片,分块展示商品信息和评价,以及设计相关商品推荐区。最后,实现交互效果,如图片放大、添加到购物车按钮、滚动监听和评论互动,提升用户体验。实际开发时需根据需求和规范进行调整,保证跨设备兼容性。
1100 1