在线视频播放

1.前端h5

<!DOCTYPE html>
<html>
<head>
    <title>Video Player</title>
</head>
<body>
    <video id="videoPlayer" width="640" height="360" controls>
        <source src="http://localhost:8085/video" type="">
    </video>
</body>
</html>

2.后端

1.文件在本地

@RequestMapping(value = "/video", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public ResponseEntity<byte[]> getVideo(@RequestHeader(value = "Range", required = false) String rangeHeader) throws IOException {
        File videoFile = new File("D:\\Download\\dolby-atmos-trailer_leaf_1080 (1).mp4");
        HttpHeaders headers = new HttpHeaders();

        long contentLength = videoFile.length();
        headers.setContentLength(contentLength);

        if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
            String[] range = rangeHeader.substring("bytes=".length()).split("-");
            long start = Long.parseLong(range[0]);
            long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
            long rangeLength = end - start + 1;
            System.out.println("rangeHeader" + start + "----" + end);
            System.out.println("rangeLength>>" + rangeLength);
            RandomAccessFile randomAccessFile = new RandomAccessFile(videoFile, "r");
            randomAccessFile.seek(start);

            byte[] buffer = new byte[(int) rangeLength];
            randomAccessFile.readFully(buffer);

           headers.set("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
          // headers.set("Accept-Ranges", "bytes");
            System.out.println("Content-Range"+headers.get("Content-Range"));
           headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            return new ResponseEntity<>(buffer, headers, HttpStatus.PARTIAL_CONTENT);
        } else {
            byte[] videoBytes = Files.readAllBytes(videoFile.toPath());
            return new ResponseEntity<>(videoBytes, headers, HttpStatus.OK);
        }
    }

2.文件在远程(本地代理下)

 @RequestMapping(value = "/getVideoDwn", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void getVideoDwn(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 视频文件的网络地址
        String videoUrl = "https://cn-beijing-data.aliyundrive.net/5fc0c8b4f1f50595b5094497b75fea8afe7b715e%2F5fc0c8b405587a69f8254396abeec229a33223ac?di=bj29&dr=34609702&f=6403623a11cebf9d430142cf99e4898d46ec77ef&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27dolby-atmos-trailer_leaf_1080.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5aNDoLStLIZ%2F7jfWBf9sTcGZsJhtbXupzz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNUugGA%2FTqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABKubZYG1xUq2lZMDjFlGRHUhz9UGR2xV3W9k%2Bnart0MJdTOPerzUFy16thRkU6GG0Yfn4CLH3Mat3IgbUVN%2FKIe%2F7Zwv4ZWsaqEX%2BaK1YAHbsMO2676F1uBcsoJQ9RB0ILokFBdp8je4vNp7w8bgz9HU%2FKAkticmNtIX8tkSUtGI%3D&u=254808010963075794&x-oss-access-key-id=STS.NU8E8fYm8Hz4Z1LU7SjMMZpEE&x-oss-expires=1678377242&x-oss-signature=ZF9JWAFQb%2F06KiV5hhIM1A4NP5GvZvs9NbhChblpTKc%3D&x-oss-signature-version=OSS2";


        HttpURLConnection connection = (HttpURLConnection) new URL(videoUrl).openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
        long contentLength = connection.getContentLengthLong();
//        response.setHeader("Content-Type", "video/mp4");
//        response.setHeader("Content-Length", String.valueOf(contentLength));

        String rangeHeader = request.getHeader("Range");
        if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
            String[] range = rangeHeader.substring("bytes=".length()).split("-");
            long start = Long.parseLong(range[0]);
            long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
            long rangeLength = end - start + 1;
            System.out.println("rangeHeader" + start + "-" + end);
            System.out.println("rangeLength>>" + rangeLength);
            HttpURLConnection connection1 = (HttpURLConnection) new URL(videoUrl).openConnection();
            //connection1.setRequestMethod("GET");
            connection1.setRequestProperty("Referer", "https://www.aliyundrive.com/");
            //connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
            connection1.setRequestProperty("Range", "bytes=" + start + "-" + end);
            InputStream inputStream = connection1.getInputStream();

            byte[] buffer = new byte[1024];
            int len = -1;
            response.setStatus(206);
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
            response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
            while ((len = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, len);
            }
            inputStream.close();
            response.getOutputStream().close();
            connection.disconnect();
            connection1.disconnect();
        } else {
            InputStream inputStream = connection.getInputStream();
            OutputStream outputStream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            inputStream.close();
            outputStream.close();
        }
    }
  1. 多线程下载加速(支持断点)

    @RequestMapping(value = "/videoManyThread", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void getVideoManyThread(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
        // 视频文件的网络地址
        String videoUrl = "https://cn-beijing-data.aliyundrive.net/wPA9FhRu%2F292012%2F63baa96ffffd146b8fa14608996c9870234550d9%2F63baa96f78a17f56b2884e58b71d91f22754f7ac?callback=eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9wZHNhcGkuYWxpeXVuZHJpdmUuY29tL3YyL2ZpbGUvZG93bmxvYWRfY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJodHRwSGVhZGVyLnJhbmdlPSR7aHR0cEhlYWRlci5yYW5nZX1cdTAwMjZidWNrZXQ9JHtidWNrZXR9XHUwMDI2b2JqZWN0PSR7b2JqZWN0fVx1MDAyNmRvbWFpbl9pZD0ke3g6ZG9tYWluX2lkfVx1MDAyNnVzZXJfaWQ9JHt4OnVzZXJfaWR9XHUwMDI2ZHJpdmVfaWQ9JHt4OmRyaXZlX2lkfVx1MDAyNmZpbGVfaWQ9JHt4OmZpbGVfaWR9IiwiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSJ9&callback-var=eyJ4OmRvbWFpbl9pZCI6ImJqMjkiLCJ4OnVzZXJfaWQiOiI3NGQ2NzQ4M2M5MWU0NzViYmJhZjc0YmQyMmUyNTUxZSIsIng6ZHJpdmVfaWQiOiIzNDYwOTcwMiIsIng6ZmlsZV9pZCI6IjYzZWQ5NTVmZGZmM2NhOWJhNTQ4NDJiMWEzNzdjMzVjMGFmM2E0NzgifQ%3D%3D&di=bj29&dr=34609702&f=63ed955fdff3ca9ba54842b1a377c35c0af3a478&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27ZYJFQ.S01E18.2023.1080P.H264.AAC-YYDS.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5DEGs3OmJVv37XeY0KDvWoZWrZpgPDtgTz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNVjdCnPSqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABfVnVHirOkxNrRMWIp45pNdFGEzh4fe1XnvKfIGLM%2BX740%2Fh%2BM8bnTOnoluAbU%2F%2FSzHzadNYgzea2Bhd63vwgofZmIi7tCMbvtsa4f2fM%2FZ8%2FdAXcLc5I0YJQkqP8bBSL8LqZhh4%2FgJJ5YyqmSoLYSJDSOfmEBNF6V6V%2FYUpYvek%3D&u=74d67483c91e475bbbaf74bd22e2551e&x-oss-access-key-id=STS.NSqQwzuJNhw5ad2YjLV9Eo5Fc&x-oss-additional-headers=referer&x-oss-expires=1678448406&x-oss-signature=bEAvAJEFH3MxsZUVT0Vqv%2BoXLBSHaVbWcYsa8aFXFh8%3D&x-oss-signature-version=OSS2";
        //视频时间秒
        long videoTime = 2580L;


        HttpURLConnection connection = (HttpURLConnection) new URL(videoUrl).openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
        //62072131
        long contentLength = connection.getContentLengthLong();
        long videoLength = contentLength;
//        response.setHeader("Content-Type", "video/mp4");
//        response.setHeader("Content-Length", String.valueOf(contentLength));
        String rangeHeader = request.getHeader("Range");
        if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
            String[] range = rangeHeader.substring("bytes=".length()).split("-");
            long start = Long.parseLong(range[0]);
            contentLength = contentLength / videoTime * 5 + start;
            long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
            if (end > videoLength) {
                end = videoLength-1;
            }
            long rangeLength = end - start + 1;
            System.out.println("rangeHeader" + start + "-" + end);
            System.out.println("rangeLength>>" + rangeLength);
            List<MultiThreadDownloader1.DownloadThread> dwnResult = MultiThreadDownloader1.dwn(videoUrl, rangeLength, start, 16);
            //HttpURLConnection connection1 = (HttpURLConnection) new URL(videoUrl).openConnection();
            //connection1.setRequestMethod("GET");
//            connection1.setRequestProperty("Referer", "https://www.aliyundrive.com/");
//            //connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
//            connection1.setRequestProperty("Range", "bytes=" + start + "-" + end);
//            InputStream inputStream = connection1.getInputStream();
//
//            byte[] buffer = new byte[1024];
//            int len;
            response.setStatus(206);
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
            response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + videoLength);
            for (MultiThreadDownloader1.DownloadThread downloadThread : dwnResult) {
                response.getOutputStream().write(downloadThread.getData(), 0, downloadThread.getData().length);
            }

            //inputStream.close();
            response.getOutputStream().close();
            connection.disconnect();
            //connection1.disconnect();
        } else {
            InputStream inputStream = connection.getInputStream();
            OutputStream outputStream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            inputStream.close();
            outputStream.close();
        }
    }
