xiangpei
2024-10-10 5602c458099e38c6c4278334e5cb4f8029c63a50
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
@@ -20,6 +21,7 @@
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.IdUtils;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
@@ -28,16 +30,25 @@
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.opencv_core.Mat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.http.HttpServletRequest;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@@ -76,6 +87,8 @@
   @Autowired
   private UserSetting userSetting;
   private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
   @Operation(summary = "开始点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
   @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@@ -149,6 +162,76 @@
      return result;
   }
   @Operation(summary = "开始点播并返回图片", security = @SecurityRequirement(name = JwtUtils.HEADER))
   @Parameter(name = "deviceId", description = "设备国标编号", required = true)
   @Parameter(name = "channelId", description = "通道国标编号", required = true)
   @GetMapping("/start/img/{deviceId}/{channelId}")
   public DeferredResult<WVPResult<String>> playReturnImg(HttpServletRequest request, @PathVariable String deviceId,
                                           @PathVariable String channelId) {
      DeferredResult<WVPResult<StreamContent>> play = this.play(request, deviceId, channelId);
      Object resultStr = play.getResult();
      System.out.println("获取结果:" + resultStr);
      WVPResult wvpResult = (WVPResult) resultStr;
      WVPResult<String> result = new WVPResult<>();
      result.setData(this.getImg(wvpResult));
      result.setCode(wvpResult.getCode());
      result.setMsg(wvpResult.getMsg());
      DeferredResult<WVPResult<String>> r = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
      r.setResult(result);
      return r;
   }
   private String getImg(WVPResult<StreamContent> wvpResult) {
      String imgUrl = null;
      if (wvpResult.getCode() == 0) {
         String rtspUrl = wvpResult.getData().getFmp4(); // 取mp4地址
         if (StringUtils.hasText(rtspUrl)) {
            System.out.println("目标地址:" + rtspUrl);
            FFmpegFrameGrabber grabber = null;
            try {
               grabber = new FFmpegFrameGrabber(rtspUrl);
//                    grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重
//                    grabber.setVideoOption("probesize", "10000"); // 设置捕获分析的最大字节
               grabber.start();
               Frame frame = grabber.grabImage(); // 直接捕获一帧
               if (frame != null) {
                  System.out.println("成功捕获一帧");
                  // 将Frame转换为Mat
                  OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
                  Mat mat = converter.convertToMat(frame);
                  imgUrl = format.format(new Date()) + "_" + IdUtils.randomUUID() + ".png";
                  // 生成图片路径
                  String imgPath = "/home/zgyw/uploadPath/" + imgUrl;
                  System.out.println("图片保存地址:" + imgPath);
                  imgUrl = "/profile/" + imgUrl;
                  // 保存图片
                  opencv_imgcodecs.imwrite(imgPath, mat);
               } else {
                  System.out.println("未捕获到帧");
               }
            } catch (FrameGrabber.Exception e) {
               e.printStackTrace();
            } finally {
               if (grabber != null) {
                  try {
                     grabber.stop(); // 停止捕获
                  } catch (FrameGrabber.Exception e) {
                     e.printStackTrace();
                  }
               }
            }
         }
      } else {
         System.out.println("请求失败,错误码:" + wvpResult.getCode() + "--" + wvpResult.getMsg());
      }
      System.out.println("图片URL:" + imgUrl);
      return imgUrl;
   }
   @Operation(summary = "停止点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
   @Parameter(name = "deviceId", description = "设备国标编号", required = true)
   @Parameter(name = "channelId", description = "通道国标编号", required = true)