You've already forked FrameTour-BE
调整
This commit is contained in:
@ -0,0 +1,126 @@
|
||||
package com.ycwl.basic.task;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.ycwl.basic.mapper.MemberMapper;
|
||||
import com.ycwl.basic.mapper.VideoMapper;
|
||||
import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
|
||||
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
|
||||
import com.ycwl.basic.notify.NotifyFactory;
|
||||
import com.ycwl.basic.notify.adapters.INotifyAdapter;
|
||||
import com.ycwl.basic.notify.entity.NotifyContent;
|
||||
import com.ycwl.basic.notify.enums.NotifyType;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.repository.TemplateRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
public class DownloadNotificationTasker {
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private VideoMapper videoMapper;
|
||||
@Autowired
|
||||
private MemberMapper memberMapper;
|
||||
|
||||
@Scheduled(cron = "0 0 21 * * *")
|
||||
public void sendDownloadNotification() {
|
||||
log.info("开始执行定时任务");
|
||||
videoMapper.listRelationByCreateTime(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000), new Date())
|
||||
.forEach(item -> {
|
||||
if (item.getIsBuy() == 1) {
|
||||
return;
|
||||
}
|
||||
MemberRespVO member = memberMapper.getById(item.getMemberId());
|
||||
MpConfigEntity scenicMp = scenicRepository.getScenicMpConfig(member.getScenicId());
|
||||
// 发送模板消息
|
||||
String templateId = scenicRepository.getVideoDownloadTemplateId(item.getScenicId());
|
||||
if (StringUtils.isBlank(templateId)) {
|
||||
log.info("模板消息为空");
|
||||
return;
|
||||
}
|
||||
log.info("发送模板消息");
|
||||
ScenicEntity scenic = scenicRepository.getScenic(item.getScenicId());
|
||||
String title = "您在【" + scenic.getName() + "】的专属影像";
|
||||
String page = "pages/videoSynthesis/buy?scenicId=" + item.getScenicId() + "&faceId=" + item.getFaceId() + "&id=" + item.getVideoId();
|
||||
/**
|
||||
* 景区 {{thing1.DATA}}
|
||||
* 备注 {{thing3.DATA}}
|
||||
*/
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
Map<String, Object> dataParam = new HashMap<>();
|
||||
Map<String, String> videoMap = new HashMap<>();
|
||||
videoMap.put("value", title);
|
||||
dataParam.put("thing1", videoMap);
|
||||
Map<String, String> remarkMap = new HashMap<>();
|
||||
remarkMap.put("value", "系统删除前,请下载好您的旅行视频");
|
||||
dataParam.put("thing3", remarkMap);
|
||||
params.put("data", dataParam);
|
||||
params.put("page", page);
|
||||
params.put("template_id", templateId);
|
||||
log.info("视频下载通知模板参数:{},用户ID:{}", params, member.getOpenId());
|
||||
INotifyAdapter adapter = NotifyFactory.get(NotifyType.WX_MP_SRV, scenicMp.toMap());
|
||||
adapter.sendTo(new NotifyContent(title, page, params), member.getOpenId());
|
||||
});
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 20 * * *")
|
||||
public void sendExpireNotification() {
|
||||
log.info("开始执行定时任务");
|
||||
videoMapper.listRelationByCreateTime(new Date(System.currentTimeMillis() - 3 * 24 * 60 * 60 * 1000), new Date(System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000))
|
||||
.forEach(item -> {
|
||||
if (item.getIsBuy() == 1) {
|
||||
return;
|
||||
}
|
||||
MemberRespVO member = memberMapper.getById(item.getMemberId());
|
||||
MpConfigEntity scenicMp = scenicRepository.getScenicMpConfig(member.getScenicId());
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(item.getScenicId());
|
||||
Integer videoStoreDay = scenicConfig.getVideoStoreDay();
|
||||
// 发送模板消息
|
||||
String templateId = scenicRepository.getVideoPreExpireTemplateId(item.getScenicId());
|
||||
if (StringUtils.isBlank(templateId)) {
|
||||
log.info("模板消息为空");
|
||||
return;
|
||||
}
|
||||
log.info("发送模板消息");
|
||||
ScenicEntity scenic = scenicRepository.getScenic(item.getScenicId());
|
||||
String title = "您在【" + scenic.getName() + "】的专属影像";
|
||||
String page = "pages/videoSynthesis/buy?scenicId=" + item.getScenicId() + "&faceId=" + item.getFaceId() + "&id=" + item.getVideoId();
|
||||
/**
|
||||
* 影像名称 {{thing1.DATA}}
|
||||
* 过期时间 {{time2.DATA}}
|
||||
* 备注 {{thing3.DATA}}
|
||||
*/
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
Map<String, Object> dataParam = new HashMap<>();
|
||||
Map<String, String> videoMap = new HashMap<>();
|
||||
videoMap.put("value", title);
|
||||
dataParam.put("thing1", videoMap);
|
||||
Map<String, String> dateMap = new HashMap<>();
|
||||
Date expireDate = new Date(item.getCreateTime().getTime() + videoStoreDay * 24 * 60 * 60 * 1000);
|
||||
dateMap.put("value", DateUtil.format(expireDate, "yyyy-MM-dd HH:mm"));
|
||||
dataParam.put("time2", dateMap);
|
||||
Map<String, String> remarkMap = new HashMap<>();
|
||||
remarkMap.put("value", "视频即将删除,花点小钱买下回忆");
|
||||
dataParam.put("thing3", remarkMap);
|
||||
params.put("data", dataParam);
|
||||
params.put("page", page);
|
||||
params.put("template_id", templateId);
|
||||
log.info("视频下载通知模板参数:{},用户ID:{}", params, member.getOpenId());
|
||||
INotifyAdapter adapter = NotifyFactory.get(NotifyType.WX_MP_SRV, scenicMp.toMap());
|
||||
adapter.sendTo(new NotifyContent(title, page, params), member.getOpenId());
|
||||
});
|
||||
}
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
package com.ycwl.basic.task;
|
||||
|
||||
import com.ycwl.basic.biz.TemplateBiz;
|
||||
import com.ycwl.basic.mapper.DeviceMapper;
|
||||
import com.ycwl.basic.mapper.FaceMapper;
|
||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||
import com.ycwl.basic.mapper.ScenicMapper;
|
||||
import com.ycwl.basic.mapper.TemplateMapper;
|
||||
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||
@ -16,8 +15,13 @@ import com.ycwl.basic.model.pc.template.entity.TemplateConfigEntity;
|
||||
import com.ycwl.basic.model.pc.template.req.TemplateReqQuery;
|
||||
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
|
||||
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
||||
import com.ycwl.basic.repository.FaceRepository;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.repository.TemplateRepository;
|
||||
import com.ycwl.basic.service.task.TaskFaceService;
|
||||
import com.ycwl.basic.service.task.TaskService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
@ -28,6 +32,12 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
|
||||
|
||||
@Component
|
||||
@EnableScheduling
|
||||
@ -45,6 +55,14 @@ public class DynamicTaskGenerator {
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private TemplateBiz templateBiz;
|
||||
@Autowired
|
||||
private FaceSampleMapper faceSampleMapper;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private TemplateRepository templateRepository;
|
||||
@Autowired
|
||||
private FaceRepository faceRepository;
|
||||
|
||||
@Scheduled(cron = "0 0 * * * ?")
|
||||
public void dynamicTask() {
|
||||
@ -113,4 +131,83 @@ public class DynamicTaskGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class Task implements Delayed {
|
||||
public Long faceSampleId;
|
||||
public Date startTime;
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
return unit.convert(startTime.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Delayed o) {
|
||||
return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public static DelayQueue<Task> queue = new DelayQueue<>();
|
||||
|
||||
public static void addTask(Long faceSampleId) {
|
||||
Date createTime = new Date();
|
||||
// 两分钟后
|
||||
createTime.setTime(createTime.getTime() + 120000L);
|
||||
queue.add(new Task(faceSampleId, createTime));
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 30000L)
|
||||
public void doTask() {
|
||||
Task task = queue.poll();
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
log.info("开始执行任务:{}", task);
|
||||
// 根据人脸照片获取人脸样本ID
|
||||
FaceSampleRespVO faceSample = faceSampleMapper.getById(task.getFaceSampleId());
|
||||
if (faceSample == null) {
|
||||
log.info("人脸样本ID{}不存在", task.getFaceSampleId());
|
||||
return;
|
||||
}
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(faceSample.getScenicId());
|
||||
if (scenicConfig == null) {
|
||||
log.info("当前景区{},无配置", faceSample.getScenicId());
|
||||
return;
|
||||
}
|
||||
if (!Integer.valueOf(1).equals(scenicConfig.getBookRoutine()) && !Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
||||
log.info("当前景区{}未启用预约流程,跳过", faceSample.getScenicId());
|
||||
return;
|
||||
}
|
||||
SearchFaceRespVo userDbSearchResult = faceService.searchFace(USER_FACE_DB_NAME, faceSample.getFaceUrl());
|
||||
// 如果人脸样本ID在人脸样本库中,则创建任务
|
||||
if (!userDbSearchResult.getSampleListIds().isEmpty()) {
|
||||
log.info("人脸样本ID在人脸样本库中,创建任务:{}", task);
|
||||
// 找
|
||||
List<Long> faceIdList = userDbSearchResult.getSampleListIds().stream().filter(faceId -> {
|
||||
FaceEntity face = faceRepository.getFace(faceId);
|
||||
if (face == null) {
|
||||
return false;
|
||||
}
|
||||
return face.getScenicId().equals(faceSample.getScenicId());
|
||||
}).collect(Collectors.toList());
|
||||
if (faceIdList.isEmpty()) {
|
||||
log.info("本景区人脸样本ID不在人脸样本库中,忽略任务:{}", task);
|
||||
return;
|
||||
}
|
||||
List<TemplateRespVO> templateList = templateRepository.getTemplateListByScenicId(faceSample.getScenicId());
|
||||
if (templateList == null || templateList.isEmpty()) {
|
||||
log.info("当前景区{},无模板配置", faceSample.getScenicId());
|
||||
return;
|
||||
}
|
||||
faceIdList.forEach(faceId -> {
|
||||
log.info("自动下发任务,人脸ID:{}", faceId);
|
||||
taskService.autoCreateTaskByFaceId(faceId);
|
||||
});
|
||||
} else {
|
||||
log.info("人脸样本ID不在人脸样本库中,忽略任务:{}", task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.ycwl.basic.device.DeviceFactory;
|
||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||
import com.ycwl.basic.mapper.DeviceMapper;
|
||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||
import com.ycwl.basic.model.pc.device.req.DeviceReqQuery;
|
||||
import com.ycwl.basic.model.pc.device.resp.DeviceRespVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -26,8 +27,8 @@ public class VideoPieceCleaner {
|
||||
@Scheduled(cron = "0 0 0 * * ?")
|
||||
public void clean() {
|
||||
log.info("开始删除视频文件");
|
||||
List<DeviceRespVO> deviceList = deviceMapper.list(new DeviceReqQuery());
|
||||
for (DeviceRespVO device : deviceList) {
|
||||
List<DeviceEntity> deviceList = deviceMapper.listAll();
|
||||
for (DeviceEntity device : deviceList) {
|
||||
DeviceConfigEntity config = deviceMapper.getConfigByDeviceId(device.getId());
|
||||
if (config == null) {
|
||||
continue;
|
||||
@ -38,7 +39,7 @@ public class VideoPieceCleaner {
|
||||
if (config.getStoreExpireDay() <= 0) {
|
||||
continue;
|
||||
}
|
||||
IDeviceStorageOperator storageOperator = DeviceFactory.getDeviceStorageOperator(null, config);
|
||||
IDeviceStorageOperator storageOperator = DeviceFactory.getDeviceStorageOperator(device, config);
|
||||
if (storageOperator == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -146,23 +146,33 @@ public class VideoPieceGetter {
|
||||
return;
|
||||
}
|
||||
log.info("查询到可用的文件: {}", listByDtRange);
|
||||
long offset = faceSample.getCreateAt().getTime() - cutPre.multiply(BigDecimal.valueOf(1000)).longValue() - listByDtRange.get(0).getCreateTime().getTime();
|
||||
FfmpegTask ffmpegTask = new FfmpegTask();
|
||||
ffmpegTask.setFileList(listByDtRange);
|
||||
ffmpegTask.setDuration(duration);
|
||||
ffmpegTask.setOffsetStart(BigDecimal.valueOf(offset, 3));
|
||||
File outFile = new File(faceSample.getDeviceId().toString() + "_" + faceSample.getId() + ".mp4");
|
||||
ffmpegTask.setOutputFile(outFile.getAbsolutePath());
|
||||
boolean result = startFfmpegTask(ffmpegTask);
|
||||
if (!result) {
|
||||
log.warn("视频裁切失败");
|
||||
return;
|
||||
// 如果完全一致,就不需要裁切
|
||||
String url;
|
||||
if (
|
||||
listByDtRange.size() != 1 ||
|
||||
(listByDtRange.get(0).getCreateTime().getTime() != faceSample.getCreateAt().getTime() - cutPre.multiply(BigDecimal.valueOf(1000)).longValue()
|
||||
|| listByDtRange.get(0).getEndTime().getTime() != faceSample.getCreateAt().getTime() + cutPost.multiply(BigDecimal.valueOf(1000)).longValue())
|
||||
) {
|
||||
long offset = faceSample.getCreateAt().getTime() - cutPre.multiply(BigDecimal.valueOf(1000)).longValue() - listByDtRange.get(0).getCreateTime().getTime();
|
||||
FfmpegTask ffmpegTask = new FfmpegTask();
|
||||
ffmpegTask.setFileList(listByDtRange);
|
||||
ffmpegTask.setDuration(duration);
|
||||
ffmpegTask.setOffsetStart(BigDecimal.valueOf(offset, 3));
|
||||
File outFile = new File(faceSample.getDeviceId().toString() + "_" + faceSample.getId() + ".mp4");
|
||||
ffmpegTask.setOutputFile(outFile.getAbsolutePath());
|
||||
boolean result = startFfmpegTask(ffmpegTask);
|
||||
if (!result) {
|
||||
log.warn("视频裁切失败");
|
||||
return;
|
||||
}
|
||||
log.info("视频裁切成功");
|
||||
IStorageAdapter adapter = StorageFactory.use("assets");
|
||||
url = adapter.uploadFile(outFile, "video-source", outFile.getName());
|
||||
// 上传成功后删除文件
|
||||
outFile.delete();
|
||||
} else {
|
||||
url = listByDtRange.get(0).getUrl();
|
||||
}
|
||||
log.info("视频裁切成功");
|
||||
IStorageAdapter adapter = StorageFactory.use("assets");
|
||||
String url = adapter.uploadFile(outFile, "video-source", outFile.getName());
|
||||
// 上传成功后删除文件
|
||||
outFile.delete();
|
||||
SourceEntity imgSource = sourceMapper.findBySampleId(faceSample.getId());
|
||||
SourceEntity sourceEntity = new SourceEntity();
|
||||
sourceEntity.setId(SnowFlakeUtil.getLongId());
|
||||
|
Reference in New Issue
Block a user