Pārlūkot izejas kodu

完成基础功能开发

liyuntian 10 mēneši atpakaļ
vecāks
revīzija
a8d34f8c5b

+ 80 - 0
mcp/src/main/java/com/chuanxia/mcp/bean/model/VideoM3u8.java

@@ -0,0 +1,80 @@
+package com.chuanxia.mcp.bean.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@TableName("video_m3u8")
+@Data
+public class VideoM3u8 {
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("video_id")
+    private String videoId;
+    @TableField("resolution")
+    private String resolution;
+    @TableField("bandwidth")
+    private String bandwidth;
+
+    @TableField("version")
+    @JsonProperty("VERSION")
+    private String VERSION;
+
+    @TableField("targetduration")
+    @JsonProperty("TARGETDURATION")
+    private String TARGETDURATION;
+
+    @TableField("sequence")
+    @JsonProperty("SEQUENCE")
+    private String SEQUENCE;
+
+    @TableField("type")
+    @JsonProperty("TYPE")
+    private String TYPE;
+
+    @TableField("extinf")
+    @JsonProperty("EXTINF")
+    private String EXTINF;
+
+
+    @TableField("ts_last_time")
+    @JsonProperty("TS_LAST_TIME")
+    private String TS_LAST_TIME;
+
+    @TableField("prefix_path")
+    @JsonProperty("PREFIX_PATH")
+    private String PREFIX_PATH;
+
+    @TableField("ts_start")
+    @JsonProperty("TS_START")
+    private String TS_START;
+
+    @TableField("ts_end")
+    @JsonProperty("TS_END")
+    private String TS_END;
+
+    @TableField("ts_name")
+    @JsonProperty("TS_NAME")
+    private String TS_NAME;
+
+    @TableField("iv")
+    @JsonProperty("IV")
+    private String IV;
+
+    @JsonProperty("KEY")
+    @TableField("`key`")
+    private String KEY;
+
+    @JsonProperty("TS_LIST")
+    private List<VideoTs> TS_LIST;
+
+    @TableField("ts_list")
+    private String tsListStr;
+}

+ 14 - 0
mcp/src/main/java/com/chuanxia/mcp/bean/model/VideoTs.java

@@ -0,0 +1,14 @@
+package com.chuanxia.mcp.bean.model;
+
+import lombok.Data;
+
+/**
+ * m3u8中ts解析对象
+ *
+ * @author Administrator
+ */
+@Data
+public class VideoTs {
+    private String name;
+    private String time;
+}

+ 27 - 0
mcp/src/main/java/com/chuanxia/mcp/bean/vo/TsArrIsOrderVo.java

@@ -0,0 +1,27 @@
+package com.chuanxia.mcp.bean.vo;
+
+import com.chuanxia.mcp.bean.model.VideoTs;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ts数组是否是自然排序,如果是,则包含开始下标,结束下标,ts文件名
+ *
+ * @author Administrator
+ */
+@Data
+public class TsArrIsOrderVo {
+    /**
+     * true代表自然排序,false代表不规则
+     */
+    private boolean order;
+    private String tsStart;
+    private String tsEnd;
+    private String tsName;
+    private String extinf;
+    private String tsLastTime;
+
+    private List<VideoTs> videoTs;
+}

+ 10 - 1
mcp/src/main/java/com/chuanxia/mcp/controller/CdnDomainController.java

@@ -16,6 +16,7 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.List;
 
@@ -63,8 +64,16 @@ public class CdnDomainController {
     public Result getCdnByVideoId(@RequestParam("videoId") String videoId,
                                   @RequestParam(value = "internetSpeed", required = false, defaultValue = "120") BigDecimal internetSpeed,
                                   @RequestParam(value = "operatorName", defaultValue = "", required = false) String operatorName,
+                                  @RequestParam(value = "type", required = false, defaultValue = "") String type,
                                   HttpServletRequest request) {
-        return doaminService.getCdnByVideoId(videoId, internetSpeed, operatorName, request);
+        return doaminService.getCdnByVideoId(videoId, internetSpeed, operatorName, type, request);
     }
 
+    @GetMapping("downLoadM3u8File")
+    @ApiOperation("根据m3u8id,下载对应播放m3u8地址")
+    public Result downLoadM3u8File(@RequestParam("cdn") String cdn,
+                                   @RequestParam("id") Integer id,
+                                   HttpServletResponse response) {
+        return doaminService.downLoadM3u8File(cdn,id,response);
+    }
 }

