/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.springblade.jfpt.rvideo.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import lombok.AllArgsConstructor; import javax.validation.Valid; import net.logstash.logback.encoder.org.apache.commons.lang3.StringEscapeUtils; import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Query; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.jfpt.alarm.service.IAlarmService; import org.springblade.jfpt.xlfeedback.service.IXlfeedbackService; import org.springframework.web.bind.annotation.*; import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.jfpt.rvideo.entity.Rvideo; import org.springblade.jfpt.rvideo.vo.RvideoVO; import org.springblade.jfpt.rvideo.service.IRvideoService; import org.springblade.core.boot.ctrl.BladeController; import java.io.File; import org.bytedeco.javacpp.avcodec; import org.bytedeco.javacv.*; import java.io.IOException; import java.util.Date; /** * 控制器 * * @author BladeX * @since 2021-03-24 */ @RestController @AllArgsConstructor @RequestMapping("/rvideo") @Api(value = "", tags = "接口") public class RvideoController extends BladeController { private final IRvideoService rvideoService; private final IAlarmService alarmService; private final IXlfeedbackService xlfeedbackService; private static String PRE_URL = "D:\\software\\minio\\data\\jfpt\\void\\"; private static String PRF_MINIO_URL = "minio/jfpt/void/"; private static Thread thread; private static String UUIDs; private static String uids; private static int count=0; private static String xcbj = "cs"; //录制视频相关 private static String streamURL;// 流地址(测试可以用obs推流) private static String filePath;// 文件路径 private static Long timesSec = 100L;// 停止录制时长 0为不限制时长 private static String fileFormat = "mp4";//录制的文件格式 private static boolean isAudio = false;//是否录制声音 private static boolean stop = false; /** * 详情 */ @GetMapping("/detail") @ApiOperationSupport(order = 1) @ApiOperation(value = "详情", notes = "传入rvideo") public R detail(Rvideo rvideo) { Rvideo detail = rvideoService.getOne(Condition.getQueryWrapper(rvideo)); return R.data(detail); } /** * 分页 */ @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "分页", notes = "传入rvideo") public R> list(Rvideo rvideo, Query query) { IPage pages = rvideoService.page(Condition.getPage(query), Condition.getQueryWrapper(rvideo)); return R.data(pages); } /** * 自定义分页 */ @GetMapping("/page") @ApiOperationSupport(order = 3) @ApiOperation(value = "分页", notes = "传入rvideo") public R> page(RvideoVO rvideo, Query query) { IPage pages = rvideoService.selectRvideoPage(Condition.getPage(query), rvideo); return R.data(pages); } /** * 新增 */ @PostMapping("/save") @ApiOperationSupport(order = 4) @ApiOperation(value = "新增", notes = "传入rvideo") public R save(@Valid @RequestBody Rvideo rvideo) { return R.status(rvideoService.save(rvideo)); } /** * 修改 */ @PostMapping("/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "修改", notes = "传入rvideo") public R update(@Valid @RequestBody Rvideo rvideo) { return R.status(rvideoService.updateById(rvideo)); } /** * 新增或修改 */ @PostMapping("/submit") @ApiOperationSupport(order = 6) @ApiOperation(value = "新增或修改", notes = "传入rvideo") public R submit(@Valid @RequestBody Rvideo rvideo) { return R.status(rvideoService.saveOrUpdate(rvideo)); } /** * 删除 */ @PostMapping("/remove") @ApiOperationSupport(order = 8) @ApiOperation(value = "删除", notes = "传入ids") public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { return R.status(rvideoService.removeByIds(Func.toLongList(ids))); } // /** // * @param sourcePath 源路径 // * @param jid 警情id // * @throws Exception // */ // @PostMapping("/rVoid") // public String rVoid(String sourcePath,String jid) throws Exception { // String webroot = "D:\\LXVideoServer\\3rd\\ffmpeg\\bin"; // String UUID = DateUtil.time(); // //目标路径 // String targetPath = PRE_URL + UUID + ".mp4"; // //返回前端路径 // String vaddress = null; // Runtime run = null; // // try { // // run = Runtime.getRuntime(); // // long start = System.currentTimeMillis(); // // System.out.println(new File(webroot).getAbsolutePath()); // //通过视频url录制30s视频保存,格式为MP4 // String newJson = StringEscapeUtils.unescapeHtml4(sourcePath); // Process p = run.exec(new File(webroot).getAbsolutePath() + "/ffmpeg -i " +newJson+ " -y -t 00:00:30 -codec copy -f mp4 " + targetPath); // // //释放进程 // // p.getOutputStream().close(); // // p.getInputStream().close(); // // p.getErrorStream().close(); // // p.waitFor(); // // long end = System.currentTimeMillis(); // // System.out.println(sourcePath + " convert success, costs:" + (end - start) + "ms"); // // } catch (Exception e) { // // e.printStackTrace(); // // } finally { // //run调用lame解码器最后释放内存 // run.freeMemory(); // //返回路径 // vaddress = "https://web.byisf.com/" + PRF_MINIO_URL + UUID + ".mp4"; // //把路径通过警情id添加到警情信息 // alarmService.updateVaddress(vaddress,jid); // } // return vaddress; // } /** * Javacv录制视频 */ @PostMapping("/rVoids") public void rVoids(String url,String uid,String jid) { /*String UUID = DateUtil.time(); UUIDs=UUID; uids=uid; RecordVideoThread recordVideoThread = new RecordVideoThread(); recordVideoThread.filePath = "D:\\video\\"+UUID + ".mp4"; recordVideoThread.timesSec = 0L; String newJson = StringEscapeUtils.unescapeHtml4(url); recordVideoThread.streamURL =newJson;// 最好设置结束时长 如直接停止程序会造成输出文件的损坏无法正常播放 recordVideoThread.isAudio = true; thread = new Thread(recordVideoThread); thread.start();*/ String UUID = DateUtil.time(); UUIDs=UUID; uids=uid; //filePath = "D:\\video\\"+UUID + ".mp4"; filePath = "D:\\software\\minio\\data\\jfpt\\void\\"+UUID + ".mp4"; timesSec = 0L; String newJson = StringEscapeUtils.unescapeHtml4(url); streamURL =newJson;// 最好设置结束时长 如直接停止程序会造成输出文件的损坏无法正常播放 isAudio = true; xcbj = "ce"; Thread threads = new Thread(new Runnable() { @Override public void run() { //System.out.println("开始1111111"); // 获取视频源 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamURL); FFmpegFrameRecorder recorder = null; try { grabber.start(); Frame frame = grabber.grabFrame(); createFile(); //"rtmp://192.168.1.225:1935/live/home" // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制) recorder = new FFmpegFrameRecorder(filePath, 1280, 720, isAudio ? 1 : 0); recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);// 直播流格式 recorder.setFormat(fileFormat);// 录制的视频格式 recorder.setFrameRate(10);// 帧数 //百度翻译的比特率,默认400000,但是我400000贼模糊,调成800000比较合适 recorder.setVideoBitrate(800000); recorder.start(); System.out.println("推流开始"); //记录当前时间 long dqdate = new Date().getTime(); while (!jid.equals(xcbj)) { //记录现在时间 long xzdate = new Date().getTime(); if (xzdate > (dqdate + 300000)){ break; } if (frame != null){ System.out.println("开始"); recorder.record(frame);//录制 frame = grabber.grabFrame();//获取下一帧 System.out.println("结束"); } } if (jid.equals(xcbj)){ recorder.record(frame); } } catch (Exception e) { e.printStackTrace(); } finally { //停止录制 if (null != grabber) { try { grabber.stop(); } catch (FrameGrabber.Exception e) { e.printStackTrace(); } } if (recorder != null) { try { recorder.stop(); } catch (FrameRecorder.Exception e) { e.printStackTrace(); } } System.out.println("录制完成,录制时长:" + timesSec + "秒"); String vaddress = null; //返回路径 vaddress = "https://web.byisf.com/" + PRF_MINIO_URL + UUID + ".mp4"; //把路径通过警情id添加到警情信息 alarmService.updateVaddress(vaddress, uids, jid); } } }); threads.start(); } private void createFile() { File outFile = new File(filePath); if (filePath.isEmpty() || !outFile.exists() || outFile.isFile()) { try { outFile.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @PostMapping("/stop") public String stop(String jid) throws FrameGrabber.Exception { //返回前端路径 // String vaddress = null; // if (thread != null){ // thread.stop(); // //返回路径 // vaddress = "https://web.byisf.com/" + PRF_MINIO_URL + UUIDs + ".mp4"; // //把路径通过警情id添加到警情信息 // alarmService.updateVaddress(vaddress,uids,jid); // return vaddress; // } xcbj = jid; return ""; } // /** // * Javacv录制视频测试 // */ // @PostMapping("/cs") // public void rVoids(String url,String uid) { // String UUID = DateUtil.time(); // UUIDs=UUID; // String newJson = StringEscapeUtils.unescapeHtml4(url); // RecordVideoThread recordVideoThread = new RecordVideoThread(newJson,"D:\\software\\minio\\data\\jfpt\\void\\"+UUID +".mp4"); // thread = new Thread(recordVideoThread); // thread.start(); // } // // @PostMapping("/csc") // public String stopcs(String jid) throws FrameGrabber.Exception { // //返回前端路径 // String vaddress = null; // // 发出中断标志 true // thread.interrupt(); // //返回路径 // vaddress = "https://web.byisf.com/" + PRF_MINIO_URL + UUIDs + ".mp4"; // //把路径通过警情id添加到警情信息 // String uids=Integer.toString(count); // alarmService.updateVaddress(vaddress,uids,jid); // return vaddress; // // } }