当前位置: 首页 > news >正文

视频播放实现示例Demo

学习链接

vue+springboot文件分片上传与边放边播实现

同步加载、播放视频的实现 ---- range blob mediaSource

通过调试技术,我理清了 b 站视频播放很快的原理

MSE (Media Source Extensions) 上手指南

浅聊音视频的媒体扩展(Media Source Extension)

流媒体视频基础 MSE 入门 & FFmpeg 制作视频预览缩略图和 fmp4

今天又学到一种播放视频的方法,先把视频分块的都获取到,然后再使用URL.createObject(chunks)创建blobUrl,再把这个blobUrl给到video标签即可 播放视频(可以拖动视频进度条)。但是这种缺点也很明显,得把所有视频文件分块获取完成后,才能播放视频。体验上就不是很好。后面有时间可以看下MediaSource相关(能否实现边下载边播放,而不是非得等到全部下载完了再播放?)

在这里插入图片描述

VideoPlay.vue

<template><div class="release_wrap"><el-card class="release_card"><el-table stripe :data="tableData" style="width: 100%" height="600px"><el-table-column prop="videoName" label="视频名称" min-width="280"></el-table-column><el-table-column label="操作"><template slot-scope="scope"><el-button size="mini" type="primary" @click="playVideo(scope.$index, scope.row)">播放</el-button></template></el-table-column></el-table></el-card><el-dialog :modal="false" title="视频播放" :visible.sync="dialogVisible" width="40%"><video :src="videoUrl" controls="controls" width="100%" @canplay="getVidDur()" id="myvideo"></video></el-dialog></div>
</template><script>var video = () => {var videoTime = document.getElementById("myvideo");console.log(videoTime.duration); //获取视频时长console.log(videoTime.currentTime); //获取视频当前播放时间
};export default {data() {return {title: "",videolist: "",//表格数据tableData: [],//弹框组件隐藏dialogVisible: false,//用于保存视频的idvideoId: 0,//保存视频的名称videoName: '',videoUrl: '',};},created() {this.getVideoInfo();},methods: {jump_home() {this.$router.replace('/')},getVidDur() {video();},//获取video表格数据getVideoInfo() {this.$axios.get("http://127.0.0.1:9098/SelectVideo/table").then((res) => {this.tableData = res.data;});},// 点击播放按钮playVideo(i, val) {// 显示弹框this.dialogVisible = true;// 保存视频名字this.videoName = val.videoName;// 保存视频idthis.videoId = val.id;// 发送HEAD请求获取视频的总大小this.$axios.get(`http://127.0.0.1:9098/SelectVideo/getVideoSizeById/${this.videoId}`).then(res => {const totalSize = res.data;const chunkSize = Math.ceil(totalSize / 20); // 设置分片大小为总大小的1/5// 定义分片传输的函数const loadVideoChunk = (startByte, endByte) => {return new Promise((resolve, reject) => {this.$axios.get(`http://127.0.0.1:9098/SelectVideo/policemen/${this.videoId}`, {headers: {Range: `bytes=${startByte}-${endByte}`},responseType: 'blob'}).then(response => {// 返回获取到的视频分片数据resolve(response.data);}).catch(error => {reject(error);});});};// 创建一个数组来保存所有分片的Promiseconst chunkPromises = [];// 获取所有分片的Promisefor (let i = 0; i < 20; i++) {const startByte = i * chunkSize;const endByte = Math.min(startByte + chunkSize - 1, totalSize - 1);chunkPromises.push(loadVideoChunk(startByte, endByte));}// 执行所有分片请求,并在全部请求完成后开始播放视频Promise.all(chunkPromises).then(chunks => {// 将分片数据合并成完整的视频Blobconst videoBlob = new Blob(chunks);const videoUrl = URL.createObjectURL(videoBlob);this.videoUrl = videoUrl;}).catch(error => {console.error('Failed to load video:', error);});}).catch(error => {console.error('Failed to get video size:', error);});},},
};
</script><style></style>

SelectVideoController

    //查询视频流的接口@GetMapping("/policemen/{videoId}")public void videoPreview(HttpServletRequest request, HttpServletResponse response, @PathVariable("videoId") String videoId) throws Exception{System.out.println(videoId);VideoUpload videoPathList = videoUploadMapper.SelectVideoId(Integer.parseInt(videoId));String videoPathUrl = videoPathList.getVideoUrl();Path filePath = Paths.get(videoPathUrl);if (Files.exists(filePath)){String mimeType = Files.probeContentType(filePath);if (StringUtils.hasText(mimeType)){response.setContentType(mimeType);}// 设置支持部分请求(范围请求)的 'Accept-Ranges' 响应头response.setHeader("Accept-Ranges", "bytes");// 从请求头中获取请求的视频片段的范围(如果提供)long startByte = 0;long endByte = Files.size(filePath) - 1;String rangeHeader = request.getHeader("Range");// System.out.println("rangeHeader:" + rangeHeader);if (rangeHeader != null && rangeHeader.startsWith("bytes=")){String[] range = rangeHeader.substring(6).split("-");startByte = Long.parseLong(range[0]);if (range.length == 2){endByte = Long.parseLong(range[1]);}}// System.out.println("start:" + startByte + ",end:" + endByte);log.info("start:" + startByte + ",end:" + endByte);// 设置 'Content-Length' 响应头,指示正在发送的视频片段的大小long contentLength = endByte - startByte + 1;response.setHeader("Content-Length", String.valueOf(contentLength));// 设置 'Content-Range' 响应头,指示正在发送的视频片段的范围response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + Files.size(filePath));// 设置响应状态为 '206 Partial Content'response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);// 使用 'RangeFileChannel' 进行视频片段的传输,以高效地只读取文件的请求部分ServletOutputStream outputStream = response.getOutputStream();try (RandomAccessFile file = new RandomAccessFile(filePath.toFile(), "r"); FileChannel fileChannel = file.getChannel()){fileChannel.transferTo(startByte, contentLength, Channels.newChannel(outputStream));} finally{outputStream.close();}} else{response.setStatus(HttpServletResponse.SC_NOT_FOUND);response.setCharacterEncoding(StandardCharsets.UTF_8.toString());}}

相关文章:

视频播放实现示例Demo

学习链接 vuespringboot文件分片上传与边放边播实现 同步加载、播放视频的实现 ---- range blob mediaSource 通过调试技术&#xff0c;我理清了 b 站视频播放很快的原理 MSE (Media Source Extensions) 上手指南 浅聊音视频的媒体扩展&#xff08;Media Source Extension…...

makefile的自动化变量

一、是什么? 自动化变量:makefile依据执行的规则自动变化生成的变量 $(@) 规则的目标文件名 $(^) 所有依赖 依赖列表 $(<)第一个依赖文件名 $(*)规则中目标中%部分名 $(?)所有比目标文件更新的依赖文件列表,空格分隔 二、使用步骤 1.引入库 代码如下(示例): make …...

使用Kind搭建本地k8s集群环境

目录 1.前提条件 2.安装Kind 3.使用Kind创建一个K8s集群 3.1.创建一个双节点集群&#xff08;一个Master节点&#xff0c;一个Worker节点&#xff09; 3.2.验证一下新创建的集群信息 3.3.删除刚刚新建的集群 4.安装集群客户端 4.1.安装kubectl 4.1.1.验证kubectl 4.2.安…...

【STM32RT-Thread零基础入门】 7. 线程创建应用(多线程运行机制)

硬件&#xff1a;STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、RT-Thread相关接口函数1. 获取当前运行的线程2. 设置调度器钩子函数 二、程序设计1. 头文件包含及宏定义2. 线程入口函数定义3. main函数设…...

.net日志系统

.NET 平台提供了强大的日志记录系统,用于在应用程序中记录各种事件、错误和调试信息。最常用的日志记录库是 Microsoft.Extensions.Logging,它是一个通用的日志接口和基础框架,可以与多种日志实现集成。以下是如何使用 .NET 日志系统的基本步骤: 安装 NuGet 包:首先,您需…...

SpringCloud学习笔记(二)_Eureka注册中心

一、Eureka简介 Eureka是一项基于REST&#xff08;代表性状态转移&#xff09;的服务&#xff0c;主要在AWS云中用于定位服务&#xff0c;以实现负载均衡和中间层服务器的故障转移。我们称此服务为Eureka Server。Eureka还带有一个基于Java的客户端组件Eureka Client&#xff…...

spark的eventLog日志分析

查找满足指定条件的app_id查询条件: 表名、时间、节点名时间限定: 最好适当放大, 不知道什么原因有点不准eventLog的存放路径: spark.history.fs.logDirectory 1. spark-sql 先限定时间段;数据是逐行读入的, 但 app_id要按整个文件过滤, 按每个条件打标;按app_id粒度聚合, 查…...

探究Java spring中jdk代理和cglib代理!

面对新鲜事物&#xff0c;我们要先了解在去探索事物的本质-默 目录 一.介绍二者代理模式 1.1.Jdk代理模式 1.2cglib代理模式 1.3二者区别 1.3.1有无接口 1.3.2灵活性 1.4对于两种代理模式的总结 1.4.1jdk代理模式 1.4.2cglib代理模式 二.两种代理模式应用场景 2.1jd…...

反转链表(C++)

1、迭代法的一种写法 ListNode* reverse_linkList(ListNode* head){if(head nullptr || head->next nullptr) return head;ListNode* begin nullptr;ListNode* mid head;ListNode* end head->next;while(true){mid->next begin;if(end nullptr){break;}begin …...

适配器模式:让不兼容的接口协同工作

在面向对象设计中&#xff0c;适配器模式是一种常见的结构型设计模式。它允许将不兼容的接口转换成客户端所期望的另一个接口&#xff0c;从而使不同的类协同工作。适配器模式的主要目的是解决不同接口之间的兼容性问题&#xff0c;同时也提高了代码的可重用性和灵活性。 问题…...

【1day】复现Milesight-VPNserver.js 任意文件读取漏洞

目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 Milesight路由器-VPN是由Milesight Technology Co., Ltd.开发的一种集成了VPN功能的路由器产品。它旨在为用户提供安全、可靠的远程访问和连接解决方案。Milesight-VPNserver.js存在任意文件读取…...

前端代码规范

1 husky husky用于绑定git hooks&#xff0c;在指定时机执行想要的命令 {"husky": {"hooks": {"pre-commit": "lint-staged" }} }需要手动修改.husky文件内容&#xff1a; . "$(dirname -- "$0")/_/husky.sh"n…...

Java接入文心一言

文章目录 文心一言应用创建接口对接接口文档代码示例依赖 常量类实体类 结束语 文心一言应用创建 首先需要先申请文心千帆大模型&#xff0c;申请地址&#xff1a;文心一言 (baidu.com)&#xff0c;点击加入体验&#xff0c;等通过审核之后就可以进入文心千帆大模型后台进行应…...

信息管理系统三级等保的一些要求

一、前言 在做一些互联网系统或面向互联网的系统时&#xff0c;需要进行备案&#xff0c;需要满足网络信息安全维护规章及有关规章制度要求&#xff0c;才能发布到互联网。所以在做系统的需求分析时&#xff0c;往往需要把信息管理系统三级等保的需求加上&#xff0c;方便开发…...

第六届“蓝帽杯”电子取证模块(初赛)解析+全资源一次性分享

前言:资源一次性分享 手机+电脑+exe+内存四个模块,我自己在网上也找了很久,才把资源找齐全,题目我也整理在这里,方便大家训练。 目录...

《Go 语言第一课》课程学习笔记(九)

常量&#xff1a;Go 在“常量”设计上的创新有哪些&#xff1f; Go 语言在常量方面的创新包括下面这几点&#xff1a; 支持无类型常量&#xff1b;支持隐式自动转型&#xff1b;可用于实现枚举。 常量 Go 语言的常量是一种在源码编译期间被创建的语法元素。这是在说这个元素…...

docker 安装nginx 和 elasticsearch ik 自定义分词

1、切换到/mydata 文件夹 创建 nginx 目录 mkdir nginx 2、运行 docker run --name nginx -p 80:80 -d nginx:1.22.0 3、复制docker 里面的nginx配置到 外面的nginx/conf 下面 docker cp nginx:/etc/nginx /mydata/nginx 4、把 /mydata/nginx下面的nginx 改…...

谈谈收音机的发展

目录 1.什么是收音机 2.收音机的工作原理 3.收音机的发展历史 4.收音机的历史作用 1.什么是收音机 收音机是一种电子设备&#xff0c;用于接收和播放广播电台的无线电信号。它是人们获取各种音乐、新闻、娱乐和其他广播节目的常用设备。 收音机通常由以下几个部分组成&…...

QTreeWidget——信号处理

文章目录 基本属性信号一、信号种类二、信号测试1、currentItemChanged、itemCollapsed、itemExpanded三个信号的测试2、itemActivated信号3、 itemChanged信号4、其余信号的测试代码&#xff08;包含以上代码&#xff09; 基本属性 信号 一、信号种类 //当前项发生变化时触…...

【Java从入门到精通|1】从特点到第一个Hello World程序

写在前面 在计算机编程领域&#xff0c;Java是一门广泛应用的高级编程语言。它以其强大的跨平台性能、丰富的库和生态系统以及易于学习的语法而备受开发者欢迎。本文将引导您逐步了解Java的特点、如何安装和配置开发环境&#xff0c;以及如何编写您的第一个Java程序。 一、Java…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...