浏览代码

修改视频

hexiao 2 年之前
父节点
当前提交
9287a3ebe2

+ 52 - 0
business-service/src/main/java/com/ozs/service/entity/vo/BaseCameraResVo.java

@@ -0,0 +1,52 @@
+package com.ozs.service.entity.vo;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ozs.common.annotation.Excel;
+import com.ozs.common.core.domain.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 线路和相机台账联合表
+ * </p>
+ *
+ * @author ozs
+ * @since 2023-02-17
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BaseCameraResVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 相机编码
+     */
+    @NotBlank(message = "相机编码不能为空")
+    private String cameraCode;
+
+    /**
+     * 开始时间
+     */
+    @NotEmpty(message = "开始时间不能为空")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    /**
+     * 结束时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @NotEmpty(message = "结束时间不能为空")
+    private Date entTime;
+
+}

+ 25 - 12
hazard-admin/src/main/java/com/ozs/web/controller/accountmanagment/BaseCameraManagementController.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ozs.common.config.BaseConfig;
 import com.ozs.common.core.controller.BaseController;
 import com.ozs.common.core.domain.AjaxResult;
+import com.ozs.common.exception.base.BaseException;
 import com.ozs.common.utils.StringUtils;
 import com.ozs.common.utils.file.FileUtils;
 import com.ozs.common.utils.http.HttpUtils;
@@ -14,16 +15,19 @@ import com.ozs.common.utils.poi.ExcelUtil;
 import com.ozs.service.entity.BaseCameraManagement;
 import com.ozs.service.entity.BaseDeviceDynamicManagement;
 import com.ozs.service.entity.vo.BaseCameraManagementVo;
+import com.ozs.service.entity.vo.BaseCameraResVo;
 import com.ozs.service.service.BaseCameraManagementService;
 import com.ozs.service.service.BaseDeviceDynamicManagementService;
 import com.ozs.service.service.BaseRailwayManagementService;
 import com.ozs.web.core.config.CaneraConfig;
+import com.ozs.web.core.util.CameraUtil;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.http.MediaType;
 import org.springframework.util.ObjectUtils;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -39,6 +43,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -205,19 +210,27 @@ public class BaseCameraManagementController extends BaseController {
     }
 
     @ApiOperation("查询录像")
-    @GetMapping("/api/records/{cameraCode}/{channel}")
-    public AjaxResult apiRecords(@PathVariable String cameraCode,@PathVariable String channel) {
-        String param = "id=" + cameraCode + "&channel=" + channel;
-        String s = HttpUtils.sendGet(caneraConfig.getPath() + "/gb28181/api/records", param);
-        System.out.println(s);
-        return success(HttpUtils.sendGet(caneraConfig.getPath() + "/gb28181/api/records", param));
+    @GetMapping("/api/records/{cameraCode}")
+    public AjaxResult apiRecords(@PathVariable String cameraCode) {
+        LambdaQueryWrapper<BaseCameraManagement> lw = new LambdaQueryWrapper<BaseCameraManagement>();
+        lw.eq(BaseCameraManagement::getCameraCode, cameraCode);
+        BaseCameraManagement one = baseCameraManagementService.getOne(lw);
+        if (ObjectUtils.isEmpty(one)) {
+            throw new BaseException("相机编号【" + cameraCode + "】不存在");
+        }
+        return success(CameraUtil.getPlayFlv(cameraCode, one.getChannel()));
     }
 
     @ApiOperation("播放回放")
-    @GetMapping("/api/invite/{cameraCode}/{channel}/{startTime}/{endTime}")
-    public AjaxResult apiInvite(@PathVariable String cameraCode,@PathVariable String channel,@PathVariable String startTime,@PathVariable String endTime) {
-        String param = "id="+cameraCode+"&channel="+channel+"&startTime="+startTime+"&endTime="+endTime;
-        return success(HttpUtils.sendGet(caneraConfig.getPath() + "/gb28181/api/invite/", param));
+    @PostMapping("/api/invite")
+    public AjaxResult apiInvite(@Validated @RequestBody BaseCameraResVo vo) {
+        LambdaQueryWrapper<BaseCameraManagement> lw = new LambdaQueryWrapper<BaseCameraManagement>();
+        lw.eq(BaseCameraManagement::getCameraCode, vo.getCameraCode());
+        BaseCameraManagement one = baseCameraManagementService.getOne(lw);
+        if (ObjectUtils.isEmpty(one)) {
+            throw new BaseException("相机编号【" + vo.getCameraCode() + "】不存在");
+        }
+        return success(CameraUtil.historyPlayList(one.getChannel(), vo.getStartTime(), vo.getEntTime()));
     }
 
 
@@ -241,8 +254,8 @@ public class BaseCameraManagementController extends BaseController {
     @ApiOperation("视频服务树形结构")
     @GetMapping("/cameraTree")
     @Cacheable(value = "baseAccountManagement", key = "'cameraTree'")
-    public AjaxResult cameraTree(@RequestParam(value = "name",required = false) String name) {
-     return    success(baseDeviceDynamicManagementService.cameraTree(name));
+    public AjaxResult cameraTree(@RequestParam(value = "name", required = false) String name) {
+        return success(baseDeviceDynamicManagementService.cameraTree(name));
     }
 }
 

+ 19 - 3
hazard-admin/src/main/java/com/ozs/web/core/config/CaneraConfig.java

@@ -9,10 +9,26 @@ import org.springframework.context.annotation.Configuration;
 public class CaneraConfig {
 
     /**
-     * 是否开启swagger
+     * 视频服务器访问路径
      */
