diff --git a/src/main/java/com/rj/common/PasswordUtil.java b/src/main/java/com/rj/common/PasswordUtil.java index 305b02d..5dead4c 100644 --- a/src/main/java/com/rj/common/PasswordUtil.java +++ b/src/main/java/com/rj/common/PasswordUtil.java @@ -139,6 +139,10 @@ public class PasswordUtil { + + + + diff --git a/src/main/java/com/rj/common/ServiceManager.java b/src/main/java/com/rj/common/ServiceManager.java index 96f6519..bda4159 100644 --- a/src/main/java/com/rj/common/ServiceManager.java +++ b/src/main/java/com/rj/common/ServiceManager.java @@ -123,6 +123,10 @@ public class ServiceManager { + + + + diff --git a/src/main/java/com/rj/config/AliyunConfig.java b/src/main/java/com/rj/config/AliyunConfig.java index d9e6c02..1b791a8 100644 --- a/src/main/java/com/rj/config/AliyunConfig.java +++ b/src/main/java/com/rj/config/AliyunConfig.java @@ -102,6 +102,9 @@ public class AliyunConfig { + + + diff --git a/src/main/java/com/rj/controller/FaceDetectController.java b/src/main/java/com/rj/controller/FaceDetectController.java index e94a1db..470026c 100644 --- a/src/main/java/com/rj/controller/FaceDetectController.java +++ b/src/main/java/com/rj/controller/FaceDetectController.java @@ -45,6 +45,8 @@ public class FaceDetectController { @RequestParam(value = "ownerName", required = false) String ownerName, @Parameter(description = "所属人电话", required = false) @RequestParam(value = "ownerPhone", required = false) String ownerPhone, + @Parameter(description = "模型名称", required = false) + @RequestParam(value = "model", required = false) String model, @Parameter(description = "头像名称", required = false) @RequestParam(value = "avatarName", required = false) String avatarName) { @@ -98,6 +100,8 @@ public class FaceDetectController { @RequestParam(value = "ownerPhone", required = false) String ownerPhone, @Parameter(description = "头像名称", required = false) @RequestParam(value = "avatarName", required = false) String avatarName, + @Parameter(description = "模型名称", required = false) + @RequestParam(value = "model", required = false) String model, @Parameter(description = "短链接有效期(秒),默认1小时", required = false) @RequestParam(value = "expiresInSeconds", defaultValue = "3600") int expiresInSeconds) { @@ -149,8 +153,8 @@ public class FaceDetectController { log.info("短链接生成成功: {}", shortUrl); // 4. 进行人脸检测 - log.info("开始进行人脸检测..."); - com.rj.entity.FaceDetectLog detectLog = faceDetectLogService.detectFaceAndSave(shortUrl, ownerName, ownerPhone, avatarName); + log.info("开始进行人脸检测,使用模型: {}", model != null ? model : "默认模型"); + com.rj.entity.FaceDetectLog detectLog = faceDetectLogService.detectFaceAndSave(shortUrl, ownerName, ownerPhone, avatarName, model); // 5. 构建响应结果 result.put("success", true); @@ -165,6 +169,7 @@ public class FaceDetectController { result.put("ownerName", ownerName); result.put("ownerPhone", ownerPhone); result.put("avatarName", avatarName); + result.put("model", model); // 人脸检测结果 result.put("faceDetection", detectLog.toString()); diff --git a/src/main/java/com/rj/controller/VideoSynthesisFromController.java b/src/main/java/com/rj/controller/VideoSynthesisFromController.java index 690dc2d..f16c30a 100644 --- a/src/main/java/com/rj/controller/VideoSynthesisFromController.java +++ b/src/main/java/com/rj/controller/VideoSynthesisFromController.java @@ -6,6 +6,7 @@ import com.rj.dto.VideoSynthesisRequestDto; import com.rj.entity.VideoSynthesisLog; import com.rj.mapper.VideoSynthesisLogMapper; import com.rj.service.IVideoSynthesisService; +import com.rj.service.MinIOService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -35,6 +36,9 @@ public class VideoSynthesisFromController { @Autowired private VideoSynthesisLogMapper videoSynthesisLogMapper; + + @Autowired + private MinIOService minIOService; /** * 视频合成接口 @@ -256,4 +260,144 @@ public class VideoSynthesisFromController { return ResponseEntity.status(500).body(result); } } + + /** + * 根据MinIO路径播放视频 + */ + @GetMapping("/play/{minioPath}") + @Operation(summary = "播放视频", description = "根据MinIO路径生成预签名URL播放视频") + public ResponseEntity> playVideo( + @Parameter(description = "MinIO文件路径", required = true) + @PathVariable String minioPath, + @Parameter(description = "过期时间(秒),默认7天", required = false) + @RequestParam(value = "expires", defaultValue = "900") int expires) { + + Map result = new HashMap<>(); + + try { + log.info("开始生成视频播放URL,MinIO路径: {}, 过期时间: {}秒", minioPath, expires); + + // 验证路径格式 + if (minioPath == null || minioPath.trim().isEmpty()) { + result.put("success", false); + result.put("message", "MinIO路径不能为空"); + return ResponseEntity.badRequest().body(result); + } + + // 清理路径,移除开头的斜杠 + String cleanPath = minioPath.startsWith("/") ? minioPath.substring(1) : minioPath; + + // 生成预签名URL + String presignedUrl = minIOService.getPresignedUrl(cleanPath, expires); + + if (presignedUrl == null || presignedUrl.trim().isEmpty()) { + result.put("success", false); + result.put("message", "生成预签名URL失败"); + return ResponseEntity.internalServerError().body(result); + } + + // 构建响应结果 + result.put("success", true); + result.put("message", "视频播放URL生成成功"); + result.put("minioPath", minioPath); + result.put("presignedUrl", presignedUrl); + result.put("expires", expires); + result.put("expiresInDays", expires / 86400); // 转换为天数 + + log.info("视频播放URL生成成功: {}", presignedUrl); + return ResponseEntity.ok(result); + + } catch (Exception e) { + log.error("生成视频播放URL失败: {}", e.getMessage(), e); + result.put("success", false); + result.put("message", "生成视频播放URL失败: " + e.getMessage()); + return ResponseEntity.internalServerError().body(result); + } + } + + /** + * 根据任务ID播放视频 + */ + @GetMapping("/play/task/{taskId}") + @Operation(summary = "根据任务ID播放视频", description = "根据任务ID查找视频并生成播放URL") + public ResponseEntity> playVideoByTaskId( + @Parameter(description = "任务ID", required = true) + @PathVariable String taskId, + @Parameter(description = "过期时间(秒),默认7天", required = false) + @RequestParam(value = "expires", defaultValue = "604800") int expires) { + + Map result = new HashMap<>(); + + try { + log.info("开始根据任务ID播放视频,任务ID: {}, 过期时间: {}秒", taskId, expires); + + // 根据任务ID查询视频合成记录 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("task_id", taskId); + VideoSynthesisLog synthesisLog = videoSynthesisLogMapper.selectOne(queryWrapper); + + if (synthesisLog == null) { + result.put("success", false); + result.put("message", "未找到对应的视频合成记录"); + return ResponseEntity.notFound().build(); + } + + if (synthesisLog.getVideoUrl() == null || synthesisLog.getVideoUrl().trim().isEmpty()) { + result.put("success", false); + result.put("message", "视频URL为空,可能视频还未生成完成"); + return ResponseEntity.badRequest().body(result); + } + + // 从videoUrl中提取MinIO路径 + String videoUrl = synthesisLog.getVideoUrl(); + String minioPath; + + // 判断是否为MinIO URL格式 + if (videoUrl.contains("/minio/")) { + // 从MinIO URL中提取路径 + String[] parts = videoUrl.split("/minio/"); + if (parts.length > 1) { + minioPath = parts[1]; + } else { + result.put("success", false); + result.put("message", "无法从视频URL中提取MinIO路径"); + return ResponseEntity.badRequest().body(result); + } + } else { + // 假设直接是MinIO路径 + minioPath = videoUrl; + } + + // 生成预签名URL + String presignedUrl = minIOService.getPresignedUrl(minioPath, expires); + + if (presignedUrl == null || presignedUrl.trim().isEmpty()) { + result.put("success", false); + result.put("message", "生成预签名URL失败"); + return ResponseEntity.internalServerError().body(result); + } + + // 构建响应结果 + result.put("success", true); + result.put("message", "视频播放URL生成成功"); + result.put("taskId", taskId); + result.put("requestId", synthesisLog.getRequestId()); + result.put("videoName", synthesisLog.getVideoName()); + result.put("minioPath", minioPath); + result.put("presignedUrl", presignedUrl); + result.put("expires", expires); + result.put("expiresInDays", expires / 86400); + result.put("taskStatus", synthesisLog.getTaskStatus()); + result.put("success", synthesisLog.getSuccess()); + + log.info("根据任务ID生成视频播放URL成功: {}", presignedUrl); + return ResponseEntity.ok(result); + + } catch (Exception e) { + log.error("根据任务ID生成视频播放URL失败: {}", e.getMessage(), e); + result.put("success", false); + result.put("message", "生成视频播放URL失败: " + e.getMessage()); + return ResponseEntity.internalServerError().body(result); + } + } } diff --git a/src/main/java/com/rj/controller/sys/MenuController.java b/src/main/java/com/rj/controller/sys/MenuController.java index a7b172d..caf4bf1 100644 --- a/src/main/java/com/rj/controller/sys/MenuController.java +++ b/src/main/java/com/rj/controller/sys/MenuController.java @@ -361,6 +361,10 @@ public class MenuController { + + + + diff --git a/src/main/java/com/rj/controller/sys/RoleController.java b/src/main/java/com/rj/controller/sys/RoleController.java index 971f828..31ba591 100644 --- a/src/main/java/com/rj/controller/sys/RoleController.java +++ b/src/main/java/com/rj/controller/sys/RoleController.java @@ -331,6 +331,10 @@ public class RoleController { + + + + diff --git a/src/main/java/com/rj/controller/sys/UserRoleController.java b/src/main/java/com/rj/controller/sys/UserRoleController.java index 032e8a3..6b5e3d5 100644 --- a/src/main/java/com/rj/controller/sys/UserRoleController.java +++ b/src/main/java/com/rj/controller/sys/UserRoleController.java @@ -337,6 +337,10 @@ public class UserRoleController { + + + + diff --git a/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java b/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java index 7fa8cb7..ce0ecc4 100644 --- a/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java +++ b/src/main/java/com/rj/dto/DifyWorkflowResponseDto.java @@ -105,6 +105,9 @@ public class DifyWorkflowResponseDto { + + + diff --git a/src/main/java/com/rj/dto/VideoSynthesisRequestDto.java b/src/main/java/com/rj/dto/VideoSynthesisRequestDto.java index 9974c48..b9e7a82 100644 --- a/src/main/java/com/rj/dto/VideoSynthesisRequestDto.java +++ b/src/main/java/com/rj/dto/VideoSynthesisRequestDto.java @@ -65,6 +65,12 @@ public class VideoSynthesisRequestDto { @Schema(description = "头部动作强度", example = "0.7") private BigDecimal headMoveStrength = new BigDecimal("0.7"); + @Schema(description = "人脸区域坐标 [x1, y1, x2, y2]", example = "[302,286,610,593]") + private String faceBbox; + + @Schema(description = "动态区域坐标 [x1, y1, x2, y2]", example = "[71,9,840,778]") + private String extBbox; + @Schema(description = "输入数据", example = "{\"image_url\": \"http://xxx/1.jpg\", \"audio_url\": \"http://xxx/1.wav\"}") private Map input; diff --git a/src/main/java/com/rj/entity/FaceDetectLog.java b/src/main/java/com/rj/entity/FaceDetectLog.java index 6e8b68e..96005eb 100644 --- a/src/main/java/com/rj/entity/FaceDetectLog.java +++ b/src/main/java/com/rj/entity/FaceDetectLog.java @@ -94,6 +94,18 @@ public class FaceDetectLog implements Serializable { @TableField("face_count") private Integer faceCount; + /** + * 人脸区域坐标 [x1, y1, x2, y2] + */ + @TableField("face_bbox") + private String faceBbox; + + /** + * 动态区域坐标 [x1, y1, x2, y2] + */ + @TableField("ext_bbox") + private String extBbox; + /** * 完整响应数据 */ diff --git a/src/main/java/com/rj/entity/VideoSynthesisLog.java b/src/main/java/com/rj/entity/VideoSynthesisLog.java index 3e12335..16834cd 100644 --- a/src/main/java/com/rj/entity/VideoSynthesisLog.java +++ b/src/main/java/com/rj/entity/VideoSynthesisLog.java @@ -157,6 +157,18 @@ public class VideoSynthesisLog { @TableField("video_temp_url") private String videoTempUrl; + /** + * 人脸区域坐标 [x1, y1, x2, y2] + */ + @TableField("face_bbox") + private String faceBbox; + + /** + * 动态区域坐标 [x1, y1, x2, y2] + */ + @TableField("ext_bbox") + private String extBbox; + /** * 视频时长(秒) */ diff --git a/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java b/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java index c60979c..7ec47fd 100644 --- a/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java +++ b/src/main/java/com/rj/mapper/CustomerProfileAnalysisMapper.java @@ -48,6 +48,9 @@ public interface CustomerProfileAnalysisMapper extends BaseMapper 0) { @@ -365,6 +388,7 @@ public class VideoSynthesisStatusScheduler { } } + /** * 生成临时视频访问URL * @@ -374,14 +398,7 @@ public class VideoSynthesisStatusScheduler { */ private String generateTempVideoUrl(String videoName, String requestId) { try { - // 构建临时访问URL - // 格式: https://your-domain.com/video/temp/{requestId}?name={videoName} - String baseUrl = "https://your-domain.com"; // 这里应该从配置文件读取 - String encodedVideoName = java.net.URLEncoder.encode(videoName, "UTF-8"); - String tempUrl = String.format("%s/video/temp/%s?name=%s", baseUrl, requestId, encodedVideoName); - - log.info("生成临时视频URL: 视频名称={}, 请求ID={}, URL={}", videoName, requestId, tempUrl); - return tempUrl; + return urlGenerator.generateTempUrl(videoName,7, TimeUnit.DAYS).getUrl(); } catch (Exception e) { log.error("生成临时视频URL失败: {}", e.getMessage(), e); diff --git a/src/main/java/com/rj/service/IFaceDetectLogService.java b/src/main/java/com/rj/service/IFaceDetectLogService.java index aa2a994..d995214 100644 --- a/src/main/java/com/rj/service/IFaceDetectLogService.java +++ b/src/main/java/com/rj/service/IFaceDetectLogService.java @@ -33,6 +33,17 @@ public interface IFaceDetectLogService extends IService { */ FaceDetectLog detectFaceAndSave(String imageUrl, String ownerName, String ownerPhone, String avatarName); + /** + * 执行人脸检测并保存日志(带扩展信息和模型名) + * @param imageUrl 图片URL + * @param ownerName 所属人姓名 + * @param ownerPhone 所属人电话 + * @param avatarName 头像名称 + * @param model 模型名称 + * @return 人脸检测日志对象 + */ + FaceDetectLog detectFaceAndSave(String imageUrl, String ownerName, String ownerPhone, String avatarName, String model); + /** * 分页查询人脸检测日志 * @param current 当前页 diff --git a/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java b/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java index 20b44f5..adf860b 100644 --- a/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java +++ b/src/main/java/com/rj/service/biz/ICustomerProfileAnalysisService.java @@ -69,6 +69,9 @@ public interface ICustomerProfileAnalysisService extends IService requestBody = new HashMap<>(); - requestBody.put("model", "liveportrait-detect"); - + requestBody.put("model", modelName); + + if (modelName.equals("emo-detect-v1")){ + Map ratioo = new HashMap<>(); + ratioo.put("ratio", "1:1"); + requestBody.put("parameters", ratioo); + } + Map input = new HashMap<>(); input.put("image_url", imageUrl); requestBody.put("input", input); @@ -93,8 +109,8 @@ public class FaceDetectLogServiceImpl extends ServiceImpl> requestEntity = new HttpEntity<>(requestBody, headers); // 发送请求 @@ -131,23 +147,50 @@ public class FaceDetectLogServiceImpl extends ServiceImpl { + + + + diff --git a/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java b/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java index 30135a1..77c550f 100644 --- a/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/MenuServiceImpl.java @@ -74,6 +74,10 @@ public class MenuServiceImpl extends ServiceImpl implements IM + + + + diff --git a/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java b/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java index 742a0f8..c8a068e 100644 --- a/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/RoleServiceImpl.java @@ -74,6 +74,10 @@ public class RoleServiceImpl extends ServiceImpl implements IR + + + + diff --git a/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java b/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java index 215934b..e34b170 100644 --- a/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java +++ b/src/main/java/com/rj/service/sys/impl/UserRoleServiceImpl.java @@ -74,6 +74,10 @@ public class UserRoleServiceImpl extends ServiceImpl i + + + + diff --git a/src/main/resources/application-audio.yml b/src/main/resources/application-audio.yml index 7d3511d..b13ac21 100644 --- a/src/main/resources/application-audio.yml +++ b/src/main/resources/application-audio.yml @@ -85,6 +85,9 @@ spring: + + + diff --git a/src/main/resources/mapper/AudioManagementStatisticsMapper.xml b/src/main/resources/mapper/AudioManagementStatisticsMapper.xml index 7b1f61b..6f4b19c 100644 --- a/src/main/resources/mapper/AudioManagementStatisticsMapper.xml +++ b/src/main/resources/mapper/AudioManagementStatisticsMapper.xml @@ -60,6 +60,10 @@ + + + + diff --git a/src/main/resources/static/tts-demo.html b/src/main/resources/static/tts-demo.html index 0c17127..331d871 100644 --- a/src/main/resources/static/tts-demo.html +++ b/src/main/resources/static/tts-demo.html @@ -265,3 +265,6 @@ + + + diff --git a/src/main/sql/add_audio_management_sales_phone.sql b/src/main/sql/add_audio_management_sales_phone.sql index 47fe7cc..dcb9c3e 100644 --- a/src/main/sql/add_audio_management_sales_phone.sql +++ b/src/main/sql/add_audio_management_sales_phone.sql @@ -22,6 +22,9 @@ AFTER `sales_name`; + + + diff --git a/src/main/sql/add_audio_name_to_tts_request_log.sql b/src/main/sql/add_audio_name_to_tts_request_log.sql index 9bf5087..825ac0f 100644 --- a/src/main/sql/add_audio_name_to_tts_request_log.sql +++ b/src/main/sql/add_audio_name_to_tts_request_log.sql @@ -14,3 +14,6 @@ ADD INDEX `idx_audio_name` (`audio_name`); + + + diff --git a/src/test/java/com/rj/service/TtsRequestLogShortUrlTest.java b/src/test/java/com/rj/service/TtsRequestLogShortUrlTest.java index ebcb1cc..5c6557f 100644 --- a/src/test/java/com/rj/service/TtsRequestLogShortUrlTest.java +++ b/src/test/java/com/rj/service/TtsRequestLogShortUrlTest.java @@ -144,3 +144,6 @@ public class TtsRequestLogShortUrlTest { + + +