public  class MultiThreadDownloader1 {
    private static final String DOWNLOAD_URL = "https://cn-beijing-data.aliyundrive.net/5fc0c8b4f1f50595b5094497b75fea8afe7b715e%2F5fc0c8b405587a69f8254396abeec229a33223ac?di=bj29&dr=34609702&f=6403623a11cebf9d430142cf99e4898d46ec77ef&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27dolby-atmos-trailer_leaf_1080.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5fUINHDmbZ2zYi%2FNWPVkHoFaLxO25%2FZhzz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNXKYFkrTqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABg%2F8a2EeaNy%2FX0vUV5PxFFvCCQNK0HaXpQFXRgW8SXxbgenaJNdtzK4BDYNsAKrH1x%2FE8NMf3qatXM7QXvRB6DCjZ6hQoqEhsYSha9oUnsVdV%2F1dVgACHN5iLi9smoZJ5h4sHEP%2B97cs%2F9NlTwLC1%2Bg4%2Fo49KTxqkIduEtUaDw94%3D&u=254808010963075794&x-oss-access-key-id=STS.NTakkwtiWzJT7EdtzPd3b4Zre&x-oss-expires=1678247687&x-oss-signature=gXQa9IYNHVFYH%2FXrf%2B8U%2BZlCmir%2B0GQ363tMTdekcVs%3D&x-oss-signature-version=OSS2";
    //private static final int THREAD_COUNT = 2;