-    @Value("${base.path}")
-    private String path;
+    @Value("${base.url:http://47.106.159.135:8554}")
+    private String url;
+
+    /**
+     * 视频服务器访问路径
+     */
+    @Value("${base.historyUrl:http://47.106.159.135/streams}")
+    private String historyUrl;
+    /**
+     * ffmpeg.exe路径
+     * "D:\\Java\\operSources\\ffmpeg-4.3.1\\bin\\ffmpeg.exe"
+     */
+    @Value("${base.ffmpegPath:C:\\Users\\Administrator.DESKTOP-0NUUTMM\\Downloads\\ffmpeg-5.1.2-essentials_build\\ffmpeg-5.1.2-essentials_build\\bin\\ffmpeg.exe}")
+    private String ffmpegPath;
+
+
+    @Value("${base.mappingUrl:http://47.106.159.135/}")
+    private String mappingUrl;
 
 
 }

+ 271 - 0
hazard-admin/src/main/java/com/ozs/web/core/util/CameraUtil.java

@@ -0,0 +1,271 @@
+package com.ozs.web.core.util;
+
+
+import com.alibaba.fastjson2.JSON;
+import com.ozs.common.config.BaseConfig;
+import com.ozs.common.exception.base.BaseException;
+import com.ozs.common.utils.DateUtils;
+import com.ozs.common.utils.http.HttpUtils;
+import com.ozs.framework.config.ServerConfig;
+import com.ozs.web.core.config.CaneraConfig;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+import springfox.documentation.spring.web.json.Json;
+
+import javax.annotation.PostConstruct;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 相机工具
+ */
+@Component
+public class CameraUtil {
+
+    private static String url;
+    private static String historyUrl = "http://47.106.159.135/streams";
+    private static String ffmpegPath;
+    private static String systemUrl;
+    private static String mappingUrl;
+    @Autowired
+    private CaneraConfig caneraConfig;
+    @Autowired
+    private ServerConfig serverConfig;
+
+    public static String getPlayFlv(String cameraCode, String channel) {
+        return historyUrl + "/hdl/" + channel + "/" + cameraCode + ".flv";
+    }
+
+    /**
+     * 实时播放
+     *
+     * @param cameraCode
+     * @param channel
+     * @return
+     */
+    public static String play(String cameraCode, String channel) {
+        if (StringUtils.isBlank(cameraCode) || StringUtils.isBlank(channel)) {
+            return null;
+        }
+        String param = "id=" + cameraCode + "&channel=" + channel;
+        return HttpUtils.sendGet(url + "/gb28181/api/records", param);
+    }
+
+    public static List<String> historyPlayList(String channel, Date startTm, Date endTm) {
+        if (StringUtils.isBlank(channel)
+                || ObjectUtils.isEmpty(startTm)
+                || ObjectUtils.isEmpty(endTm)) {
+            return null;
+        }
+        List<String> ls = new ArrayList<>();
+        // 调用视频服务返回参数
+        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
+        String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
+        String param = "channel=" + channel + "&startTime=" + startTime + "&endTime=" + endTime;
+        String s = HttpUtils.sendGet(historyUrl + "/api/record/flv/list", param);
+        // 视频拼接
+        if (!StringUtils.isBlank(s)) {
+            List<Map<String, Object>> maps = JSON.parseArray(s, Map.class);
+            for (Map<String, Object> map : maps) {
+                Object path = map.get("Path");
+                if (!ObjectUtils.isEmpty(path)) {
+                    ls.add(mappingUrl + path.toString());
+                }
+            }
+        }
+        return ls;
+    }
+
+    /**
+     * 历史回放
+     *
+     * @param channel
+     * @param startTm
+     * @param endTm
+     * @return
+     * @throws IOException
+     */
+    public static String historyPlay(String channel, Date startTm, Date endTm) throws IOException {
+        if (StringUtils.isBlank(channel)
+                || ObjectUtils.isEmpty(startTm)
+                || ObjectUtils.isEmpty(endTm)) {
+            return null;
+        }
+        // 调用视频服务返回参数
+        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
+        String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, startTm);
+        String param = "channel=" + channel + "&startTime=" + startTime + "&endTime=" + endTime;
+        String s = HttpUtils.sendGet(historyUrl + "/api/record/flv/list", param);
+
+        // 视频拼接
+        if (!StringUtils.isBlank(s)) {
+            List<Map<String, Object>> maps = JSON.parseArray(s, Map.class);
+            // 视频服务映射路径
+            String NewfilePath = BaseConfig.getProfile() + "/" + channel + "/" + startTime + "/" + endTime + ".flv";
+            List<String> fromVideoFileList = new ArrayList();
+            for (Map<String, Object> map : maps) {
+                Object path = map.get("Path");
+                if (!ObjectUtils.isEmpty(path)) {
+                    fromVideoFileList.add(mappingUrl + path);
+                }
+            }
+            convetor(fromVideoFileList, NewfilePath);
+            return systemUrl + "/profile" + "/" + channel + "/" + startTime + "/" + endTime + ".flv";
+        }
+        // http://47.106.159.135/record/flv/34020000001320000002/20230304_183122_183222-d98df13f-ba77-11ed-aeb9-00163e06a5f3.flv
+        return null;
+    }
+
+    /**
+     * * 参数:
+     * **List<String> fromVideoFileList 需要合并的多视频url地址以List存放**
+     * **String ffmpeg 此处是ffmpeg 配置地址,可写死如“E:/ffmpeg/bin/ffmpeg.exe”**
+     * **String NewfilePath 合并后的视频存放地址,如:E:/mergevideo.mp4***
+     */
+    public static void convetor(List<String> fromVideoFileList,
+                                String NewfilePath) throws IOException {
+        new Thread(
+                () -> {
+                    try {
+                        List<String> voidTS = new ArrayList<>();
+                        Process process = null;
+                        ProcessBuilder builder = null;
+                        List<String> command = null;
+                        for (int i = 0; i < fromVideoFileList.size(); i++) {
+                            String fromVideoFile = fromVideoFileList.get(i);
+                            command = new ArrayList<String>();
+                            command.add(ffmpegPath);
+                            command.add("-y");
+                            command.add("-i");
+                            command.add(fromVideoFile);
+                            command.add("-vcodec");
+                            command.add("copy");
+                            command.add("-bsf:v");
+                            command.add("h264_mp4toannexb");
+                            command.add("-f");
+                            command.add("mpegts");
+                            command.add(fromVideoFile.substring(0,
+                                    fromVideoFile.lastIndexOf(".")) + ".ts");
+                            builder = new ProcessBuilder(command);
+                            voidTS.add(fromVideoFile.substring(0,
+                                    fromVideoFile.lastIndexOf("."))
+                                    + ".ts");
+                            try {
+                                process = builder.start();
+                                InputStream errorStream = process
+                                        .getErrorStream();
+                                InputStreamReader inputStreamReader = new InputStreamReader(
+                                        errorStream);
+                                BufferedReader br = new BufferedReader(
+                                        inputStreamReader);
+                                String line = "";
+                                StringBuffer sb = new StringBuffer();
+                                while ((line = br.readLine()) != null) {
+                                    sb.append(line);
+                                }
+                                String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
+                                Pattern pattern = Pattern
+                                        .compile(regexDuration);
+                                Matcher m = pattern.matcher(sb.toString());
+                                System.out.println(sb.toString());
+                                br.close();
+                                inputStreamReader.close();
+                                errorStream.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        List<String> dos = new ArrayList<>();
+                        StringBuffer tsPath = new StringBuffer();
+                        tsPath.append(ffmpegPath);
+                        tsPath.append(" -i ");
+                        tsPath.append("concat:");
+                        for (int t = 0; t < voidTS.size(); t++) {
+                            if (t != voidTS.size() - 1) {
+                                tsPath.append(voidTS.get(t) + "|");
+                            } else {
+                                tsPath.append(voidTS.get(t));
+                            }
+                        }
+                        tsPath.append(" -vcodec ");
+                        tsPath.append(" copy ");
+                        tsPath.append(" -bsf:a ");
+                        tsPath.append(" aac_adtstoasc ");
+                        tsPath.append(" -movflags ");
+                        tsPath.append(" +faststart ");
+                        tsPath.append(NewfilePath);
+                        Process pr = Runtime.getRuntime().exec(
+                                tsPath.toString());
+                        process.getInputStream();
+                        pr.getOutputStream().close();
+                        pr.getInputStream().close();
+                        pr.getErrorStream().close();
+                        try {
+                            pr.waitFor();
+                            Thread.sleep(1000);
+                            pr.destroy();
+                        } catch (InterruptedException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                        //删除生成的ts文件
+                        for (String filePath : voidTS) {
+                            File file = new File(filePath);
+                            file.delete();
+                            pr.destroy();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }).start();
+    }
+
+    //工具类
+
+    public static void queryRecords(String cameraCode, String channel, Date startTm, Date endTm) {
+        if (StringUtils.isBlank(cameraCode)
+                || StringUtils.isBlank(channel)
+                || ObjectUtils.isEmpty(startTm)
+                || ObjectUtils.isEmpty(endTm)) {
+            throw new BaseException("参数为空");
+        }
+        String param = "id=" + cameraCode + "&channel=" + channel + "&startTime=" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startTm) + "&endTm=" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endTm);
+        String s = HttpUtils.sendGet(historyUrl + "/api/gb28181/query/records", param);
+        System.out.println(s);
+    }
+
+    public static void main(String[] args) throws IOException {
+
+
+//        historyPlay("34020000001320000002", "2023-03-03", "2023-03-04");
+//        String s = "record/flv/34020000001320000002/20230304_211304_211404-70a2dff9-ba8e-11ed-aeb9-00163e06a5f3.flv";
+//        int i = s.lastIndexOf("/");
+//        String substring = s.substring(i + 1, s.length());
+//        String substring1 = substring.substring(0, substring.indexOf("-"));
+//        String[] s1 = substring1.split("_");
+//        System.out.println(s1.length);
+//        for (String s2 : s1) {
+//            System.out.println(s2);
+//        }
+//        Date backupTime=DateUtils.addDays(new Date(), -1);
+//        queryRecords("34020000001320000002","34020000001320000002",backupTime,DateUtils.getNowDate());
+        System.out.println(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
+    }
+
+    @PostConstruct
+    public void init() {
+        url = caneraConfig.getUrl();
+        mappingUrl = caneraConfig.getMappingUrl();
+        historyUrl = caneraConfig.getHistoryUrl();
+        ffmpegPath = caneraConfig.getFfmpegPath();
+        systemUrl = serverConfig.getUrl();
+    }
+
+}

+ 1 - 0
hazard-admin/src/main/resources/application.yml

@@ -16,6 +16,7 @@ base:
   captchaType: math
 #  path: http://47.106.159.135:8554
   path: http://47.106.159.135:8554
+  ffmpegPath: C:\Users\Administrator.DESKTOP-0NUUTMM\Downloads\ffmpeg-5.1.2-essentials_build\ffmpeg-5.1.2-essentials_build\bin\ffmpeg.exe
 
 # 开发环境配置
 server: