网站首页 > java教程 正文
介绍
最近因为想做个在手机上播放电脑上视频的软件,所以就去了解了一下springboot播放视频流的技术实现。网上查了很多资料,发现都有问题:
- 最低级的,直接在springboot中读取了整个视频文件,然后把读取到的文件流,写入HttpServletResponse的OutputStream。这种方案问题很大,服务器耗内存,客户端卡顿,因为客户端得把整个视频下载好才能播放。
- 稍好一点的,意识到要使用http的range来实现分片加载,就是客户端无需下载整个视频了,可以拖动进度条,分段请求服务器。但是,网上的教程,都是自己动手实现的,代码逻辑大概是这样:根据客户端要的文件片段,springboot加载本地文件,切分出具体那段文件,返回给客户端。逻辑没问题,就是没必要这么干~因为,springboot自己本身就有这方面的代码。自己写又不稳定,又麻烦。
ResourceHttpRequestHandler
ResourceHttpRequestHandler是springboot加载静态资源的一个类,平时是用来从你resources/statics等目录加载文件的。所以,这个类本身就是支持range请求数据的。我们要做的,就是把要播放的文件File传递给ResourceHttpRequestHandler就行,三五行代码搞定!
springboot服务端代码
第一步,先自定义实现一个ResourceHttpRequestHandler。代码如下:
package com.tec666.moviebar.config;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import javax.servlet.http.HttpServletRequest;
/**
* @author longge93
*/
@Component
public class NonStaticResourceHttpRequestHandler extends ResourceHttpRequestHandler {
public final static String ATTR_FILE = "NON-STATIC-FILE";
@Override
protected Resource getResource(HttpServletRequest request) {
String filePath = (String) request.getAttribute(ATTR_FILE);
return new FileSystemResource(filePath);
}
}
上面代码的意思是:从HttpServletRequest的attribute中读取文件path,然后返回给ResourceHttpRequestHandler处理。当然,这个attribute是我们后面传进来的。
第二步,在视频播放controller中,把本地文件路径传入ResourceHttpRequestHandler。代码如下:
@Controller
@RequestMapping(value = "/api/baseResource")
public class BaseSourceApiController {
@Autowired
private NonStaticResourceHttpRequestHandler nonStaticResourceHttpRequestHandler;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping(value = "/video", method = RequestMethod.GET)
public void video(
HttpServletRequest request,
HttpServletResponse response
) {
try {
String path = "D:/abc.mp4";
File file = new File(path);
if (file.exists()) {
request.setAttribute(NonStaticResourceHttpRequestHandler.ATTR_FILE, path);
nonStaticResourceHttpRequestHandler.handleRequest(request, response);
} else {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
}
} catch (Exception e) {
}
}
}
参数解释:记得把上面代码中的path替换成你的路径,或者从controller请求参数里获取。
到此,整个springboot播放视频流的功能就实现了,感觉是全网最最简便的了。因为可以根据range返回视频流片段,所以客户端是可以随意拖动进度条,可以倍速播放的。相比把整个视频下载好再播放,这个方案才是yyds!
Vue前端播放器
我使用的是vue-video-player这个开源组件,你可以自己用npm安装一下,然后在你的项目中直接用就行。配置参数的时候,视频地址就填上面springboot的这个controller地址。
java截取视频生成图片封面、GIF封面
主要分为两个功能:
- java截取视频,把视频帧拆分成几张图片,用作视频封面。
- java把几张图片拼接成一个gif图片。
这两个功能是在做播放器的时候,一起顺手实现的,网上的教程相对挺多的,如果有需要请点击右侧“联系作者”联系我,我再开单独的文章介绍。
播放器效果展示
我们打开chrome的开发者工具,查看播放视频时的网络请求,可以发现视频是被切分成小片段,根据你当前的播放进度,分片下载的。请看下图:
版权声明:《springboot+vue播放视频流(无需下载视频,可以拖动进度、倍速播放)》为CoderBBB作者「」的原创文章,转载请附上原文出处链接及本声明。
原文链接:https://www.coderbbb.com/articles/39
- 上一篇: 短视频APP的技术框架
- 下一篇: 音视频命令转换工具 - FFmpeg
猜你喜欢
- 2025-01-21 有视频才有真相 两款录屏软件推荐
- 2025-01-21 第十三章:Java图形用户界面编程
- 2025-01-21 全新版Jetpack进阶提升,系统性落地短视频App|超清完结无秘
- 2025-01-21 如何实现在线视频播放?
- 2025-01-21 Java 中的屏幕共享
- 2025-01-21 用 Java 语言,写一个植物大战僵尸简易版
- 2025-01-21 JavaCV的摄像头实战之五:推流(我的直播梦)
- 2025-01-21 西瓜视频稳定性治理体系建设一:Tailor 原理及实践
- 2025-01-21 “易语言”基础知识——编写一个MP3播放器
- 2025-01-21 Spring Boot + Minio 去掉电影网站视频广告:基于 M3U8播放地址
你 发表评论:
欢迎- 05-02Go 中的 channel 与 Java BlockingQueue 的本质区别
- 05-02处理线上RabbitMQ队列阻塞(rabbitmq队列状态)
- 05-02实现延迟队列,这些你知道吗?(延迟队列 kafka)
- 05-02学无止境:AQS阻塞队列和条件队列是如何使用的?
- 05-02京东大佬问我,SpringBoot中如何做延迟队列?单机与分布式如何做?
- 05-02阻塞队列ArrayBlockingQueue的实现原理浅析
- 05-02高性能队列:Java Concurrent包中的BlockingQueue
- 05-02不允许还有Java程序员不了解BlockingQueue阻塞队列的实现原理
- 最近发表
-
- Go 中的 channel 与 Java BlockingQueue 的本质区别
- 处理线上RabbitMQ队列阻塞(rabbitmq队列状态)
- 实现延迟队列,这些你知道吗?(延迟队列 kafka)
- 学无止境:AQS阻塞队列和条件队列是如何使用的?
- 京东大佬问我,SpringBoot中如何做延迟队列?单机与分布式如何做?
- 阻塞队列ArrayBlockingQueue的实现原理浅析
- 高性能队列:Java Concurrent包中的BlockingQueue
- 不允许还有Java程序员不了解BlockingQueue阻塞队列的实现原理
- JAVA并发之BlockingQueue(阻塞队列)
- dify案例分享-API文档生成接口代码
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)