You've already forked FrameTour-BE
外部设备及对接阿里云媒体处理
This commit is contained in:
83
src/main/java/com/ycwl/basic/controller/extern/CustomDeviceController.java
vendored
Normal file
83
src/main/java/com/ycwl/basic/controller/extern/CustomDeviceController.java
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package com.ycwl.basic.controller.extern;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.model.custom.req.AliyunCallbackReq;
|
||||
import com.ycwl.basic.model.custom.req.CreateUploadTaskReq;
|
||||
import com.ycwl.basic.model.custom.req.UploadCompleteReq;
|
||||
import com.ycwl.basic.model.custom.req.UploadFailedReq;
|
||||
import com.ycwl.basic.model.custom.resp.CreateUploadTaskResp;
|
||||
import com.ycwl.basic.service.custom.CustomUploadTaskService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/extern/custom-device")
|
||||
@IgnoreToken
|
||||
public class CustomDeviceController {
|
||||
|
||||
@Autowired
|
||||
private CustomUploadTaskService customUploadTaskService;
|
||||
|
||||
@PostMapping("/upload/create")
|
||||
public ApiResponse<CreateUploadTaskResp> createUploadTask(@RequestBody CreateUploadTaskReq req) {
|
||||
try {
|
||||
CreateUploadTaskResp resp = customUploadTaskService.createUploadTask(req);
|
||||
return ApiResponse.success(resp);
|
||||
} catch (Exception e) {
|
||||
log.error("创建上传任务失败", e);
|
||||
return ApiResponse.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/upload/complete")
|
||||
public ApiResponse<String> uploadComplete(@RequestBody UploadCompleteReq req) {
|
||||
try {
|
||||
customUploadTaskService.completeUpload(req.getAccessKey(), req.getTaskId());
|
||||
return ApiResponse.success("上传完成,人脸识别任务已提交");
|
||||
} catch (Exception e) {
|
||||
log.error("上传完成处理失败", e);
|
||||
return ApiResponse.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/upload/failed")
|
||||
public ApiResponse<String> uploadFailed(@RequestBody UploadFailedReq req) {
|
||||
try {
|
||||
customUploadTaskService.markTaskFailed(req.getAccessKey(), req.getTaskId(), req.getErrorMsg());
|
||||
return ApiResponse.success("任务已标记为失败");
|
||||
} catch (Exception e) {
|
||||
log.error("标记任务失败处理异常", e);
|
||||
return ApiResponse.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/aliyun/mps/callback")
|
||||
public ApiResponse<String> aliyunCallback(@RequestBody AliyunCallbackReq req) {
|
||||
try {
|
||||
customUploadTaskService.handleAliyunCallback(req.getJobId(), req.getStatus());
|
||||
return ApiResponse.success("回调处理完成");
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云回调处理失败", e);
|
||||
return ApiResponse.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/aliyun/mps/callback")
|
||||
public ApiResponse<String> aliyunCallback(@RequestParam("jobId") String jobId, @RequestParam("status") String status) {
|
||||
try {
|
||||
customUploadTaskService.handleAliyunCallback(jobId, status);
|
||||
return ApiResponse.success("回调处理完成");
|
||||
} catch (Exception e) {
|
||||
log.error("阿里云回调处理失败", e);
|
||||
return ApiResponse.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CustomUploadTaskMapper extends BaseMapper<CustomUploadTaskEntity> {
|
||||
CustomUploadTaskEntity getByJobId(String jobId);
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.ycwl.basic.model.custom.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("custom_upload_task")
|
||||
public class CustomUploadTaskEntity {
|
||||
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
private Long scenicId;
|
||||
|
||||
private Long deviceId;
|
||||
|
||||
private String savePath;
|
||||
|
||||
private String status;
|
||||
|
||||
private String jobId;
|
||||
|
||||
private String errorMsg;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private Date updateTime;
|
||||
}
|
145
src/main/java/com/ycwl/basic/model/custom/entity/FaceData.java
Normal file
145
src/main/java/com/ycwl/basic/model/custom/entity/FaceData.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package com.ycwl.basic.model.custom.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FaceData {
|
||||
private String category;
|
||||
private String name;
|
||||
private List<Occurrence> occurrences;
|
||||
private Double ratio;
|
||||
|
||||
// Getters and setters
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Occurrence> getOccurrences() {
|
||||
return occurrences;
|
||||
}
|
||||
|
||||
public void setOccurrences(List<Occurrence> occurrences) {
|
||||
this.occurrences = occurrences;
|
||||
}
|
||||
|
||||
public Double getRatio() {
|
||||
return ratio;
|
||||
}
|
||||
|
||||
public void setRatio(Double ratio) {
|
||||
this.ratio = ratio;
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class Occurrence {
|
||||
@JsonProperty("faceUrl")
|
||||
private String faceUrl;
|
||||
|
||||
private Double from;
|
||||
private Position position;
|
||||
private String scene;
|
||||
private Double score;
|
||||
private Double timestamp;
|
||||
private Double to;
|
||||
|
||||
// Getters and setters
|
||||
public String getFaceUrl() {
|
||||
return faceUrl;
|
||||
}
|
||||
|
||||
public void setFaceUrl(String faceUrl) {
|
||||
this.faceUrl = faceUrl;
|
||||
}
|
||||
|
||||
public Double getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public void setFrom(Double from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getScene() {
|
||||
return scene;
|
||||
}
|
||||
|
||||
public void setScene(String scene) {
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public Double getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(Double score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public Double getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Double timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public Double getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public void setTo(Double to) {
|
||||
this.to = to;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class Position {
|
||||
@JsonProperty("leftTop")
|
||||
private List<Integer> leftTop;
|
||||
|
||||
@JsonProperty("rightBottom")
|
||||
private List<Integer> rightBottom;
|
||||
|
||||
// Getters and setters
|
||||
public List<Integer> getLeftTop() {
|
||||
return leftTop;
|
||||
}
|
||||
|
||||
public void setLeftTop(List<Integer> leftTop) {
|
||||
this.leftTop = leftTop;
|
||||
}
|
||||
|
||||
public List<Integer> getRightBottom() {
|
||||
return rightBottom;
|
||||
}
|
||||
|
||||
public void setRightBottom(List<Integer> rightBottom) {
|
||||
this.rightBottom = rightBottom;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.model.custom.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AliyunCallbackReq {
|
||||
|
||||
private String jobId;
|
||||
|
||||
private String pipelineId;
|
||||
|
||||
private String status;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.model.custom.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateUploadTaskReq {
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private String fileName;
|
||||
|
||||
private String type;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.ycwl.basic.model.custom.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UploadCompleteReq {
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private Long taskId;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.model.custom.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UploadFailedReq {
|
||||
|
||||
private String accessKey;
|
||||
|
||||
private Long taskId;
|
||||
|
||||
private String errorMsg;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.model.custom.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateUploadTaskResp {
|
||||
|
||||
private Long taskId;
|
||||
|
||||
private String uploadUrl;
|
||||
|
||||
private String savePath;
|
||||
}
|
@@ -0,0 +1,339 @@
|
||||
package com.ycwl.basic.service.custom;
|
||||
|
||||
import com.aliyun.credentials.Client;
|
||||
import com.aliyun.credentials.models.Config;
|
||||
import com.aliyun.mts20140618.models.QuerySmarttagJobRequest;
|
||||
import com.aliyun.mts20140618.models.QuerySmarttagJobResponse;
|
||||
import com.aliyun.mts20140618.models.QuerySmarttagJobResponseBody;
|
||||
import com.aliyun.mts20140618.models.SubmitSmarttagJobRequest;
|
||||
import com.aliyun.mts20140618.models.SubmitSmarttagJobResponse;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||
import com.ycwl.basic.mapper.DeviceMapper;
|
||||
import com.ycwl.basic.mapper.CustomUploadTaskMapper;
|
||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||
import com.ycwl.basic.mapper.ScenicMapper;
|
||||
import com.ycwl.basic.mapper.SourceMapper;
|
||||
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||
import com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity;
|
||||
import com.ycwl.basic.model.custom.entity.FaceData;
|
||||
import com.ycwl.basic.model.custom.req.CreateUploadTaskReq;
|
||||
import com.ycwl.basic.model.custom.resp.CreateUploadTaskResp;
|
||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.utils.JacksonUtil;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.ycwl.basic.constant.StorageConstant.VIID_FACE;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CustomUploadTaskService {
|
||||
|
||||
@Autowired
|
||||
private CustomUploadTaskMapper customUploadTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@Autowired
|
||||
private ScenicService scenicService;
|
||||
@Autowired
|
||||
private FaceSampleMapper faceSampleMapper;
|
||||
@Autowired
|
||||
private SourceMapper sourceMapper;
|
||||
|
||||
private static final ThreadPoolExecutor executor;
|
||||
static {
|
||||
executor = new ThreadPoolExecutor(16, 32, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
|
||||
}
|
||||
|
||||
public CreateUploadTaskResp createUploadTask(CreateUploadTaskReq req) {
|
||||
if (StringUtils.isBlank(req.getAccessKey())) {
|
||||
throw new RuntimeException("设备访问密钥不能为空");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(req.getFileName())) {
|
||||
throw new RuntimeException("文件名不能为空");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(req.getType())) {
|
||||
throw new RuntimeException("上传类型不能为空");
|
||||
}
|
||||
|
||||
// 验证设备访问权限
|
||||
DeviceEntity device = validateDeviceAccess(req.getAccessKey(), req.getType());
|
||||
|
||||
long taskId = SnowFlakeUtil.getLongId();
|
||||
String savePath = generateSavePath(device.getScenicId(), req.getFileName());
|
||||
|
||||
CustomUploadTaskEntity task = new CustomUploadTaskEntity();
|
||||
task.setId(taskId);
|
||||
task.setScenicId(device.getScenicId());
|
||||
task.setDeviceId(device.getId());
|
||||
task.setSavePath(savePath);
|
||||
task.setStatus("PENDING");
|
||||
task.setCreateTime(new Date());
|
||||
task.setUpdateTime(new Date());
|
||||
|
||||
customUploadTaskMapper.insert(task);
|
||||
|
||||
String uploadUrl = generateUploadUrl(savePath);
|
||||
|
||||
CreateUploadTaskResp resp = new CreateUploadTaskResp();
|
||||
resp.setTaskId(taskId);
|
||||
resp.setUploadUrl(uploadUrl);
|
||||
resp.setSavePath(savePath);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
public void completeUpload(String accessKey, Long taskId) {
|
||||
// 验证设备访问权限
|
||||
DeviceEntity device = validateDeviceAccess(accessKey, null);
|
||||
|
||||
CustomUploadTaskEntity task = customUploadTaskMapper.selectById(taskId);
|
||||
if (task == null) {
|
||||
throw new RuntimeException("任务不存在");
|
||||
}
|
||||
|
||||
// 验证任务属于该设备的景区
|
||||
if (!device.getScenicId().equals(task.getScenicId())) {
|
||||
throw new RuntimeException("无权限操作该任务");
|
||||
}
|
||||
|
||||
task.setStatus("UPLOADING");
|
||||
task.setUpdateTime(new Date());
|
||||
customUploadTaskMapper.updateById(task);
|
||||
|
||||
try {
|
||||
String jobId = submitSmarttagJob(task.getSavePath());
|
||||
|
||||
task.setJobId(jobId);
|
||||
task.setStatus("COMPLETED");
|
||||
task.setUpdateTime(new Date());
|
||||
customUploadTaskMapper.updateById(task);
|
||||
|
||||
log.info("人脸识别任务提交成功,taskId: {}, jobId: {}", taskId, jobId);
|
||||
} catch (Exception e) {
|
||||
task.setStatus("FAILED");
|
||||
task.setErrorMsg("人脸识别任务提交失败: " + e.getMessage());
|
||||
task.setUpdateTime(new Date());
|
||||
customUploadTaskMapper.updateById(task);
|
||||
|
||||
log.error("人脸识别任务提交失败,taskId: {}", taskId, e);
|
||||
throw new RuntimeException("人脸识别任务提交失败");
|
||||
}
|
||||
}
|
||||
|
||||
public void markTaskFailed(String accessKey, Long taskId, String errorMsg) {
|
||||
// 验证设备访问权限
|
||||
DeviceEntity device = validateDeviceAccess(accessKey, null);
|
||||
|
||||
CustomUploadTaskEntity task = customUploadTaskMapper.selectById(taskId);
|
||||
if (task == null) {
|
||||
throw new RuntimeException("任务不存在");
|
||||
}
|
||||
|
||||
// 验证任务属于该设备的景区
|
||||
if (!device.getScenicId().equals(task.getScenicId())) {
|
||||
throw new RuntimeException("无权限操作该任务");
|
||||
}
|
||||
|
||||
task.setStatus("FAILED");
|
||||
task.setErrorMsg(errorMsg);
|
||||
task.setUpdateTime(new Date());
|
||||
customUploadTaskMapper.updateById(task);
|
||||
|
||||
log.info("任务标记为失败,taskId: {}, errorMsg: {}", taskId, errorMsg);
|
||||
}
|
||||
|
||||
public void handleAliyunCallback(String jobId, String status) {
|
||||
LambdaQueryWrapper<CustomUploadTaskEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CustomUploadTaskEntity::getJobId, jobId);
|
||||
|
||||
CustomUploadTaskEntity task = customUploadTaskMapper.selectOne(wrapper);
|
||||
if (task == null) {
|
||||
log.warn("未找到对应的上传任务,jobId: {}", jobId);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("收到阿里云回调,jobId: {}, status: {}, taskId: {}", jobId, status, task.getId());
|
||||
|
||||
handleAliyunMpsJobComplete(jobId);
|
||||
}
|
||||
|
||||
private String generateSavePath(Long scenicId, String fileName) {
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
String extension = "";
|
||||
if (fileName.contains(".")) {
|
||||
extension = fileName.substring(fileName.lastIndexOf("."));
|
||||
}
|
||||
return String.format("custom-device/%d/%s%s", scenicId, timestamp, extension);
|
||||
}
|
||||
|
||||
private String generateUploadUrl(String savePath) {
|
||||
try {
|
||||
IStorageAdapter adapter = StorageFactory.use();
|
||||
|
||||
Date expireDate = new Date(System.currentTimeMillis() + 3600 * 1000);
|
||||
return adapter.getUrlForUpload(expireDate, null, savePath);
|
||||
} catch (Exception e) {
|
||||
log.error("生成上传URL失败,savePath: {}", savePath, e);
|
||||
throw new RuntimeException("生成上传URL失败");
|
||||
}
|
||||
}
|
||||
|
||||
private String submitSmarttagJob(String inputPath) {
|
||||
try {
|
||||
log.info("提交人脸识别任务,inputPath: {}", inputPath);
|
||||
String jobId = createAliyunMtsTask(inputPath);
|
||||
executor.execute(() -> loopQueryJobStatus(jobId));
|
||||
return jobId;
|
||||
} catch (Exception e) {
|
||||
log.error("提交人脸识别任务失败,inputPath: {}", inputPath, e);
|
||||
throw new RuntimeException("提交人脸识别任务失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceEntity validateDeviceAccess(String accessKey, String type) {
|
||||
if (StringUtils.isBlank(accessKey)) {
|
||||
throw new RuntimeException("设备访问密钥不能为空");
|
||||
}
|
||||
|
||||
DeviceEntity device = deviceMapper.getByDeviceNo(accessKey);
|
||||
if (device == null || device.getStatus() != 1) {
|
||||
throw new RuntimeException("无效的设备访问密钥或设备已被禁用");
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
private String createAliyunMtsTask(String inputPath) {
|
||||
try {
|
||||
// 创建任务
|
||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
.setAccessKeyId("LTAI5tCWgYJz9kZvvh2KVhkH")
|
||||
.setAccessKeySecret("RObb3EZ1YsmR63ul1gh7tnIfT1foOc");
|
||||
config.endpoint = "mts.cn-shanghai.aliyuncs.com";
|
||||
com.aliyun.mts20140618.Client client = new com.aliyun.mts20140618.Client(config);
|
||||
SubmitSmarttagJobRequest request = new SubmitSmarttagJobRequest();
|
||||
request.setPipelineId("d791f854652e466bad66301e5c97b7bb");
|
||||
request.setTemplateId("a004e08402bd496a8a9adbb2ba920973");
|
||||
request.setTitle(String.valueOf(System.currentTimeMillis()));
|
||||
request.setNotifyUrl("https://zhentuai.com/extern/custom-device/aliyun/mps/callback");
|
||||
request.setInput(String.format("oss://frametour-assets/user-assets/%s", inputPath));
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
SubmitSmarttagJobResponse submitSmarttagJobResponse = client.submitSmarttagJobWithOptions(request, runtime);
|
||||
return submitSmarttagJobResponse.getBody().jobId;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loopQueryJobStatus(String jobId) {
|
||||
try {
|
||||
Thread.sleep(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
handleAliyunMpsJobComplete(jobId);
|
||||
}
|
||||
|
||||
|
||||
public void handleAliyunMpsJobComplete(String jobId) {
|
||||
CustomUploadTaskEntity task = customUploadTaskMapper.getByJobId(jobId);
|
||||
try {
|
||||
// 查询任务
|
||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
.setAccessKeyId("LTAI5tCWgYJz9kZvvh2KVhkH")
|
||||
.setAccessKeySecret("RObb3EZ1YsmR63ul1gh7tnIfT1foOc");
|
||||
config.endpoint = "mts.cn-shanghai.aliyuncs.com";
|
||||
com.aliyun.mts20140618.Client client = new com.aliyun.mts20140618.Client(config);
|
||||
QuerySmarttagJobRequest request = new QuerySmarttagJobRequest();
|
||||
request.setJobId(jobId);
|
||||
QuerySmarttagJobResponse response = client.querySmarttagJob(request);
|
||||
if (Strings.CI.equals(response.getBody().jobStatus, "Fail")) {
|
||||
log.error("智能标签任务失败");
|
||||
return;
|
||||
}
|
||||
if (!Strings.CI.equals(response.getBody().jobStatus, "Success")) {
|
||||
log.info("jobId:{} 智能标签任务等待查询!", jobId);
|
||||
executor.execute(() -> loopQueryJobStatus(jobId));
|
||||
return;
|
||||
}
|
||||
List<QuerySmarttagJobResponseBody.QuerySmarttagJobResponseBodyResultsResult> result = response.getBody().results.getResult();
|
||||
QuerySmarttagJobResponseBody.QuerySmarttagJobResponseBodyResultsResult first = result.stream()
|
||||
.filter(r -> "VideoLabel".equals(r.getType()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (first == null) {
|
||||
return;
|
||||
}
|
||||
List<FaceData> persons = JacksonUtil.getArray(first.getData(), "persons", FaceData.class);
|
||||
if (persons == null || persons.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(task.getScenicId());
|
||||
IStorageAdapter storageAdapter = StorageFactory.use();
|
||||
persons.stream()
|
||||
.filter(p -> p.getRatio() > 0.1)
|
||||
.map(FaceData::getOccurrences)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(occurrences -> {
|
||||
if (occurrences.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Long newFaceSampleId = SnowFlakeUtil.getLongId();
|
||||
String faceUrl = occurrences.getFirst().getFaceUrl();
|
||||
FaceSampleEntity faceSample = new FaceSampleEntity();
|
||||
faceSample.setId(newFaceSampleId);
|
||||
faceSample.setScenicId(task.getScenicId());
|
||||
faceSample.setDeviceId(task.getDeviceId());
|
||||
faceSample.setStatus(1);
|
||||
faceSample.setCreateAt(task.getCreateTime());
|
||||
faceSample.setFaceUrl(faceUrl);
|
||||
faceSampleMapper.add(faceSample);
|
||||
faceBodyAdapter.assureFaceDb(task.getScenicId().toString());
|
||||
AddFaceResp addFaceResp = faceBodyAdapter.addFace(task.getScenicId().toString(), newFaceSampleId.toString(), faceUrl, newFaceSampleId.toString());
|
||||
if (addFaceResp != null) {
|
||||
faceSample.setScore(addFaceResp.getScore());
|
||||
faceSampleMapper.updateScore(faceSample.getId(), addFaceResp.getScore());
|
||||
}
|
||||
SourceEntity source = new SourceEntity();
|
||||
source.setId(SnowFlakeUtil.getLongId());
|
||||
source.setDeviceId(task.getDeviceId());
|
||||
source.setScenicId(task.getScenicId());
|
||||
source.setFaceSampleId(newFaceSampleId);
|
||||
source.setCreateTime(task.getCreateTime());
|
||||
source.setType(1);
|
||||
source.setUrl(faceUrl);
|
||||
source.setVideoUrl(storageAdapter.getUrl(task.getSavePath()));
|
||||
sourceMapper.add(source);
|
||||
});
|
||||
System.out.println(JacksonUtil.toJson(persons));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
7
src/main/resources/mapper/CustomUploadTaskMapper.xml
Normal file
7
src/main/resources/mapper/CustomUploadTaskMapper.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="com.ycwl.basic.mapper.CustomUploadTaskMapper">
|
||||
<select id="getByJobId" resultType="com.ycwl.basic.model.custom.entity.CustomUploadTaskEntity">
|
||||
select * from custom_upload_task where job_id = #{jobId}
|
||||
</select>
|
||||
</mapper>
|
Reference in New Issue
Block a user