Java后端接口返回视频流,使用video组件播放视频,实现分段下载

这篇具有很好参考价值的文章主要介绍了Java后端接口返回视频流,使用video组件播放视频,实现分段下载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

视频文件保存在不为人知的地方,总之前端不能直接访问的位置,需要通过后端接口取出来再返回给前端。
前端这样子播放

<video controls="controls" controls="controls">
  <source src="http://ip:port/xxxxxxx" type="video/mp4" />
</video>

src=后端接口
如果后端直接这样子写

	//path为本地文件路劲
    public void play(String path, HttpServletRequest request, HttpServletResponse response) {
        //获取视频文件流
        FileInputStream fileInputStream = null;
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            fileInputStream = new FileInputStream(new File(path));
        byte[] cache = new byte[1024];
            response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
            response.setHeader(HttpHeaders.CONTENT_LENGTH, fileInputStream.available()+"");
        int flag;
        while ((flag = fileInputStream.read(cache)) != -1) {
            outputStream.write(cache, 0, flag);
        }
        outputStream.flush();
        outputStream.close();
        }catch (Exception e){
            log.error("文件传输错误", e);
            throw new RuntimeException("文件传输错误");
        } finally{
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("流释放错误", e);
                }
            }
            if(fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.error("文件流释放错误", e);
                }
            }
        }
    }

小视频问题不大,视频大的话会卡顿很久,查看请求发现会先请求下载完整视频后开始播放。而且不能拖动进度条进行播放。追及原因是因为video会先发送一个探测请求获取视频的大小、长度等信息,之后才开始进行播放。不能拖动进度条播放是因为获取视频接口不支持断点传输所以只能依次观看。
http请求就有相关断点传输的协议,http协议状态码206就是实现断点传输的协议,Http请求头部需要指定获取数据的范围: Range: bytes=first-end,first,开始数据的索引位置,end,结束数据的索引位置。Http响应需要指定范围响应头:content-range bytes first-end,并且http状态码设置为206。
所以实现视频断点播放的大概思路为,先识别http请求头是否携带range请求头,如果携带则表示请求需要进行断点下载,识别出断点的位置后使用随机读取文件类RandomAccessFile进行一定范围的读写,之后返回设置Content-Range请求头表示返回数据的范围,并设置http状态码为206表示断点传输。代码如下文章来源地址https://www.toymoban.com/news/detail-530095.html

	//path为本地文件路劲
	public void play(String path, HttpServletRequest request, HttpServletResponse response) {

        RandomAccessFile targetFile = null;
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            response.reset();
            //获取请求头中Range的值
            String rangeString = request.getHeader(HttpHeaders.RANGE);

            //打开文件
            File file = new File(path);
            if (file.exists()) {
                //使用RandomAccessFile读取文件
                targetFile = new RandomAccessFile(file, "r");
                long fileLength = targetFile.length();
                long requestSize = (int) fileLength;
                //分段下载视频
                if (StringUtils.hasText(rangeString)) {
                    //从Range中提取需要获取数据的开始和结束位置
                    long requestStart = 0, requestEnd = 0;
                    String[] ranges = rangeString.split("=");
                    if (ranges.length > 1) {
                        String[] rangeDatas = ranges[1].split("-");
                        requestStart = Integer.parseInt(rangeDatas[0]);
                        if (rangeDatas.length > 1) {
                            requestEnd = Integer.parseInt(rangeDatas[1]);
                        }
                    }
                    if (requestEnd != 0 && requestEnd > requestStart) {
                        requestSize = requestEnd - requestStart + 1;
                    }
                    //根据协议设置请求头
                    response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
                    response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
                    if (!StringUtils.hasText(rangeString)) {
                        response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + "");
                    } else {
                        long length;
                        if (requestEnd > 0) {
                            length = requestEnd - requestStart + 1;
                            response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
                            response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + requestEnd + "/" + fileLength);
                        } else {
                            length = fileLength - requestStart;
                            response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
                            response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (fileLength - 1) + "/"
                                    + fileLength);
                        }
                    }
                    //断点传输下载视频返回206
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    //设置targetFile,从自定义位置开始读取数据
                    targetFile.seek(requestStart);
                } else {
                    //如果Range为空则下载整个视频
                    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=test.mp4");
                    //设置文件长度
                    response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));
                }

                //从磁盘读取数据流返回
                byte[] cache = new byte[4096];
                try {
                    while (requestSize > 0) {
                        int len = targetFile.read(cache);
                        if (requestSize < cache.length) {
                            outputStream.write(cache, 0, (int) requestSize);
                        } else {
                            outputStream.write(cache, 0, len);
                            if (len < cache.length) {
                                break;
                            }
                        }
                        requestSize -= cache.length;
                    }
                } catch (IOException e) {
                    // tomcat原话。写操作IO异常几乎总是由于客户端主动关闭连接导致,所以直接吃掉异常打日志
                    //比如使用video播放视频时经常会发送Range为0- 的范围只是为了获取视频大小,之后就中断连接了
                    log.info(e.getMessage());
                }
            } else {
                throw new RuntimeException("文件路劲有误");
            }
            outputStream.flush();
        } catch (Exception e) {
            log.error("文件传输错误", e);
            throw new RuntimeException("文件传输错误");
        }finally {
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error("流释放错误", e);
                }
            }
            if(targetFile != null){
                try {
                    targetFile.close();
                } catch (IOException e) {
                    log.error("文件流释放错误", e);
                }
            }
        }
    }