    public static void main(String[] args) {
        try {
            //dwn();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<DownloadThread> dwn(String dwnUrl, long totalLength, long chushistartIndex,int THREAD_COUNT) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        System.out.println("开始下载");
        URL url = new URL(dwnUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Referer", "https://www.aliyundrive.com/");

        List<DownloadThread> threads = new ArrayList<>();
        long blockSize = totalLength / THREAD_COUNT;
        for (long i = 0; i < THREAD_COUNT; i++) {
            long startIndex = i * blockSize + chushistartIndex;
            long endIndex = (i + 1) * blockSize + +chushistartIndex - 1;
            if (i == THREAD_COUNT - 1) {
                endIndex = totalLength + +chushistartIndex - 1;
            }
            DownloadThread thread = new DownloadThread(dwnUrl, startIndex, endIndex);
            threads.add(thread);
            thread.start();
        }

        boolean finished = false;
        while (!finished) {
            finished = true;
            for (DownloadThread thread : threads) {
                if (!thread.isFinished()) {
                    finished = false;
                    break;
                }
            }
            Thread.sleep(100);
        }

//        File file = new File("D:\\Download\\file.mp4");
//        FileOutputStream outputStream = new FileOutputStream(file);
//        for (DownloadThread thread : threads) {
//            if (thread.getData() != null)
//                outputStream.write(thread.getData());
//        }
        //outputStream.close();
        System.out.println((System.currentTimeMillis() - startTime) / 1000.0);
        return threads;
    }

    public static class DownloadThread extends Thread {
        private String url;
        private long startIndex;
        private long endIndex;
        private boolean finished;
        private byte[] data;

        public DownloadThread(String url, long startIndex, long endIndex) {
            this.url = url;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.finished = false;
        }

        public boolean isFinished() {
            return finished;
        }

        public byte[] getData() {
            return data;
        }

        @Override
        public void run() {
            try {
                URL url = new URL(this.url);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Referer", "https://www.aliyundrive.com/");
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                InputStream inputStream = conn.getInputStream();
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                inputStream.close();
                outputStream.close();
                data = outputStream.toByteArray();
                finished = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值