+ 10 - 3
mcp/src/main/java/com/chuanxia/mcp/controller/CdnM3u8Controller.java

@@ -1,7 +1,9 @@
 package com.chuanxia.mcp.controller;
 
+import com.chuanxia.mcp.bean.model.VideoM3u8;
 import com.chuanxia.mcp.bean.vo.Result;
 import com.chuanxia.mcp.sched.M3U8Utils;
+import com.chuanxia.mcp.service.VideoM3u8Service;
 import io.swagger.annotations.Api;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -9,16 +11,21 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 @RestController
 @Api("m3u8")
 @RequestMapping("cdnM3U8")
 @RequiredArgsConstructor
 public class CdnM3u8Controller {
     private final M3U8Utils m3U8Utils;
+    private final VideoM3u8Service m3u8Service;
 
     @GetMapping("test")
-    public Result test(@RequestParam("url")String url,@RequestParam("videoId")String videoId) {
-        String s = m3U8Utils.downloadM3U8(url, videoId);
-        return Result.success(s);
+    public Result test(@RequestParam("baseUrl") String url,
+                       @RequestParam("videoId") String videoId) {
+        List<VideoM3u8> videoM3u8s = m3U8Utils.downloadM3U8(url, videoId);
+        m3u8Service.saveBatch(videoM3u8s);
+        return Result.success("操作成功");
     }
 }

+ 3 - 1
mcp/src/main/java/com/chuanxia/mcp/exception/GlobalExceptionHandler.java

@@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
 
 /**
  * 全局异常处理
+ *
  * @author liyuntian
  */
 @ControllerAdvice
@@ -16,6 +17,7 @@ public class GlobalExceptionHandler {
     @ResponseBody
     @ExceptionHandler(ResultException.class)
     public Result handleCustomException(ResultException e) {
+        e.printStackTrace();
         log.error("进入了业务异常全局异常捕获,异常原因:{}", e.getMessage());
         return Result.error(e.getCode(), e.getMessage());
     }
@@ -25,7 +27,7 @@ public class GlobalExceptionHandler {
     public Result exceptionCatch(Exception e) {
         e.printStackTrace();
         log.error("系统发生异常,异常原因:{}", e.getMessage());
-        return Result.error(500, "系统发生异常,原因:"+e.getMessage());
+        return Result.error(500, "系统发生异常,原因:" + e.getMessage());
     }
 }
 

+ 9 - 0
mcp/src/main/java/com/chuanxia/mcp/mapper/VideoM3u8Mapper.java

@@ -0,0 +1,9 @@
+package com.chuanxia.mcp.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.chuanxia.mcp.bean.model.VideoM3u8;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface VideoM3u8Mapper extends BaseMapper<VideoM3u8> {
+}

+ 326 - 13
mcp/src/main/java/com/chuanxia/mcp/sched/M3U8Utils.java

@@ -1,5 +1,12 @@
 package com.chuanxia.mcp.sched;
 
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSON;
+import com.chuanxia.mcp.bean.model.VideoM3u8;
+import com.chuanxia.mcp.bean.model.VideoTs;
+import com.chuanxia.mcp.bean.vo.TsArrIsOrderVo;
+import com.chuanxia.mcp.exception.ResultException;
+import com.chuanxia.mcp.service.VideoM3u8Service;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
@@ -7,9 +14,13 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
-import java.io.*;
-import java.nio.file.Files;
-import java.util.Objects;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @Slf4j
 @Component
@@ -17,27 +28,329 @@ import java.util.Objects;
 public class M3U8Utils {
 
     private final RestTemplate restTemplate;
+    private final VideoM3u8Service m3u8Service;
 
     @Value("${m3u8.downLoadPath}")
     private String downLoadPath;
     @Value("${m3u8.tsDownLoadPath}")
     private String tsDownLoadPath;
+    private Pattern pattern = Pattern.compile("\\d+");
 
     /**
-     * 下载m3u8文件,包含key的下载地址(如果有) 和 ts文件名
+     * 下载m3u8文件,解析ts
+     *
+     * @param videoId 视频id
+     * @return video对象
      */
-    public String downloadM3U8(String url, String videoId) {
-        log.info("-- 开始下载 m3u8 --");
-        ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(url, byte[].class);
-        //log.info("m3u8 内容 = {}", new String(forEntity.getBody()));
-        String m3u8Path = downLoadPath + videoId + ".m3u8";
-        File file = new File(m3u8Path);
+    public List<VideoM3u8> downloadM3U8(String baseUrl, String videoId) {
+        ArrayList<VideoM3u8> result = new ArrayList<>();
+        String fileName = "";
+        String uri = "";
+        String url = "";
         try {
-            Files.write(file.toPath(), Objects.requireNonNull(forEntity.getBody(), "未获取到文件"));
-        } catch (IOException e) {
-            e.printStackTrace();
+            URI baseUri = new URI(baseUrl);
+            String scheme = baseUri.getScheme();
+            url = scheme + "://" + baseUri.getHost();
+            String path = baseUri.getPath();
+            uri = path.substring(0, path.lastIndexOf("/") + 1);
+            fileName = path.substring(path.lastIndexOf("/") + 1);
+        } catch (URISyntaxException e) {
+            log.info("解析客户服务器地址失败,原因:{}", e.getMessage());
+        }
+        String m3u8Str = m3u8ToString(fileName, url + uri);
+        String resolutionRatio = "1280x720";
+        String bandwidth = "2400000";
+        String[] m3u8Arr = m3u8Str.split("\n");
+        if (m3u8Arr.length > 0) {
+            //判断当前m3U8是单码文件还是多码文件
+            String endData = m3u8Arr[m3u8Arr.length - 1];
+            log.info("当前m3u8最后结尾内容:{}", endData);
+            if (endData.endsWith("#EXT-X-ENDLIST")) {
+                //当前m3u8文件是单码文件,直接解析,入库
+                VideoM3u8 videoM3u8 = analysisM3u8(url + uri + fileName, m3u8Str, resolutionRatio, bandwidth, videoId, url, uri);
+                result.add(videoM3u8);
+            } else {
+                for (int i = 0; i < m3u8Arr.length; i++) {
+                    String m3u8StreamStr = m3u8Arr[i];
+                    //判断当前行是否是分辨率
+                    if (m3u8StreamStr.contains("#EXT-X-STREAM-INF")) {
+                        String[] split = m3u8StreamStr.split(",");
+                        if (split.length >= 2) {
+                            String resolutionRatioStr = split[1];
+                            //bandwidth
+                            if (resolutionRatioStr.contains("RESOLUTION=")) {
+                                String[] resolutionArr = resolutionRatioStr.split("RESOLUTION=");
+                                resolutionRatio = resolutionArr[1];
+                            }
+                        }
+                        if (split[0].contains("BANDWIDTH")) {
+                            bandwidth = split[0].split("BANDWIDTH=")[1];
+                        }
+                        //是分辨率头文件,获取下一行.m3u8地址,可能是http完整地址,可能是相对路径
+                        String m3u8RadioUrl = m3u8Arr[i + 1];
+                        String nextM3u8Url;
+                        String nextM3u8FileName;
+                        if (m3u8RadioUrl.startsWith("http")) {
+                            //完整链接,直接去获取m3u8
+                            nextM3u8Url = m3u8RadioUrl;
+                            nextM3u8FileName = nextM3u8Url.substring(nextM3u8Url.lastIndexOf("/") + 1);
+                        } else {
+                            nextM3u8Url = url + uri;
+                            nextM3u8FileName = m3u8RadioUrl;
+                        }
+                        String nextM3U8FileStr = m3u8ToString(nextM3u8FileName, nextM3u8Url);
+                        VideoM3u8 videoM3u8 = analysisM3u8(nextM3u8Url + nextM3u8FileName, nextM3U8FileStr, resolutionRatio, bandwidth, videoId, url, uri);
+                        result.add(videoM3u8);
+                    }
+                }
+            }
+
+        }
+        return result;
+    }
+
+    /**
+     * 获取m3u8文件内容
+     *
+     * @param fileName 文件名
+     * @param url      地址
+     * @return 文件内容
+     */
+    private String m3u8ToString(String fileName, String url) {
+        StringBuilder fileUrl = new StringBuilder();
+        fileUrl.append(url);
+        fileUrl.append(fileName);
+        log.info("开始去下载m3u8文件,当前url:{},文件名:{}", fileUrl.toString(), fileName);
+        ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(fileUrl.toString(), byte[].class);
+        if (forEntity.getBody() == null) {
+            throw new ResultException(500, "没有获取到对应m3u8文件");
         }
         return new String(forEntity.getBody());
     }
 
+    /**
+     * 解析当前m3u8文件
+     *
+     * @param m3u8Url         m3u8文件下载地址
+     * @param m3u8Content     文件内容
+     * @param resolutionRatio 分辨率
+     * @param bandwidth       码率
+     * @param videoId         videoId
+     * @param url             请求域名
+     * @param uri             相对路径
+     * @return m3u8对象
+     */
+    private VideoM3u8 analysisM3u8(String m3u8Url, String m3u8Content, String resolutionRatio, String bandwidth, String videoId, String url, String uri) {
+        //开始解析m3u8文件
+        String[] split = m3u8Content.split("\n");
+        VideoM3u8 m3u8 = new VideoM3u8();
+        m3u8.setVideoId(videoId);
+        m3u8.setBandwidth(bandwidth);
+        m3u8.setResolution(resolutionRatio);
+        m3u8.setSEQUENCE("0");
+
+        //开始封装组合数据入库
+        int i = 0;
+        List<VideoTs> tsList = new ArrayList<>(split.length);
+        for (String data : split) {
+            if (data.contains("#EXT-X-VERSION")) {
+                //版本
+                m3u8.setVERSION(data.split(":")[1]);
+            } else if (data.contains("#EXT-X-TARGETDURATION")) {
+                //分片最大时长
+                m3u8.setTARGETDURATION(data.split(":")[1]);
+            } else if (data.contains("#EXT-X-MEDIA-SEQUENCE")) {
+                //播放最开始下标
+                m3u8.setSEQUENCE(data.split(":")[1]);
+            } else if (data.contains("#EXT-X-PLAYLIST-TYPE:")) {
+                //播放类型
+                m3u8.setTYPE(data.split(":")[1]);
+            } else if (data.contains("#EXT-X-KEY:METHOD")) {
+                if (data.contains("URI")) {
+                    for (String s : data.split(",")) {
+                        if (s.contains("URI=")) {
+                            String keyUrl = s.split("URI=")[1].replaceAll("\"", "");
+                            if (keyUrl.contains("http")) {
+                                ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(keyUrl, byte[].class);
+                                String key = Base64.getEncoder().encodeToString(forEntity.getBody());
+                                m3u8.setKEY(key);
+                            } else {
+                                //如果key是相对路径,就拼接地址,获取key地址
+                                ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(url + uri + keyUrl, byte[].class);
+                                String key = Base64.getEncoder().encodeToString(forEntity.getBody());
+                                m3u8.setKEY(key);
+                            }
+                        }
+                    }
+                }
+                //IV,key
+                m3u8.setIV(data.split("IV=")[1]);
+            } else if (data.contains("#EXTINF")) {
+                //分片时间
+                String extinf = data.split(":")[1].replaceAll(",", "");
+                //ts
+                String tsName = split[i + 1];
+                VideoTs videoTs = new VideoTs();
+                videoTs.setTime(extinf);
+                videoTs.setName(tsName);
+                tsList.add(videoTs);
+            }
+            i++;
+        }
+        if (CollectionUtil.isNotEmpty(tsList)) {
+            int listSize = 2;
+            TsArrIsOrderVo orderVo = checkIsOrder(tsList);
+            //判断当前ts是绝对路径还是相对路径,如果是绝对路径,则不再设置path
+            VideoTs videoTs = tsList.get(0);
+            String name = videoTs.getName();
+            if (!name.contains("http")) {
+                try {
+                    URI m3u8Uri = new URI(m3u8Url);
+                    String path = m3u8Uri.getPath();
+                    path = path.substring(0, path.lastIndexOf("/") + 1);
+                    m3u8.setPREFIX_PATH(path);
+                } catch (URISyntaxException e) {
+                    log.error("获取当前m3u8所在相对路径失败,原因:{}", e.getMessage());
+                }
+            }
+            if (tsList.size() >= listSize) {
+                if (orderVo.isOrder()) {
+                    //是自然排序,设置值
+                    m3u8.setTS_START(orderVo.getTsStart());
+                    m3u8.setTS_END(orderVo.getTsEnd());
+                    m3u8.setEXTINF(orderVo.getExtinf());
+                    m3u8.setTS_LAST_TIME(orderVo.getTsLastTime());
+                    m3u8.setTS_NAME(orderVo.getTsName());
+                } else {
+                    //不是自然排序,设置arr
+                    m3u8.setTsListStr(JSON.toJSONString(orderVo.getVideoTs()));
+                }
+            } else {
+                //ts数组长度小于2,直接设置入库
+                m3u8.setTsListStr(JSON.toJSONString(tsList));
+            }
+
+        }
+        return m3u8;
+    }
+
+
+    /**
+     * 比较两个ts文件是否按照自然排序规则
+     *
+     * @param tsList ts数组
+     * @return true表示按规则排序, false表示无规则
+     */
+    private TsArrIsOrderVo checkIsOrder(List<VideoTs> tsList) {
+
+        VideoTs first = tsList.get(0);
+        VideoTs last = tsList.get(tsList.size() - 1);
+        String firstName = first.getName();
+        firstName = firstName.split("\\.")[0];
+        String lastName = last.getName();
+        lastName = lastName.split("\\.")[0];
+
+        TsArrIsOrderVo orderVo = new TsArrIsOrderVo();
+        //判断里面每一个ts时间是否固定(去除最后一条)
+
+        //每循环一次,用第一次的时间跟下一次时间做比较
+        String lastExtinfTime = "";
+        for (int i = 0; i < tsList.size() - 1; i++) {
+            VideoTs videoTs = tsList.get(i);
+            if (i == 0) {
+                lastExtinfTime = videoTs.getTime();
+            } else {
+                if (!lastExtinfTime.equals(videoTs.getTime())) {
+                    orderVo.setOrder(false);
+                    orderVo.setVideoTs(tsList);
+                    return orderVo;
+                }
+            }
+        }
+        int size = tsList.size();
+        String numberMatcher = "[0-9]+";
+        //开头数字,结尾字符串,直接false
+        if (firstName.matches(numberMatcher) && !lastName.matches(numberMatcher)) {
+            orderVo.setOrder(false);
+            orderVo.setVideoTs(tsList);
+            return orderVo;
+        }
+        //开头字符串,结尾数字,直接false
+        if (!firstName.matches(numberMatcher) && lastName.matches(numberMatcher)) {
+            orderVo.setOrder(false);
+            orderVo.setVideoTs(tsList);
+            return orderVo;
+        }
+        //两边都是数字,看看是不是自然排序
+        if (firstName.matches(numberMatcher) && lastName.matches(numberMatcher)) {
+            //长度+首数-1=尾数
+
+            if (Long.parseLong(firstName) + size - 1 != Long.parseLong(lastName)) {
+                orderVo.setOrder(false);
+                orderVo.setVideoTs(tsList);
+                return orderVo;
+            }
+        }
+        // 匹配一个或多个数字
+        Matcher firstMatcher = pattern.matcher(firstName);
+        Matcher lastMatcher = pattern.matcher(lastName);
+        ArrayList<String> firstArr = new ArrayList<>();
+        ArrayList<String> lastArr = new ArrayList<>();
+        while (firstMatcher.find()) {
+            String number = firstMatcher.group();
+            firstArr.add(number);
+        }
+        while (lastMatcher.find()) {
+            String number = lastMatcher.group();
+            lastArr.add(number);
+        }
+        if (firstArr.size() != lastArr.size()) {
+            //数字切割分组长度不一致,直接false
+            orderVo.setOrder(false);
+            orderVo.setVideoTs(tsList);
+            return orderVo;
+        } else {
+            //长度一致,判断数字是不是自然排序
+            String firstNum = "";
+            String lastNum = "";
+            int count = 0;
+            //记录一下不一致的下标
+            int inconsistentIndex = 0;
+            for (int i = 0; i < firstArr.size(); i++) {
+                if (!firstArr.get(i).equals(lastArr.get(i))) {
+                    count++;
+                    firstNum = firstArr.get(i);
+                    lastNum = lastArr.get(i);
+                    inconsistentIndex = i;
+                }
+            }
+            if (count > 1) {
+                //出现不相等的数字次数大于1
+                orderVo.setOrder(false);
+                orderVo.setVideoTs(tsList);
+                return orderVo;
+            }
+            String tsName = firstName.substring(0, firstName.indexOf(firstNum, inconsistentIndex));
+            String substring = tsName + (Integer.parseInt(firstNum) + size - 1);
+            lastName = lastName.substring(0, lastName.indexOf(lastNum, inconsistentIndex)) + (Integer.parseInt(lastNum));
+            if (substring.equals(lastName)) {
+                tsName = tsName + "{num}.ts";
+                //规则匹配
+                orderVo.setOrder(true);
+                //分片时间
+                orderVo.setExtinf(lastExtinfTime);
+                //最后一次分片时间
+                orderVo.setTsLastTime(last.getTime());
+                orderVo.setTsStart(firstNum);
+                orderVo.setTsEnd(lastNum);
+                orderVo.setTsName(tsName);
+            } else {
+                orderVo.setOrder(false);
+                orderVo.setVideoTs(tsList);
+                return orderVo;
+            }
+            return orderVo;
+        }
+    }
+
 }

+ 4 - 1
mcp/src/main/java/com/chuanxia/mcp/service/CdnDoaminService.java

@@ -8,6 +8,7 @@ import com.chuanxia.mcp.bean.model.CdnDomain;
 import com.chuanxia.mcp.bean.vo.Result;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 
 public interface CdnDoaminService extends IService<CdnDomain> {
@@ -19,5 +20,7 @@ public interface CdnDoaminService extends IService<CdnDomain> {
 
     Result<String> updateDomain(CdnDomain domain);
 
-    Result getCdnByVideoId(String videoId, BigDecimal internetSpeed, String operatorName, HttpServletRequest request);
+    Result getCdnByVideoId(String videoId, BigDecimal internetSpeed, String operatorName, String type, HttpServletRequest request);
+
+    Result downLoadM3u8File(String cdn, Integer id, HttpServletResponse response);
 }

+ 7 - 0
mcp/src/main/java/com/chuanxia/mcp/service/VideoM3u8Service.java

@@ -0,0 +1,7 @@
+package com.chuanxia.mcp.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chuanxia.mcp.bean.model.VideoM3u8;
+
+public interface VideoM3u8Service extends IService<VideoM3u8> {
+}

+ 45 - 8
mcp/src/main/java/com/chuanxia/mcp/service/impl/CdnDoaminServiceImpl.java

@@ -1,6 +1,7 @@
 package com.chuanxia.mcp.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -29,6 +30,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.*;
 
@@ -47,6 +49,7 @@ public class CdnDoaminServiceImpl extends ServiceImpl<CdnDomainMapper, CdnDomain
     private final CdnDomainCityMapper domainCityMapper;
     private final CdnDomainTimeRuleMapper domainTimeRuleMapper;
     private final CdnCityMapper cityMapper;
+    private final VideoM3u8Mapper m3u8Mapper;
 
     @Override
     public Result<IPage<CdnDomain>> listPage(DomainQueryDto queryDto) {
@@ -135,8 +138,7 @@ public class CdnDoaminServiceImpl extends ServiceImpl<CdnDomainMapper, CdnDomain
     }
 
     @Override
-    public Result getCdnByVideoId(String videoId, BigDecimal internetSpeed, String operatorName, HttpServletRequest request) {
-
+    public Result getCdnByVideoId(String videoId, BigDecimal internetSpeed, String operatorName, String type, HttpServletRequest request) {
         //根据ip获取归属地
         String requestIp = IpUtil.getRequestIp(request);
         try {
@@ -180,22 +182,57 @@ public class CdnDoaminServiceImpl extends ServiceImpl<CdnDomainMapper, CdnDomain
                     level = countLevel(level, internetSpeed);
                     if (DeviceUaLevel.HIGH.getLevel().equals(level)) {
 
-                        ratio = "1980*1080";
+                        ratio = "1980x1080";
                     } else if (DeviceUaLevel.MEDIUM.getLevel().equals(level)) {
-                        ratio = "1280*720";
+                        ratio = "1280x720";
                     } else if (DeviceUaLevel.LOW.getLevel().equals(level)) {
-                        ratio = "1024*768";
+                        ratio = "1024x768";
                     }
                 }
-                String m3u8Url = cdnDomain.getDomain() + "/" + ratio;
-
-                return Result.success(m3u8Url);
+                LambdaQueryWrapper<VideoM3u8> m3u8Query = Wrappers.lambdaQuery();
+                m3u8Query.eq(VideoM3u8::getVideoId, videoId);
+                List<VideoM3u8> videoM3u8s = m3u8Mapper.selectList(m3u8Query);
+                if (CollectionUtil.isEmpty(videoM3u8s)) {
+                    throw new ResultException(500, "当前videoId没有找到对应视频");
+                }
+                VideoM3u8 m3u8 = null;
+                for (VideoM3u8 videoM3u8 : videoM3u8s) {
+                    if (ratio.equals(videoM3u8.getResolution())) {
+                        m3u8 = videoM3u8;
+                        break;
+                    }
+                }
+                if (m3u8 == null) {
+                    m3u8 = videoM3u8s.get(0);
+                }
+                if (!StringUtils.isBlank(type)) {
+                    String downLoadFileUrl = "http://192.168.1.134:8088/api?cdn=" + cdnDomain.getDomain() + "&id=" + m3u8.getId();
+                    throw new ResultException(888, downLoadFileUrl);
+                }
+                String tsListStr = m3u8.getTsListStr();
+                if (!StringUtils.isBlank(tsListStr)) {
+                    List<VideoTs> tsList = JSON.parseArray(tsListStr, VideoTs.class);
+                    m3u8.setTS_LIST(tsList);
+                    String prefixPath = m3u8.getPREFIX_PATH();
+                    if (StringUtils.isNotBlank(prefixPath)) {
+                        m3u8.setPREFIX_PATH(cdnDomain.getDomain() + m3u8.getPREFIX_PATH());
+                    }
+                    m3u8.setTsListStr("");
+                } else {
+                    m3u8.setPREFIX_PATH(cdnDomain.getDomain() + m3u8.getPREFIX_PATH());
+                }
+                return Result.success(m3u8);
             } else {
                 throw new ResultException(500, "根据ip地址获取城市信息失败");
             }
         } catch (Exception e) {
             e.printStackTrace();
+            throw new ResultException(500, e.getMessage());
         }
+    }
+
+    @Override
+    public Result downLoadM3u8File(String cdn, Integer id, HttpServletResponse response) {
         return null;
     }
 

+ 15 - 0
mcp/src/main/java/com/chuanxia/mcp/service/impl/VideoM3u8ServiceImpl.java

@@ -0,0 +1,15 @@
+package com.chuanxia.mcp.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chuanxia.mcp.bean.model.VideoM3u8;
+import com.chuanxia.mcp.mapper.VideoM3u8Mapper;
+import com.chuanxia.mcp.service.VideoM3u8Service;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class VideoM3u8ServiceImpl extends ServiceImpl<VideoM3u8Mapper, VideoM3u8> implements VideoM3u8Service {
+}

+ 1 - 0
mcp/src/main/resources/application-local.yml

@@ -7,6 +7,7 @@ spring:
 mybatis-plus:
   configuration:
     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    map-underscore-to-camel-case: false
 m3u8:
   downLoadPath: D:\\m3u8Download
   tsDownLoadPath: D:\\m3u8TsDownLoad