设备关联逻辑
This commit is contained in:
parent
fb530a1eb4
commit
bcf8e8e88d
@ -60,4 +60,5 @@ public class DeviceConfigEntity {
|
|||||||
private Integer enablePreBook;
|
private Integer enablePreBook;
|
||||||
private Integer imageFree;
|
private Integer imageFree;
|
||||||
private Integer videoFree;
|
private Integer videoFree;
|
||||||
|
private Long pairDevice;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.ycwl.basic.device.DeviceFactory;
|
|||||||
import com.ycwl.basic.device.entity.common.FileObject;
|
import com.ycwl.basic.device.entity.common.FileObject;
|
||||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||||
|
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
||||||
import com.ycwl.basic.repository.DeviceRepository;
|
import com.ycwl.basic.repository.DeviceRepository;
|
||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
@ -20,6 +21,7 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
|||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
@ -35,7 +37,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -117,6 +121,18 @@ public class VideoPieceGetter {
|
|||||||
final ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 512, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(512));
|
final ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 512, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(512));
|
||||||
List<String> currentPlaceholder = new ArrayList<>();
|
List<String> currentPlaceholder = new ArrayList<>();
|
||||||
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
||||||
|
Map<Long, Long> pairDeviceMap = new ConcurrentHashMap<>();
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
Long scenicId = list.get(0).getScenicId();
|
||||||
|
List<DeviceEntity> allDeviceByScenicId = deviceRepository.getAllDeviceByScenicId(scenicId);
|
||||||
|
allDeviceByScenicId.forEach(device -> {
|
||||||
|
Long deviceId = device.getId();
|
||||||
|
DeviceConfigEntity deviceConfig = deviceRepository.getDeviceConfig(deviceId);
|
||||||
|
if (deviceConfig != null && deviceConfig.getPairDevice() != null) {
|
||||||
|
pairDeviceMap.putIfAbsent(deviceId, deviceConfig.getPairDevice());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Collection<List<FaceSampleEntity>> collection = list.stream()
|
Collection<List<FaceSampleEntity>> collection = list.stream()
|
||||||
.filter(faceSample -> {
|
.filter(faceSample -> {
|
||||||
if (templatePlaceholder != null) {
|
if (templatePlaceholder != null) {
|
||||||
@ -136,125 +152,47 @@ public class VideoPieceGetter {
|
|||||||
} catch (InterruptedException ignore) {
|
} catch (InterruptedException ignore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isFirst.set(false);
|
if (pairDeviceMap.containsValue(faceSample.getDeviceId())) {
|
||||||
|
// 有关联设备!
|
||||||
|
// 找到对应的deviceId
|
||||||
|
pairDeviceMap.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getValue().equals(faceSample.getDeviceId()))
|
||||||
|
.map(Map.Entry::getKey).forEach(pairDeviceId -> {
|
||||||
|
log.info("找到同景区关联设备:{} -> {}", pairDeviceId, faceSample.getDeviceId());
|
||||||
|
if (pairDeviceId != null) {
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
DeviceEntity device = deviceRepository.getDevice(faceSample.getDeviceId());
|
boolean result = doCut(pairDeviceId, faceSample.getId(), faceSample.getCreateAt(), task);
|
||||||
DeviceConfigEntity config = deviceRepository.getDeviceConfig(faceSample.getDeviceId());
|
|
||||||
|
|
||||||
SourceEntity source = sourceMapper.querySameVideo(faceSample.getId(), device.getId());
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
BigDecimal cutPre = BigDecimal.valueOf(5L);
|
|
||||||
BigDecimal cutPost = BigDecimal.valueOf(4L);
|
|
||||||
if (config == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 有配置
|
|
||||||
if (config.getCutPre() != null) {
|
|
||||||
cutPre = config.getCutPre();
|
|
||||||
}
|
|
||||||
if (config.getCutPost() != null) {
|
|
||||||
cutPost = config.getCutPost();
|
|
||||||
}
|
|
||||||
IDeviceStorageOperator pieceGetter = DeviceFactory.getDeviceStorageOperator(device, config);
|
|
||||||
if (pieceGetter == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BigDecimal duration = cutPre.add(cutPost);
|
|
||||||
List<FileObject> listByDtRange = pieceGetter.getFileListByDtRange(
|
|
||||||
new Date(faceSample.getCreateAt().getTime() - cutPre.multiply(BigDecimal.valueOf(1000)).longValue()),
|
|
||||||
new Date(faceSample.getCreateAt().getTime() + cutPost.multiply(BigDecimal.valueOf(1000)).longValue())
|
|
||||||
);
|
|
||||||
if (listByDtRange.isEmpty()) {
|
|
||||||
log.warn("没有可用的文件");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.info("查询到可用的文件: {}", listByDtRange);
|
|
||||||
// 如果完全一致,就不需要裁切
|
|
||||||
String url;
|
|
||||||
if (listByDtRange.size() == 1 && listByDtRange.get(0).isExact()) {
|
|
||||||
url = listByDtRange.get(0).getUrl();
|
|
||||||
} else {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
SourceEntity imgSource = sourceMapper.findBySampleId(faceSample.getId());
|
|
||||||
SourceEntity sourceEntity = new SourceEntity();
|
|
||||||
sourceEntity.setId(SnowFlakeUtil.getLongId());
|
|
||||||
sourceEntity.setCreateTime(faceSample.getCreateAt());
|
|
||||||
if (imgSource != null) {
|
|
||||||
sourceEntity.setUrl(imgSource.getUrl());
|
|
||||||
sourceEntity.setPosJson(imgSource.getPosJson());
|
|
||||||
}
|
|
||||||
sourceEntity.setVideoUrl(url);
|
|
||||||
sourceEntity.setFaceSampleId(faceSample.getId());
|
|
||||||
sourceEntity.setScenicId(faceSample.getScenicId());
|
|
||||||
sourceEntity.setDeviceId(faceSample.getDeviceId());
|
|
||||||
sourceEntity.setType(1);
|
|
||||||
if (task.memberId != null && task.faceId != null) {
|
|
||||||
MemberSourceEntity videoSource = new MemberSourceEntity();
|
|
||||||
videoSource.setMemberId(task.getMemberId());
|
|
||||||
videoSource.setType(1);
|
|
||||||
videoSource.setFaceId(task.getFaceId());
|
|
||||||
videoSource.setScenicId(faceSample.getScenicId());
|
|
||||||
videoSource.setSourceId(sourceEntity.getId());
|
|
||||||
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), faceSample.getScenicId(), 1, task.getFaceId());
|
|
||||||
if (isBuy.isBuy()) { // 如果用户买过
|
|
||||||
videoSource.setIsBuy(1);
|
|
||||||
} else if (isBuy.isFree()) { // 全免费逻辑
|
|
||||||
videoSource.setIsBuy(1);
|
|
||||||
} else {
|
|
||||||
videoSource.setIsBuy(0);
|
|
||||||
}
|
|
||||||
sourceMapper.addRelation(videoSource);
|
|
||||||
}
|
|
||||||
sourceMapper.add(sourceEntity);
|
|
||||||
} else {
|
|
||||||
// 有原视频
|
|
||||||
if (task.memberId != null && task.faceId != null) {
|
|
||||||
int count = sourceMapper.hasRelationTo(task.getMemberId(), source.getId(), 1);
|
|
||||||
if (count <= 0) {
|
|
||||||
// 没有关联
|
|
||||||
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), faceSample.getScenicId(), 1, task.getFaceId());
|
|
||||||
MemberSourceEntity videoSource = new MemberSourceEntity();
|
|
||||||
videoSource.setId(SnowFlakeUtil.getLongId());
|
|
||||||
videoSource.setScenicId(faceSample.getScenicId());
|
|
||||||
videoSource.setFaceId(task.getFaceId());
|
|
||||||
videoSource.setMemberId(task.getMemberId());
|
|
||||||
videoSource.setType(1);
|
|
||||||
if (isBuy.isBuy()) { // 如果用户买过
|
|
||||||
videoSource.setIsBuy(1);
|
|
||||||
} else if (isBuy.isFree()) { // 全免费逻辑
|
|
||||||
videoSource.setIsBuy(1);
|
|
||||||
} else {
|
|
||||||
videoSource.setIsBuy(0);
|
|
||||||
}
|
|
||||||
videoSource.setSourceId(source.getId());
|
|
||||||
sourceMapper.addRelation(videoSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (templatePlaceholder != null) {
|
if (templatePlaceholder != null) {
|
||||||
if (templatePlaceholder.contains(faceSample.getDeviceId().toString())) {
|
if (templatePlaceholder.contains(faceSample.getDeviceId().toString())) {
|
||||||
if (!currentPlaceholder.contains(faceSample.getDeviceId().toString())) {
|
if (!currentPlaceholder.contains(faceSample.getDeviceId().toString())) {
|
||||||
|
if (result) {
|
||||||
currentPlaceholder.add(faceSample.getDeviceId().toString());
|
currentPlaceholder.add(faceSample.getDeviceId().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
log.info("当前进度:{}/{}", currentPlaceholder.size(), collection.size());
|
||||||
|
if (currentPlaceholder.size() >= collection.size()) {
|
||||||
|
if (!invoke.get()) {
|
||||||
|
invoke.set(true);
|
||||||
|
task.getCallback().onInvoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
isFirst.set(false);
|
||||||
|
executor.execute(() -> {
|
||||||
|
boolean result = doCut(faceSample.getDeviceId(), faceSample.getId(), faceSample.getCreateAt(), task);
|
||||||
|
if (templatePlaceholder != null) {
|
||||||
|
if (templatePlaceholder.contains(faceSample.getDeviceId().toString())) {
|
||||||
|
if (!currentPlaceholder.contains(faceSample.getDeviceId().toString())) {
|
||||||
|
if (result) {
|
||||||
|
currentPlaceholder.add(faceSample.getDeviceId().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
log.info("当前进度:{}/{}", currentPlaceholder.size(), collection.size());
|
log.info("当前进度:{}/{}", currentPlaceholder.size(), collection.size());
|
||||||
if (currentPlaceholder.size() >= collection.size()) {
|
if (currentPlaceholder.size() >= collection.size()) {
|
||||||
if (!invoke.get()) {
|
if (!invoke.get()) {
|
||||||
@ -288,6 +226,120 @@ public class VideoPieceGetter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean doCut(Long deviceId, Long faceSampleId, Date baseTime, Task task) {
|
||||||
|
DeviceEntity device = deviceRepository.getDevice(deviceId);
|
||||||
|
DeviceConfigEntity config = deviceRepository.getDeviceConfig(deviceId);
|
||||||
|
|
||||||
|
SourceEntity source = sourceMapper.querySameVideo(faceSampleId, device.getId());
|
||||||
|
|
||||||
|
if (source == null) {
|
||||||
|
BigDecimal cutPre = BigDecimal.valueOf(5L);
|
||||||
|
BigDecimal cutPost = BigDecimal.valueOf(4L);
|
||||||
|
if (config != null) {
|
||||||
|
// 有配置
|
||||||
|
if (config.getCutPre() != null) {
|
||||||
|
cutPre = config.getCutPre();
|
||||||
|
}
|
||||||
|
if (config.getCutPost() != null) {
|
||||||
|
cutPost = config.getCutPost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDeviceStorageOperator pieceGetter = DeviceFactory.getDeviceStorageOperator(device, config);
|
||||||
|
if (pieceGetter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BigDecimal duration = cutPre.add(cutPost);
|
||||||
|
List<FileObject> listByDtRange = pieceGetter.getFileListByDtRange(
|
||||||
|
new Date(baseTime.getTime() - cutPre.multiply(BigDecimal.valueOf(1000)).longValue()),
|
||||||
|
new Date(baseTime.getTime() + cutPost.multiply(BigDecimal.valueOf(1000)).longValue())
|
||||||
|
);
|
||||||
|
if (listByDtRange.isEmpty()) {
|
||||||
|
log.warn("没有可用的文件");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.info("查询到可用的文件: {}", listByDtRange);
|
||||||
|
// 如果完全一致,就不需要裁切
|
||||||
|
String url;
|
||||||
|
if (listByDtRange.size() == 1 && listByDtRange.get(0).isExact()) {
|
||||||
|
url = listByDtRange.get(0).getUrl();
|
||||||
|
} else {
|
||||||
|
long offset = baseTime.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(deviceId.toString() + "_" + faceSampleId + ".mp4");
|
||||||
|
ffmpegTask.setOutputFile(outFile.getAbsolutePath());
|
||||||
|
boolean result = startFfmpegTask(ffmpegTask);
|
||||||
|
if (!result) {
|
||||||
|
log.warn("视频裁切失败");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log.info("视频裁切成功");
|
||||||
|
IStorageAdapter adapter = StorageFactory.use("assets");
|
||||||
|
url = adapter.uploadFile(outFile, "video-source", outFile.getName());
|
||||||
|
// 上传成功后删除文件
|
||||||
|
outFile.delete();
|
||||||
|
}
|
||||||
|
SourceEntity imgSource = sourceMapper.findBySampleId(faceSampleId);
|
||||||
|
SourceEntity sourceEntity = new SourceEntity();
|
||||||
|
sourceEntity.setId(SnowFlakeUtil.getLongId());
|
||||||
|
sourceEntity.setCreateTime(baseTime);
|
||||||
|
if (imgSource != null) {
|
||||||
|
sourceEntity.setUrl(imgSource.getUrl());
|
||||||
|
sourceEntity.setPosJson(imgSource.getPosJson());
|
||||||
|
}
|
||||||
|
sourceEntity.setVideoUrl(url);
|
||||||
|
sourceEntity.setFaceSampleId(faceSampleId);
|
||||||
|
sourceEntity.setScenicId(device.getScenicId());
|
||||||
|
sourceEntity.setDeviceId(deviceId);
|
||||||
|
sourceEntity.setType(1);
|
||||||
|
if (task.memberId != null && task.faceId != null) {
|
||||||
|
MemberSourceEntity videoSource = new MemberSourceEntity();
|
||||||
|
videoSource.setMemberId(task.getMemberId());
|
||||||
|
videoSource.setType(1);
|
||||||
|
videoSource.setFaceId(task.getFaceId());
|
||||||
|
videoSource.setScenicId(device.getScenicId());
|
||||||
|
videoSource.setSourceId(sourceEntity.getId());
|
||||||
|
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), device.getScenicId(), 1, task.getFaceId());
|
||||||
|
if (isBuy.isBuy()) { // 如果用户买过
|
||||||
|
videoSource.setIsBuy(1);
|
||||||
|
} else if (isBuy.isFree()) { // 全免费逻辑
|
||||||
|
videoSource.setIsBuy(1);
|
||||||
|
} else {
|
||||||
|
videoSource.setIsBuy(0);
|
||||||
|
}
|
||||||
|
sourceMapper.addRelation(videoSource);
|
||||||
|
}
|
||||||
|
sourceMapper.add(sourceEntity);
|
||||||
|
} else {
|
||||||
|
// 有原视频
|
||||||
|
if (task.memberId != null && task.faceId != null) {
|
||||||
|
int count = sourceMapper.hasRelationTo(task.getMemberId(), source.getId(), 1);
|
||||||
|
if (count <= 0) {
|
||||||
|
// 没有关联
|
||||||
|
IsBuyRespVO isBuy = orderBiz.isBuy(task.getMemberId(), device.getScenicId(), 1, task.getFaceId());
|
||||||
|
MemberSourceEntity videoSource = new MemberSourceEntity();
|
||||||
|
videoSource.setId(SnowFlakeUtil.getLongId());
|
||||||
|
videoSource.setScenicId(device.getScenicId());
|
||||||
|
videoSource.setFaceId(task.getFaceId());
|
||||||
|
videoSource.setMemberId(task.getMemberId());
|
||||||
|
videoSource.setType(1);
|
||||||
|
if (isBuy.isBuy()) { // 如果用户买过
|
||||||
|
videoSource.setIsBuy(1);
|
||||||
|
} else if (isBuy.isFree()) { // 全免费逻辑
|
||||||
|
videoSource.setIsBuy(1);
|
||||||
|
} else {
|
||||||
|
videoSource.setIsBuy(0);
|
||||||
|
}
|
||||||
|
videoSource.setSourceId(source.getId());
|
||||||
|
sourceMapper.addRelation(videoSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean startFfmpegTask(FfmpegTask task) {
|
public boolean startFfmpegTask(FfmpegTask task) {
|
||||||
boolean result;
|
boolean result;
|
||||||
if (task.getFileList().size() == 1) {
|
if (task.getFileList().size() == 1) {
|
||||||
|
@ -39,7 +39,8 @@
|
|||||||
cut_post = #{cutPost},
|
cut_post = #{cutPost},
|
||||||
enable_pre_book = #{enablePreBook},
|
enable_pre_book = #{enablePreBook},
|
||||||
image_free = #{imageFree},
|
image_free = #{imageFree},
|
||||||
video_free = #{videoFree}
|
video_free = #{videoFree},
|
||||||
|
pair_device = #{pairDevice}
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
<update id="updateEntity">
|
<update id="updateEntity">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user