视频图片儿分析模型。

This commit is contained in:
spllzh
2025-10-12 09:37:43 +08:00
parent b047a3be90
commit 5f2c952a6e
33 changed files with 1935 additions and 104 deletions

View File

@@ -4,13 +4,17 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.entity.DetectVideoTemplate;
import com.rj.mapper.DetectVideoTemplateMapper;
import com.rj.service.IDetectVideoTemplateService;
import com.rj.service.MinIOService;
import com.rj.utils.MinIOUrlGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
@@ -31,6 +35,12 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
@Value("${dashscope.api.key:}")
private String apiKey;
@Autowired
private MinIOService minioService;
@Autowired
private MinIOUrlGenerator urlGenerator;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
@@ -52,10 +62,11 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
/**
* 执行视频模板检测并保存日志
*/
public DetectVideoTemplate detectVideoTemplateAndSave(String videoUrl, String ownerName, String ownerPhone, String avatarName, String model) {
public DetectVideoTemplate detectVideoTemplateAndSave(String videoUrl, String ownerName, String ownerPhone, String templateName, String model) {
if (apiKey == null || apiKey.trim().isEmpty()) {
log.error("DASHSCOPE_API_KEY未配置");
return createErrorLog(videoUrl, "DASHSCOPE_API_KEY未配置", ownerName, ownerPhone, avatarName);
return createErrorLog(videoUrl, "DASHSCOPE_API_KEY未配置", ownerName, ownerPhone, templateName);
}
// 创建日志记录
@@ -65,13 +76,13 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
detectVideoTemplate.setRequestId(requestId);
// 设置模型名称,如果未提供则使用默认值
String modelName = (model != null && !model.trim().isEmpty()) ? model : "video-template-detect";
String modelName = (model != null && !model.trim().isEmpty()) ? model : "animate-anyone-template-gen2";
detectVideoTemplate.setModel(modelName);
log.info("使用模型: {}", modelName);
detectVideoTemplate.setVideoUrl(videoUrl);
detectVideoTemplate.setOwnerName(ownerName);
detectVideoTemplate.setOwnerPhone(ownerPhone);
detectVideoTemplate.setAvatarName(avatarName);
detectVideoTemplate.setTemplateName(templateName);
detectVideoTemplate.setRequestTime(requestTime);
long startTime = System.currentTimeMillis();
@@ -89,20 +100,19 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(apiKey);
// 添加异步调用请求头
headers.set("X-DashScope-Async", "enable");
log.info("发送视频模板检测请求requestBody : {}, 请求参数headers: {}", requestBody , headers);
// 创建请求实体
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
// 发送请求
ResponseEntity<String> response = restTemplate.exchange(
API_URL,
HttpMethod.POST,
requestEntity,
String.class
);
log.info("发送视频模板检测请求请求ID: {}, 视频URL: {}", requestId, videoUrl);
// 发送请求
ResponseEntity<String> response = restTemplate.postForEntity(API_URL, requestEntity, String.class);
log.info("发送视频模板检测请求response: {}, 视频URL: {}", response, videoUrl);
// 计算处理时间
long endTime = System.currentTimeMillis();
@@ -121,48 +131,35 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
if (response.getStatusCode() == HttpStatus.OK) {
JsonNode jsonResponse = objectMapper.readTree(response.getBody());
// 根据success字段判断是否成功
boolean isSuccess = false;
if (jsonResponse.has("output") && jsonResponse.get("output").has("success")) {
isSuccess = jsonResponse.get("output").get("success").asBoolean();
detectVideoTemplate.setSuccess(isSuccess);
log.info("视频模板检测结果 - success: {}", isSuccess);
} else {
// 如果没有success字段则根据HTTP状态码判断
isSuccess = response.getStatusCode().is2xxSuccessful();
detectVideoTemplate.setSuccess(isSuccess);
}
// 检查是否有检测到模板
// 解析响应数据
if (jsonResponse.has("output")) {
JsonNode output = jsonResponse.get("output");
// 解析模板ID
if (output.has("template_id")) {
String templateId = output.get("template_id").asText();
detectVideoTemplate.setTemplateId(templateId);
log.info("检测到的模板ID: {}", templateId);
// 解析任务ID
if (output.has("task_id")) {
String taskId = output.get("task_id").asText();
detectVideoTemplate.setTaskId(taskId);
log.info("任务ID: {}", taskId);
}
// 记录message信息
if (output.has("message")) {
String message = output.get("message").asText();
log.info("检测消息: {}", message);
// 解析任务状态
if (output.has("task_status")) {
String taskStatus = output.get("task_status").asText();
detectVideoTemplate.setTaskStatus(taskStatus);
log.info("任务状态: {}", taskStatus);
// 根据任务状态判断是否成功
boolean isSuccess = "SUCCESS".equalsIgnoreCase(taskStatus) || "COMPLETED".equalsIgnoreCase(taskStatus);
detectVideoTemplate.setSuccess(isSuccess);
}
}
// 记录请求ID
// 记录message信息
if (jsonResponse.has("request_id")) {
String apiRequestId = jsonResponse.get("request_id").asText();
log.info("API请求ID: {}", apiRequestId);
}
// 记录使用情况
if (jsonResponse.has("usage")) {
JsonNode usage = jsonResponse.get("usage");
log.info("使用情况: {}", usage.toString());
String request_id = jsonResponse.get("request_id").asText();
detectVideoTemplate.setRequestId(request_id);
}
} else {
// HTTP状态码不是200直接标记为失败
detectVideoTemplate.setSuccess(false);
@@ -224,14 +221,14 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
/**
* 创建错误日志
*/
private DetectVideoTemplate createErrorLog(String videoUrl, String errorMessage, String ownerName, String ownerPhone, String avatarName) {
private DetectVideoTemplate createErrorLog(String videoUrl, String errorMessage, String ownerName, String ownerPhone, String templateName) {
DetectVideoTemplate detectVideoTemplate = new DetectVideoTemplate();
detectVideoTemplate.setRequestId(UUID.randomUUID().toString());
detectVideoTemplate.setModel("video-template-detect");
detectVideoTemplate.setVideoUrl(videoUrl);
detectVideoTemplate.setOwnerName(ownerName);
detectVideoTemplate.setOwnerPhone(ownerPhone);
detectVideoTemplate.setAvatarName(avatarName);
detectVideoTemplate.setTemplateName(templateName);
detectVideoTemplate.setRequestTime(LocalDateTime.now());
detectVideoTemplate.setResponseTime(LocalDateTime.now());
detectVideoTemplate.setSuccess(false);
@@ -252,7 +249,7 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
@Override
public com.baomidou.mybatisplus.extension.plugins.pagination.Page<DetectVideoTemplate> getPageList(
Integer current, Integer size, Boolean success, String startTime, String endTime,
String ownerName, String ownerPhone, String avatarName) {
String ownerName, String ownerPhone, String templateName) {
com.baomidou.mybatisplus.extension.plugins.pagination.Page<DetectVideoTemplate> page =
new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, size);
@@ -276,8 +273,8 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
if (ownerPhone != null && !ownerPhone.trim().isEmpty()) {
queryWrapper.like(DetectVideoTemplate::getOwnerPhone, ownerPhone);
}
if (avatarName != null && !avatarName.trim().isEmpty()) {
queryWrapper.like(DetectVideoTemplate::getAvatarName, avatarName);
if (templateName != null && !templateName.trim().isEmpty()) {
queryWrapper.like(DetectVideoTemplate::getTemplateName, templateName);
}
// 按请求时间倒序排列
@@ -348,4 +345,92 @@ public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTempl
return statistics;
}
/**
* 上传视频模板文件并进行检测
*/
@Override
public DetectVideoTemplate uploadAndDetectVideoTemplate(MultipartFile file, String userId, String ownerName,
String ownerPhone, String templateName, String model, int expiresInSeconds) {
try {
log.info("开始处理视频模板上传,文件名: {}, 大小: {} bytes, 用户ID: {}",
file.getOriginalFilename(), file.getSize(), userId);
// 1. 验证文件
if (file.isEmpty()) {
return createErrorLog("", "文件不能为空", ownerName, ownerPhone, templateName);
}
// 验证文件类型
String contentType = file.getContentType();
if (contentType == null || (!contentType.startsWith("video/"))) {
return createErrorLog("", "只支持视频文件格式", ownerName, ownerPhone, templateName);
}
// 验证文件大小限制为100MB
if (file.getSize() > 100 * 1024 * 1024) {
return createErrorLog("", "文件大小不能超过100MB", ownerName, ownerPhone, templateName);
}
// 2. 上传文件到MinIO
log.info("开始上传视频文件到MinIO...");
String fileUrl = minioService.uploadFile(file);
log.info("视频文件上传成功URL: {}", fileUrl);
// 3. 生成短链接临时访问URL
log.info("开始生成短链接,有效期: {}秒", expiresInSeconds);
String fileName = extractFileNameFromUrl(fileUrl);
MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName, expiresInSeconds);
if (!urlInfo.isSuccess()) {
return createErrorLog(fileUrl, "生成短链接失败: " + urlInfo.getErrorMessage(), ownerName, ownerPhone, templateName);
}
String shortUrl = urlInfo.getUrl();
log.info("短链接生成成功: {}", shortUrl);
// 4. 进行视频模板检测
log.info("开始进行视频模板检测,使用模型: {}", model != null ? model : "默认模型");
DetectVideoTemplate detectLog = detectVideoTemplateAndSave(shortUrl, ownerName, ownerPhone, templateName, model);
// 5. 更新日志记录,添加文件信息和临时链接信息
detectLog.setVideoUrl(fileUrl);
detectLog.setRequestId(detectLog.getRequestId()); // 保持原有的requestId
detectLog.setTempUrl(shortUrl);
detectLog.setTempUrlExpiresAt(urlInfo.getExpiresAt());
// 如果检测日志中有task_id也保存到数据库
if (detectLog.getTaskId() != null) {
detectLog.setTaskId(detectLog.getTaskId());
}
// 保存更新后的日志
saveDetectVideoTemplateLog(detectLog);
log.info("视频模板上传和检测处理完成文件URL: {}, 短链接: {}", fileUrl, shortUrl);
return detectLog;
} catch (Exception e) {
log.error("视频模板上传和检测失败: {}", e.getMessage(), e);
return createErrorLog("", "视频模板上传和检测失败: " + e.getMessage(), ownerName, ownerPhone, templateName);
}
}
/**
* 从URL中提取文件名
*/
private String extractFileNameFromUrl(String fileUrl) {
if (fileUrl == null || fileUrl.trim().isEmpty()) {
return null;
}
// 从URL中提取文件名
// 例如: http://101.35.52.237:19005/car/20251009_105616_48320fc2d8e24f7bb4be66cbb54a6512.jpg
// 提取: 20251009_105616_48320fc2d8e24f7bb4be66cbb54a6512.jpg
String[] parts = fileUrl.split("/");
if (parts.length > 0) {
return parts[parts.length - 1];
}
return null;
}
}