|
@@ -0,0 +1,299 @@
|
|
|
+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.web.core.config.CaneraConfig;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.ObjectUtils;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.io.*;
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 相机工具
|
|
|
+ */
|
|
|
+@Component
|
|
|
+@Slf4j
|
|
|
+public class CameraUtil {
|
|
|
+
|
|
|
+ private static String url;
|
|
|
+ private static String historyUrl;
|
|
|
+ private static String ffmpegPath;
|
|
|
+ private static String mappingUrl;
|
|
|
+ @Autowired
|
|
|
+ private CaneraConfig caneraConfig;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 历史回放
|
|
|
+ *
|
|
|
+ * @param fromVideoFileList
|
|
|
+ * @param ph
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static String historyPlay(List<String> fromVideoFileList, String ph) throws IOException {
|
|
|
+ // 视频服务映射路径
|
|
|
+ String NewfilePath = BaseConfig.getProfile() + ph;
|
|
|
+ log.info("NewfilePath:{}", NewfilePath);
|
|
|
+ log.info("fromVideoFileList:{}", fromVideoFileList);
|
|
|
+ convetor(fromVideoFileList, NewfilePath);
|
|
|
+ return "/profile" + ph;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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, endTm);
|
|
|
+ String ph = "/flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date())
|
|
|
+ + "/" + channel + "/" + startTime + "/" + endTime + "/"
|
|
|
+ + UUID.randomUUID().toString() + ".flv";
|
|
|
+ String param = "channel=" + channel + "&startTime=" + startTime + "&endTime=" + endTime;
|
|
|
+ String s = HttpUtils.sendGet(historyUrl + "/api/record/flv/list", param);
|
|
|
+ // 视频拼接
|
|
|
+ if (!StringUtils.isBlank(s) || "null".equals(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)) {
|
|
|
+ String s1 = path.toString();
|
|
|
+ String substring = s1.substring(s1.lastIndexOf("/") + 1, s1.length());
|
|
|
+ String substring1 = substring.substring(0, substring.indexOf("-"));
|
|
|
+ String[] s2 = substring1.split("_");
|
|
|
+ if (!ObjectUtils.isEmpty(s2)) {
|
|
|
+ String s3 = s2[0] + s2[1];
|
|
|
+ String s4 = s2[0] + s2[2];
|
|
|
+ Date sdate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s3);
|
|
|
+ Date edate = DateUtils.dateTime(DateUtils.YYYYMMDDHHMMSS, s4);
|
|
|
+ /* s | e | */
|
|
|
+ if (startTm.compareTo(sdate) <= 0 && endTm.compareTo(edate) > 0) {
|
|
|
+ ls.add(mappingUrl + path.toString());
|
|
|
+
|
|
|
+ /* | s e | */
|
|
|
+ } else if (startTm.compareTo(sdate) >= 0 && endTm.compareTo(edate) <= 0) {
|
|
|
+ ls.add(mappingUrl + path.toString());
|
|
|
+
|
|
|
+ /* | s | e */
|
|
|
+ } else if (startTm.compareTo(sdate) >= 0 && endTm.compareTo(edate) >= 0) {
|
|
|
+ ls.add(mappingUrl + path.toString());
|
|
|
+
|
|
|
+ /* s| | e */
|
|
|
+ } else if (startTm.compareTo(sdate) <= 0 && endTm.compareTo(edate) >= 0) {
|
|
|
+ ls.add(mappingUrl + path.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!ObjectUtils.isEmpty(ls)) {
|
|
|
+ return ls;
|
|
|
+// try {
|
|
|
+// return historyPlay(ls, ph);
|
|
|
+// } catch (IOException e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+ url = caneraConfig.getUrl();
|
|
|
+ mappingUrl = caneraConfig.getMappingUrl();
|
|
|
+ historyUrl = caneraConfig.getHistoryUrl();
|
|
|
+ ffmpegPath = caneraConfig.getFfmpegPath();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * * 参数:
|
|
|
+ * **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 mergeFile(List<String> fromVideoFileList, String NewfilePath) {
|
|
|
+ // 合并命令
|
|
|
+ String commit = "$0 -f concat -safe 0 -i $1 -c copy $2";
|
|
|
+
|
|
|
+ String str = commit.replace("$0", ffmpegPath);
|
|
|
+ if (!ObjectUtils.isEmpty(fromVideoFileList)) {
|
|
|
+ for (String s : fromVideoFileList) {
|
|
|
+ str = str.replace("$1", s);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ str = str.replace("$2", NewfilePath);
|
|
|
+ System.out.println(str);
|
|
|
+ Runtime runtime = Runtime.getRuntime();
|
|
|
+ try {
|
|
|
+ Process proce = runtime.exec(str);
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) throws IOException {
|
|
|
+
|
|
|
+ List<String> fromVideoFileList = new ArrayList();
|
|
|
+ String p = "C:\\Users\\Administrator.DESKTOP-0NUUTMM\\Desktop\\work\\106\\流媒体\\";
|
|
|
+ String NewfilePath = p + "mergevideo.flv";
|
|
|
+ fromVideoFileList.add(p + "20230303_174931_175031-d6d56396-b9a8-11ed-aeb9-00163e06a5f3.flv");
|
|
|
+ fromVideoFileList.add(p + "20230303_175032_175132-fb32b9fe-b9a8-11ed-aeb9-00163e06a5f3.flv");
|
|
|
+ fromVideoFileList.add(p + "20230303_175133_175233-1f97af04-b9a9-11ed-aeb9-00163e06a5f3.flv");
|
|
|
+ fromVideoFileList.add(p + "20230303_175234_175334-43f4daf1-b9a9-11ed-aeb9-00163e06a5f3.flv");
|
|
|
+ convetor(fromVideoFileList, NewfilePath);
|
|
|
+
|
|
|
+ }
|
|
|
+}
|