java实现video标签视频流播放

这篇具有很好参考价值的文章主要介绍了java实现video标签视频流播放。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

java实现video标签视频流播放

问题:

在遇到video标签播放后端视频源时问题。直接返回文件流的话 video需要将文件整个下载一次才会播放。这样如果小文件没有问题。如果文件大的话就比较恶心了。

解决方案:通过模拟video标签默认的range bytes规范方法分段获取视频信息。

video标签是通过请求头带上 Range: bytes=1179648- 意思是:告诉服务端我要1179648字节开始之后的内容
然后服务端响应头返回:
accept-ranges: bytes #告诉浏览器我响应的数据的范围是字节形式的。
Content-Length: 286233105 #这次响应内容的大小。
Content-Range: bytes 1179648-287412752/287412753 #响应内容的范围。287412753 是整个视频总大小。

实现代码仅供参考主要是理解思想:文章来源地址https://www.toymoban.com/news/detail-628999.html

  public void videoStream(String env,String app,String id, HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.拿到文件引用
        FileInfo fi = getCacheFileInfo(env, app, id);
        if (fi==null){
            log.info("找不到文件:"+getKey(env,app,id));
            return;
        }


        String header = request.getHeader(HttpHeaders.RANGE);
        //2.如果没有这个协议则直接走流下载
        if (StringUtils.isEmpty(header)){
            fileService.downloadFileStream(env,app,id,response);
            return;
        }

        //3.获取数据的数据的范围
        String[] rangeArr = header.replace("bytes=","").split("-");
        long fileLength = getFileLength(fi);
        long requestStart = getRequestStart(rangeArr);
        long requestEnd = getRequestEnd(rangeArr);
        if (requestEnd==0){
            requestEnd=requestStart+ chunkSize -1;
        }
        if (requestEnd>=fileLength){
            requestEnd=fileLength-1;
        }


        //4根据协议设置请求头
        response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
        response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");
        long length = requestEnd - requestStart + 1;
        if (requestStart==0){
            length=fileLength;
        }
        response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);
        response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + requestStart + "-" + (requestStart==0?fileLength-1:requestEnd) + "/" + fileLength);
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);


        //5.写数据
        writeData(env, app,fi,requestStart,requestEnd,response);


    }
      

private void writeData(String env,String app ,FileInfo fi, long requestStart, long requestEnd, HttpServletResponse response) {
        try (BufferedOutputStream bos=new BufferedOutputStream(response.getOutputStream())){
           //这个是下载普通文件
            if (fi instanceof StandaloneFileInfo){

                writeDataStandalone((StandaloneFileInfo) fi,requestStart,requestEnd,bos);
			//这个是下载分片文件
            }else if ( fi instanceof ShardingFileInfo){
                writeDataSharding(env,app,(ShardingFileInfo) fi,requestStart,requestEnd,bos);
            }
        }catch (Exception e){
            log.error("写数据报错");
        }
    }


	
    private void writeDataSharding(String env,String app,ShardingFileInfo fi, long requestStart, long requestEnd, BufferedOutputStream bos) throws Exception {
        //1.计算当前字节请求范围在那些分片上。
        int startChuck= (int) ((requestStart+1)%chunkSize==0?(requestStart+1)/chunkSize:((requestStart+1)/chunkSize)+1);
        int endChuck  = (int) ((requestEnd+1)/chunkSize)+1;

        //2.将需要请求的分片数据下载下来 放入一个buffer  这里为什么要用buffer 因为这种请求是很频繁的使用堆内存 比使用堆外内存消耗大。因为堆内存要gc
        ByteBuf buffer= ByteBufAllocator.DEFAULT.heapBuffer(chunkSize);
        List<String> shards = fi.getShardingMappingIds();
        for (int i = startChuck-1; i <shards.size()&&i<endChuck; i++) {
            StandaloneFileInfo info = (StandaloneFileInfo) fileService.downloadFile(env, app, shards.get(i));
            buffer.writeBytes(info.getData());
        }

        //3.计算具体从buff的那个字节开始读 以及这次读取字节的范围
        int startLen=(int) ((requestStart) % chunkSize);
        int len= (int) ((requestEnd - requestStart)+ 1);

        //4.将需要读取的字节写回去。并且释放掉这次的buffer。
        byte[] data=new byte[buffer.writerIndex()];
        buffer.getBytes(buffer.readerIndex(),data);
        bos.write(data,startLen,len);
        buffer.release();
    }


    private void writeDataStandalone(StandaloneFileInfo sfi,long requestStart, long requestEnd, OutputStream sos) throws IOException {
        byte[] bytes = Arrays.copyOfRange(sfi.getData(), (int) requestStart, (int) requestEnd);
        sos.write(bytes);
    }

到了这里,关于java实现video标签视频流播放的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Video(flv,mpegts)视频流解决方案

    1.直播与点播 点播:从后端请求到MP4视频,前端把地址放在video的src中实现播放 直播:1.获取的是流数据2.要求实时性 2.视频流形式 RTSP转RTMP 底层基于 TCP,在浏览器端依赖 Flash,但是从2020底年开始,谷歌已经带头不支持flash插件了 RTSP转HLS 后端将视频转成HLS流,以m3u8后缀结尾。通过

    2024年02月17日
    浏览(34)
  • 【音视频】如何播放rtsp视频流

    现阶段直播越来越流行,直播技术发展也越来越快。Webrtc和rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtsp、webrtc的使用过程。 本文重点介绍如何播放rtsp视频流,通过ffplay方式以及VLC media player的方式来播放 可以参考上一篇博文:【音视频】基于

    2024年01月19日
    浏览(48)
  • 【vue2】前端如何播放rtsp 视频流,拿到rtsp视频流地址如何处理,海康视频rtsp h264 如何播放

    最近在写vue2 项目其中有个需求是实时播放摄像头的视频,摄像头是 海康 的设备,搞了很长时间终于监控视频出来了,记录一下,放置下次遇到。文章有点长,略显啰嗦请耐心看完。 测试?测试什么?测试rtsp视频流能不能播放。 video mediaplay官网 即(VLC) 下载、安装完VLC后

    2024年02月05日
    浏览(39)
  • 【音视频】基于NGINX如何播放rtmp视频流

    现阶段直播越来越流行,直播技术发展也越来越快。Webrtc、rtmp、rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtmp如何播放。 本文重点介绍基于NGINX如何播放rtmp视频流 可以参考上一篇博文:【音视频】基于webrtc协议浏览器播放rtsp https://blog.csdn.n

    2024年01月19日
    浏览(41)
  • 如何解决html播放rtsp视频,浏览器播放rtsp视频流方案

    最近项目中需要实时播放摄像头rtsp视频流,于是就专门做了些研究。而浏览器不能直接播放,只有通过插件或者转码来实现这个需求。 要实现这个目的,可以采用的方案非常得多,有商业的也有开源的,这里主要列举一些开源的方案。这里的方案都是我尝试过了的,有些成

    2024年02月05日
    浏览(40)
  • 【vue Dplayer】播放hls视频流

    安装Dplayer和hls.js 准备测试流 hls测试地址:(截止2023.08.08有效) http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8

    2024年02月13日
    浏览(27)
  • TSINGSEE青犀视频汇聚平台EasyCVR多种视频流播放协议介绍

    众所周知,TSINGSEE青犀视频汇聚平台EasyCVR可支持多协议方式接入,包括主流标准协议GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。今天我们来说一说,EasyCVR平台支持分发的多种视频流协议。 视频监控综合管理平台EasyCVR具备视频

    2024年02月14日
    浏览(29)
  • electron+vue网页直接播放RTSP视频流?

    目前大部分摄像头都支持RTSP协议,但是在浏览器限制,最新版的浏览器都不能直接播放RTSP协议,Electron 桌面应用是基于 Chromium 内核的,所以也不能直接播放RTSP,但是我们又有这个需求怎么办呢? 市场上的方案很多,有很多免费开源的,同时也有比较成熟的商业软件,丰俭

    2024年02月02日
    浏览(40)
  • 前端播放大视频卡顿的解决(m3u8视频流)

    最近在一个大屏看板项目中有一个需求是:要求视频和看板要进行来回切换。 最开始的做法是将MP4视频放在项目里,在本地运行时是没什么问题的,但是在往仓库里提交代码时出现了问题。当单个文件超过100MB时会导致代码提交失败; 后来的解决方案是将视频文件放到服务器

    2024年01月19日
    浏览(48)
  • Vue中使用EasyPlayer播放H265视频流

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

    2024年02月03日
    浏览(25)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包