栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MInIO入门-04 基于minio+ckplayer视频点播 实现

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MInIO入门-04 基于minio+ckplayer视频点播 实现

MInIO入门-04 基于minio+ckplayer视频点播 实现 1、ckplayer(前端js播放器) 1.1、官网

https://www.ckplayer.com/

2、后台实现 2.1、参考博客

https://blog.csdn.net/waleit/article/details/117693364

2.2、通过request的Range来实现

2.3、后台代码
package cn.lyf.minio.controller;

import cn.lyf.minio.core.MinioTemplate;
import cn.lyf.minio.entity.MinioObject;
import io.minio.StatObjectResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;


@RestController
@Slf4j
@RequestMapping(value = "/video")
public class VideoController {

    private static final String OBJECT_INFO_LIST = "cn:lyf:minio:media:object:info:list";


    @Autowired
    private MinioTemplate minioTemplate;

    @Resource(name = "jsonRedisTemplate")
    private RedisTemplate jsonRedisTemplate;

    
    @GetMapping(value = "/play")
    public void getVideoOutStream(HttpServletRequest request, HttpServletResponse response,
                                  @RequestParam(value = "bucketName") String bucketName,
                                  @RequestParam(value = "objectName") String objectName) {
        // 设置响应报头
        // 需要查询redis
        String key = bucketName + ":" + objectName;
        Object obj = jsonRedisTemplate.boundHashOps(OBJECT_INFO_LIST).get(key);
        MinioObject minioObject;
        if (obj == null) {
            StatObjectResponse objectInfo = minioTemplate.getObjectInfo(bucketName, objectName);

            // 存入Redis中
            if (objectInfo == null) {
                throw new IllegalArgumentException(key + "不存在");
            }

            // 判断是否是视频,是否为mp4格式
            String filenameExtension = StringUtils.getFilenameExtension(objectName);
            if (!"mp4".equalsIgnoreCase(filenameExtension)) {
                throw new IllegalArgumentException("不支持的媒体类型");
            }

            minioObject = new MinioObject();
            BeanUtils.copyProperties(objectInfo, minioObject);


            jsonRedisTemplate.boundHashOps(OBJECT_INFO_LIST).put(key, minioObject);
        } else {
            minioObject = (MinioObject) obj;
        }


        long fileSize = minioObject.getSize();
        // Accept-Ranges: bytes
        response.setHeader("Accept-Ranges", "bytes");
        //pos开始读取位置;  last最后读取位置
        long startPos = 0;
        long endPos = fileSize - 1;
        String rangeHeader = request.getHeader("Range");
        if (!ObjectUtils.isEmpty(rangeHeader) && rangeHeader.startsWith("bytes=")) {

            try {
                // 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970
                String numRang = request.getHeader("Range").replaceAll("bytes=", "");
                if (numRang.startsWith("-")) {
                    endPos = fileSize - 1;
                    startPos = endPos - Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 1,
                            numRang.length() - 1)) + 1;
                } else if (numRang.endsWith("-")) {
                    endPos = fileSize - 1;
                    startPos = Long.parseLong(new String(numRang.getBytes(StandardCharsets.UTF_8), 0,
                            numRang.length() - 1));
                } else {
                    String[] strRange = numRang.split("-");
                    if (strRange.length == 2) {
                        startPos = Long.parseLong(strRange[0].trim());
                        endPos = Long.parseLong(strRange[1].trim());
                    } else {
                        startPos = Long.parseLong(numRang.replaceAll("-", "").trim());
                    }
                }

                if (startPos < 0 || endPos < 0 || endPos >= fileSize || startPos > endPos) {
                    // SC 要求的范围不满足
                    response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return;
                }

                // 断点续传 状态码206
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            } catch (NumberFormatException e) {
                log.error(request.getHeader("Range") + " is not Number!");
                startPos = 0;
            }
        }

        // 总共需要读取的字节
        long rangLength = endPos - startPos + 1;
        response.setHeader("Content-Range", String.format("bytes %d-%d/%d", startPos, endPos, fileSize));
        response.addHeader("Content-Length", String.valueOf(rangLength));
        response.addHeader("Content-Type", "video/mp4");

        try (BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
             BufferedInputStream bis = new BufferedInputStream(
                     minioTemplate.getObject(bucketName, objectName, startPos, rangLength))) {
            IOUtils.copy(bis, bos);
        } catch (
                IOException e) {
            if (e instanceof ClientAbortException) {
                // ignore
            } else {
                log.error(e.getMessage());
            }
        }
    }
}

2.4、相关依赖代码见博客

https://blog.csdn.net/lyf_zm/article/details/124627842

3、测试使用 3.1、包结构

3.2、video.html 3.2.1、创建视频对象
// 创建视频对象
let videoObject = {
    container: '.video',//视频容器的ID
    volume: 0.8,//默认音量,范围0-1
    video: 'http://localhost:18002/video/play?bucketName=minio-test&objectName=488b4f54-a5be-4796-883c-954e0cd83742.mp4',//视频地址
};

// 调用播放器并赋值给变量player
let player = new ckplayer(videoObject)
3.2.2、完整代码



    
    ckplayer
    
    
    
    


    
播放容器

官网:www.ckplayer.com

手册:www.ckplayer.com/manual/

社区:bbs.ckplayer.com

全功能演示:www.ckplayer.com/demo.html

控制示例:

3.3、播放

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/878097.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号