水印
This commit is contained in:
parent
7e8eebdef5
commit
180ba67de8
@ -70,4 +70,8 @@ public class ScenicConfigEntity {
|
||||
private String storeConfigJson;
|
||||
private BigDecimal brokerDirectRate;
|
||||
private Integer faceDetectHelperThreshold;
|
||||
|
||||
private String watermarkType;
|
||||
private String watermarkScenicText;
|
||||
private String watermarkDtFormat;
|
||||
}
|
||||
|
168
src/main/java/com/ycwl/basic/task/ImageWatermarkTask.java
Normal file
168
src/main/java/com/ycwl/basic/task/ImageWatermarkTask.java
Normal file
@ -0,0 +1,168 @@
|
||||
package com.ycwl.basic.task;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ycwl.basic.image.watermark.ImageWatermarkFactory;
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
|
||||
import com.ycwl.basic.image.watermark.operator.IOperator;
|
||||
import com.ycwl.basic.mapper.SourceMapper;
|
||||
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||
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.model.pc.source.entity.MemberSourceEntity;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||
import com.ycwl.basic.notify.entity.WxMpSrvConfig;
|
||||
import com.ycwl.basic.repository.FaceRepository;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
import com.ycwl.basic.utils.WxMpUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@Component
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
public class ImageWatermarkTask {
|
||||
@Autowired
|
||||
private FaceRepository faceRepository;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private SourceMapper sourceMapper;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public static class Task {
|
||||
public Long memberId;
|
||||
public Long faceId;
|
||||
}
|
||||
|
||||
public static ConcurrentLinkedQueue<Task> queue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public static void addTask(Long memberId, Long faceId) {
|
||||
queue.add(new Task(memberId, faceId));
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 200L)
|
||||
public void doTask() {
|
||||
Task task = queue.poll();
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
log.info("poll task: {}/{}", task, queue.size());
|
||||
new Thread(() -> {
|
||||
try {
|
||||
runTask(task);
|
||||
} catch (Exception e) {
|
||||
log.error("run task error", e);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void runTask(Task task) {
|
||||
// 生成二维码
|
||||
FaceEntity face = faceRepository.getFace(task.faceId);
|
||||
if (face == null) {
|
||||
return;
|
||||
}
|
||||
ScenicEntity scenic = scenicRepository.getScenic(face.getScenicId());
|
||||
if (scenic == null) {
|
||||
return;
|
||||
}
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
|
||||
MpConfigEntity scenicMpConfig = scenicRepository.getScenicMpConfig(face.getScenicId());
|
||||
if (scenicMpConfig == null) {
|
||||
return;
|
||||
}
|
||||
List<SourceEntity> sourceEntities = sourceMapper.listImageByFaceRelation(task.memberId, task.faceId);
|
||||
if (sourceEntities == null || sourceEntities.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
File qrcode = new File("qrcode_"+face.getMemberId()+".jpg");
|
||||
try {
|
||||
String urlLink = WxMpUtil.generateUrlLink(scenicMpConfig.getAppId(), scenicMpConfig.getAppSecret(), "pages/videoSynthesis/index", "scenicId=" + face.getScenicId() + "&faceId=" + face.getId());
|
||||
QrCodeUtil.generate(urlLink + "?cq=", 300, 300, qrcode);
|
||||
} catch (Exception e) {
|
||||
log.error("generateWXQRCode error", e);
|
||||
return;
|
||||
}
|
||||
IStorageAdapter adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
// TODO
|
||||
WatermarkInfo info = new WatermarkInfo();
|
||||
info.setQrcodeFile(qrcode);
|
||||
final ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 128, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(128));
|
||||
for (SourceEntity sourceEntity : sourceEntities) {
|
||||
executor.execute(() -> {
|
||||
String url;
|
||||
try {
|
||||
IOperator operator = ImageWatermarkFactory.get(scenicConfig.getWatermarkType());
|
||||
File dstFile = new File(sourceEntity.getId() + ".jpg");
|
||||
File watermarkedFile = new File(sourceEntity.getId() + "_w.png");
|
||||
try {
|
||||
HttpUtil.downloadFile(sourceEntity.getUrl(), dstFile);
|
||||
} catch (Exception e) {
|
||||
log.error("downloadFile error", e);
|
||||
return;
|
||||
}
|
||||
info.setOriginalFile(dstFile);
|
||||
info.setScenicLine(scenicConfig.getWatermarkScenicText());
|
||||
info.setDatetime(sourceEntity.getCreateTime());
|
||||
info.setDtFormat(scenicConfig.getWatermarkDtFormat());
|
||||
info.setWatermarkedFile(watermarkedFile);
|
||||
try {
|
||||
operator.process(info);
|
||||
} catch (ImageWatermarkException e) {
|
||||
log.error("process error", e);
|
||||
return;
|
||||
}
|
||||
url = adapter.uploadFile(watermarkedFile, "photo_w", watermarkedFile.getName());
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, "photo_w", watermarkedFile.getName());
|
||||
} catch (ImageWatermarkException e) {
|
||||
// 不支持
|
||||
url = sourceEntity.getUrl();
|
||||
}
|
||||
|
||||
MemberSourceEntity memberSource = new MemberSourceEntity();
|
||||
memberSource.setMemberId(task.memberId);
|
||||
memberSource.setScenicId(face.getScenicId());
|
||||
memberSource.setFaceId(task.faceId);
|
||||
memberSource.setType(sourceEntity.getType());
|
||||
memberSource.setSourceId(sourceEntity.getId());
|
||||
memberSource.setWaterUrl(url);
|
||||
sourceMapper.updateWaterUrl(memberSource);
|
||||
});
|
||||
}
|
||||
try {
|
||||
Thread.sleep(2000L);
|
||||
log.info("executor等待被结束![A:{}/T:{}/F:{}]", executor.getActiveCount(), executor.getTaskCount(), executor.getCompletedTaskCount());
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(30, TimeUnit.SECONDS);
|
||||
log.info("executor已结束![A:{}/T:{}/F:{}]", executor.getActiveCount(), executor.getTaskCount(), executor.getCompletedTaskCount());
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,8 @@ import java.io.FileOutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
public class WxMpUtil {
|
||||
private static final String GET_WXA_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s";
|
||||
private static final String GET_WXA_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
|
||||
private static final String GET_URL_LICK_URL = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=%s";
|
||||
|
||||
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
private static String ACCESS_TOKEN = "";
|
||||
@ -61,6 +62,33 @@ public class WxMpUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateUrlLink(String appId, String appSecret, String path, String query) throws Exception {
|
||||
String url = String.format(GET_URL_LICK_URL, getAccessToken(appId, appSecret));
|
||||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("path", path);
|
||||
json.put("query", query);
|
||||
StringEntity entity = new StringEntity(json.toJSONString(), "utf-8");
|
||||
httpPost.setEntity(entity);
|
||||
httpPost.setHeader("Content-Type", "application/json");
|
||||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
expireTime = new Date();
|
||||
throw new Exception("获取小程序码失败");
|
||||
}
|
||||
HttpEntity responseEntity = response.getEntity();
|
||||
if (responseEntity != null) {
|
||||
String responseStr = EntityUtils.toString(responseEntity);
|
||||
JSONObject jsonObject = JSONObject.parseObject(responseStr);
|
||||
return jsonObject.getString("url_link");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
generateWXAQRCode("wxe7ff26af70bfc37c", "5252fbbc68513bc77b7cc0052b9f9695", "trial", "pages/home/index?scenicId=3955650120997015552", "sxlj_t.jpg");
|
||||
}
|
||||
|
@ -107,7 +107,10 @@
|
||||
face_detect_helper_threshold=#{faceDetectHelperThreshold},
|
||||
store_type=#{storeType},
|
||||
store_config_json=#{storeConfigJson},
|
||||
broker_direct_rate=#{brokerDirectRate}
|
||||
broker_direct_rate=#{brokerDirectRate},
|
||||
watermark_type=#{watermarkType},
|
||||
watermark_scenic_text=#{watermarkScenicText},
|
||||
watermark_dt_format=#{watermarkDtFormat}
|
||||
</set>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
@ -38,6 +38,11 @@
|
||||
</set>
|
||||
where member_id = #{memberId} and face_id = #{faceId} and `type` = #{type}
|
||||
</update>
|
||||
<update id="updateWaterUrl">
|
||||
update member_source
|
||||
set water_url = #{waterUrl}
|
||||
where member_id = #{memberId} and source_id = #{sourceId} and `type` = #{type}
|
||||
</update>
|
||||
<delete id="deleteById">
|
||||
delete from source where id = #{id}
|
||||
</delete>
|
||||
|
Loading…
x
Reference in New Issue
Block a user