到了这里,关于Java后端接口返回视频流,使用video组件播放视频,实现分段下载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 视频推流测试——使用ffmpeg进行推流生成rtsp视频流

    在我们完成开发工作之后,需要通过推流的形式来验证能否正确接收视频流,并送入视频检测程序。笔者在这里使用的是业内最为常用的ffmpeg。具体方法如下。 访问ffmpeg的官网,地址为https://ffmpeg.org/download.html,按照如下途中来选择下载。 下载完成后,会得到一个zip格式的压

    2024年02月09日
    浏览(52)
  • JAVA实现H264视频流推送到RTSP、RTMP服务----JavaCV

    前提: 1.准备好rtsp、rtmp服务 2.准备好视频流接收程序 基本思路是:启动两个线程,线程1接收视频流,线程2使用JavaCV将视频流推送到RTSP、RTMP服务,两者之间使用管道流进行通信。线程2接收到视频流后的具体操作:启动grabber接收视频流并捕获视频帧,然后启动recoder将捕获的

    2024年02月11日
    浏览(60)
  • Windows上使用FFmpeg实现本地视频推送模拟海康协议rtsp视频流

    Nginx搭建RTMP服务器+FFmpeg实现海康威视摄像头预览: Nginx搭建RTMP服务器+FFmpeg实现海康威视摄像头预览_nginx rtmp 海康摄像头_霸道流氓气质的博客-CSDN博客 上面记录的是使用FFmpeg拉取海康协议摄像头的rtsp流并推流到流媒体服务器。 如果在其它业务场景下需要本地的视频文件模拟

    2024年02月12日
    浏览(44)
  • Vue中使用EasyPlayer播放H265视频流

    需要在Vue2的项目中使用EasyPlayer进行H265视频流的播放。使用官方的最新版本加载H265会有问题。一直处于加载中… 引入easyplayer,这里最开始引入了最新版会有问题,因此引入的是3.3.12版本,可参照官方文档进行配置。 EasyPlayer示例及使用说明 在static文件夹中引入对应EasyPlayer.

    2024年02月03日
    浏览(37)
  • Vue实现摄像头视频分屏, 使用flv.js接收rtmp/flv视频流

    1. 现有的平台系统播放实时视频。 因为用户电脑都是Linux系统,无法直接使用海康前端SDK,讨论决定由后台推视频流,简单调研后发现最流行的是flv,而且有B站开源的flv.js适配。前期后台推给我RTMP前缀的视频流,我尝试使用video.js,西瓜视频等都失败了,后来后端改为http前

    2024年02月03日
    浏览(56)
  • ZED相机使用记录(一):利用ZED SDK使用python完成局域网内的远程视频(视频流)传输

    ** 本文主要介绍ZED2相机以及具有的功能,ZED2相机(这里使用ZED2相机,主要是因为视频流传输功能目前只有ZED2、ZED mini等新版本相机才有的功能)** 本文所使用的环境: python:3.8 CUDA:10.2 需要安装的python库:pyzed(安装好ZED SDK后安装)、opencv(cv2)、sys 接收端(服务端):测试过的有

    2024年02月13日
    浏览(39)
  • vue2使用rtsp视频流接入海康威视摄像头(纯前端)

    海康威视官方的RTSP最新取流格式如下: rtsp://用户名:密码@IP:554/Streaming/Channels/101 用户名和密码 IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210) 所以笔者的rtsp流地址就是 rtsp://用户名:密码@192.168.1.210:554/Streaming/Channels/101 1.1关闭 萤石云的接入 1.2 调整视频编码为H.264 在此下载

    2024年04月26日
    浏览(57)
  • VS+QT+Opencv使用YOLOv4对视频流进行目标检测

    对单张图像的检测,请参考:https://blog.csdn.net/qq_45445740/article/details/109659938

    2024年02月12日
    浏览(55)
  • 使用Flask+OpenCV实现浏览器/微信小程序的视频流传输

    前言 一、 Flask+浏览器实现 二、 Flask+微信小程序实现 三、Flask+uni-app小程序实现 后记 近期在做的东西涉及到实时视频的处理,碰到一些问题,因此将之记录下来,便于日后翻看,同时也希望能给遇到同样问题的小伙伴提供帮助。 实现代码如下: 分为 app.py 和index.html。 1. F

    2024年02月06日
    浏览(75)
  • vue使用vue-h265-player播放h265编码格式视频流

    GitHub地址 vue-h265-player 支持h265编码格式视频流播放 vue使用vue-h265-player 1、安装vue-h265-player 2、拷贝libDecoder.wasm文件到public目录下 复制node_modules/h265-player/lib/libDecoder.wasm文件到public目录下 3、示例代码 url: 需要播放的链接,播放器会根据该值的变化自动重启。 maxRetryCount: 最大尝

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包