|
@@ -3,15 +3,18 @@ package com.ozs.web.core.util;
|
|
|
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
import com.ozs.common.config.BaseConfig;
|
|
|
+import com.ozs.common.core.domain.AjaxResult;
|
|
|
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 io.swagger.annotations.ApiOperation;
|
|
|
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 org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
import java.io.*;
|
|
@@ -45,12 +48,21 @@ public class CameraUtil {
|
|
|
* @return
|
|
|
* @throws IOException
|
|
|
*/
|
|
|
- public static String historyPlay(List<String> fromVideoFileList, String ph) throws IOException {
|
|
|
+ public static String historyPlay(List<String> fromVideoFileList, String ph) {
|
|
|
// 视频服务映射路径
|
|
|
String NewfilePath = flvPath + ph;
|
|
|
log.info("NewfilePath:{}", NewfilePath);
|
|
|
log.info("fromVideoFileList:{}", fromVideoFileList);
|
|
|
- convetor(fromVideoFileList, NewfilePath);
|
|
|
+ new Thread(() -> {
|
|
|
+ try {
|
|
|
+ myConvetor(fromVideoFileList, NewfilePath);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ // windows可以 linux不行
|
|
|
+// convetor(fromVideoFileList, NewfilePath);
|
|
|
return mappingUrl + "record/flv/hazard/" + ph;
|
|
|
}
|
|
|
|
|
@@ -65,6 +77,27 @@ public class CameraUtil {
|
|
|
return historyUrl + "/hdl/" + channel + "/" + cameraCode + ".flv";
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 开启录制功能
|
|
|
+ *
|
|
|
+ * @param cameraCode 相机编码
|
|
|
+ * @param channel 相机通道
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String startRecording(String cameraCode, String channel) {
|
|
|
+ return historyUrl + "/api/record/flv/start?streamPath=" + channel + "/" + cameraCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭录制功能
|
|
|
+ *
|
|
|
+ * @param taskId 录像接口返回的任务ID
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String endRecording(String taskId) {
|
|
|
+ return historyUrl + "/api/record/flv/stop?id=" + taskId;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 实时播放
|
|
|
*
|
|
@@ -83,12 +116,12 @@ public class CameraUtil {
|
|
|
|
|
|
public static String historyPlayListStr(String channel, Date startTm, Date endTm) {
|
|
|
List<String> list = historyPlayList(channel, startTm, endTm, filePath);
|
|
|
- String ph = "flv/" + DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date())
|
|
|
- + "-" + channel + "-"
|
|
|
+ String ph = "flv/" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date())
|
|
|
+ + "/" + channel + "/"
|
|
|
+ UUID.randomUUID().toString() + ".flv";
|
|
|
try {
|
|
|
return historyPlay(list, ph);
|
|
|
- } catch (IOException e) {
|
|
|
+ } catch (Exception e) {
|
|
|
log.error(e.getMessage());
|
|
|
e.printStackTrace();
|
|
|
}
|
|
@@ -167,61 +200,82 @@ public class CameraUtil {
|
|
|
* **String NewfilePath 合并后的视频存放地址,如:E:/mergevideo.mp4***
|
|
|
*/
|
|
|
public static void convetor(List<String> fromVideoFileList,
|
|
|
- String NewfilePath) throws IOException {
|
|
|
+ String newfilePath) throws IOException {
|
|
|
+ File file = new File(newfilePath);
|
|
|
+ if (!file.getParentFile().exists()) {
|
|
|
+ file.getParentFile().mkdirs();
|
|
|
+ log.info("创建文件夹:{}", file.getParentFile().getPath());
|
|
|
+ }
|
|
|
+ log.info("newfilePath:{}", newfilePath);
|
|
|
+ Runtime.getRuntime().exec("chmod 777 " + file.getParentFile().getPath());
|
|
|
List<String> voidTS = new ArrayList<>();
|
|
|
Process process = null;
|
|
|
ProcessBuilder builder = null;
|
|
|
List<String> command = null;
|
|
|
-
|
|
|
+ String substr = fromVideoFileList.get(0).substring(0, fromVideoFileList.get(0).lastIndexOf("/"));
|
|
|
+ log.info("substr:{}", substr);
|
|
|
+ Runtime.getRuntime().exec("chmod 777 " + substr);
|
|
|
+ // 转化为临时文件 .ts 放入到 voidTS里面
|
|
|
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");
|
|
|
- fromVideoFile = fromVideoFile.substring(fromVideoFile.lastIndexOf("/") + 1, fromVideoFile.length());
|
|
|
- String n = flvPath + fromVideoFile.substring(0,
|
|
|
- fromVideoFile.lastIndexOf("."));
|
|
|
- command.add(n + ".ts");
|
|
|
- builder = new ProcessBuilder(command);
|
|
|
- voidTS.add(n + ".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);
|
|
|
+ File file1 = new File(fromVideoFile);
|
|
|
+ if (file1.exists()) {
|
|
|
+ log.info("文件存在:{}", fromVideoFile);
|
|
|
+ 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) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
}
|
|
|
- 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();
|
|
|
+ } else {
|
|
|
+ log.info("文件不存在:{}", fromVideoFile);
|
|
|
}
|
|
|
}
|
|
|
+ for (String voidT : voidTS) {
|
|
|
+ Runtime.getRuntime().exec("chmod 777 " + voidT);
|
|
|
+ }
|
|
|
+ log.info("ffmpegPath:{}", ffmpegPath);
|
|
|
List<String> dos = new ArrayList<>();
|
|
|
StringBuffer tsPath = new StringBuffer();
|
|
|
tsPath.append(ffmpegPath);
|
|
|
tsPath.append(" -i ");
|
|
|
tsPath.append("concat:");
|
|
|
+ log.info("voidTS:{}", voidTS);
|
|
|
for (int t = 0; t < voidTS.size(); t++) {
|
|
|
if (t != voidTS.size() - 1) {
|
|
|
tsPath.append(voidTS.get(t) + "|");
|
|
@@ -235,7 +289,8 @@ public class CameraUtil {
|
|
|
tsPath.append(" aac_adtstoasc ");
|
|
|
tsPath.append(" -movflags ");
|
|
|
tsPath.append(" +faststart ");
|
|
|
- tsPath.append(NewfilePath);
|
|
|
+ tsPath.append(newfilePath);
|
|
|
+ log.info("执行的命令:{}", tsPath.toString());
|
|
|
Process pr = Runtime.getRuntime().exec(
|
|
|
tsPath.toString());
|
|
|
process.getInputStream();
|
|
@@ -243,19 +298,104 @@ public class CameraUtil {
|
|
|
pr.getInputStream().close();
|
|
|
pr.getErrorStream().close();
|
|
|
try {
|
|
|
- pr.waitFor();
|
|
|
- Thread.sleep(1000);
|
|
|
- pr.destroy();
|
|
|
+ int i = pr.waitFor();
|
|
|
+ System.out.println("********");
|
|
|
+ log.info("********");
|
|
|
+ System.out.println(i);
|
|
|
+ log.info(i + "");
|
|
|
+ log.info("********");
|
|
|
+ System.out.println("********");
|
|
|
} catch (InterruptedException e) {
|
|
|
- // TODO Auto-generated catch block
|
|
|
+ log.error(e.getMessage());
|
|
|
e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ pr.destroy();
|
|
|
}
|
|
|
+
|
|
|
//删除生成的ts文件
|
|
|
- for (String filePath : voidTS) {
|
|
|
- File file = new File(filePath);
|
|
|
- file.delete();
|
|
|
- pr.destroy();
|
|
|
+// for (String filePath : voidTS) {
|
|
|
+// File filet = new File(filePath);
|
|
|
+// filet.delete();
|
|
|
+// pr.destroy();
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static void myConvetor(List<String> fromVideoFileList,
|
|
|
+ String newfilePath) throws IOException {
|
|
|
+ /*
|
|
|
+ * for f in *.flv; do echo "file '$f'" >> mylist.txt; done
|
|
|
+ ffmpeg -f concat -i mylist.txt -c copy output.flv
|
|
|
+ * */
|
|
|
+
|
|
|
+ List<String> rspList = new ArrayList<String>();
|
|
|
+ File file = new File(newfilePath);
|
|
|
+ boolean flay = false;
|
|
|
+ if (!file.getParentFile().exists()) {
|
|
|
+ file.getParentFile().mkdirs();
|
|
|
+ log.info("创建文件夹:{}", file.getParentFile().getPath());
|
|
|
+ flay = true;
|
|
|
+ }
|
|
|
+ log.info("newfilePath:{}", newfilePath);
|
|
|
+
|
|
|
+
|
|
|
+ StringBuffer sm = new StringBuffer("for f in ");
|
|
|
+ for (int t = 0; t < fromVideoFileList.size(); t++) {
|
|
|
+ File ft = new File(fromVideoFileList.get(t));
|
|
|
+ if (ft.exists()) {
|
|
|
+ if (t != fromVideoFileList.size() - 1) {
|
|
|
+ sm.append(fromVideoFileList.get(t) + " ");
|
|
|
+ } else {
|
|
|
+ sm.append(fromVideoFileList.get(t));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String substring = newfilePath.substring(0, newfilePath.lastIndexOf("."));
|
|
|
+ substring = substring + ".txt";
|
|
|
+ log.info("临时转化的文件:{}", substring);
|
|
|
+
|
|
|
+
|
|
|
+ sm.append("; do echo \"file '$f'\" >> " + substring + "; done");
|
|
|
+ String commit = sm.toString();
|
|
|
+ log.info("合并转化文件的命令:{}", commit);
|
|
|
+ Process proc = Runtime.getRuntime().exec("/bin/bash", null, null);
|
|
|
+ BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
|
|
+ PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
|
|
|
+
|
|
|
+ try {
|
|
|
+ String commit1 = ffmpegPath + " -f concat -safe 0 -i " + substring + " -c copy " + newfilePath;
|
|
|
+ List<String> commands = new ArrayList<>();
|
|
|
+ if (flay) {
|
|
|
+ commands.add("chomd -R 777 " + file.getParentFile().getPath());
|
|
|
+ }
|
|
|
+ // 合并成一个临时文件
|
|
|
+ commands.add(commit);
|
|
|
+ // 临时文件转化为 flv
|
|
|
+ commands.add(commit1);
|
|
|
+ for (String line : commands) {
|
|
|
+ out.println(line);
|
|
|
+ }
|
|
|
+ out.println("exit");// 这个命令必须执行,否则in流不结束。
|
|
|
+ String rspLine = "";
|
|
|
+ while ((rspLine = in.readLine()) != null) {
|
|
|
+ System.out.println(rspLine);
|
|
|
+ rspList.add(rspLine);
|
|
|
+ }
|
|
|
+ int i = proc.waitFor();
|
|
|
+ log.info("执行结果:{}", i);
|
|
|
+ //删除生成的ts文件
|
|
|
+ File file1 = new File(substring);
|
|
|
+ if (file1.exists()) {
|
|
|
+ file1.delete();
|
|
|
+ }
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ in.close();
|
|
|
+ out.close();
|
|
|
+ proc.destroy();
|
|
|
}
|
|
|
+ log.info("返回结果:{}", rspList);
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) throws IOException {
|