Files
smartDriveEE/src/main/java/com/rj/controller/VideoSynthesisFromController.java
2025-10-09 08:38:17 +08:00

404 lines
18 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.rj.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.HashMap;
import java.util.Map;
/**
* 视频合成控制器
*
* @author rj
* @date 2025-01-02
*/
@Slf4j
@RestController
@RequestMapping("/api/video-synthesis")
@Tag(name = "视频合成,根据头像和音频生成视频", description = "视频合成相关接口,根据头像和音频生成视频")
public class VideoSynthesisFromController {
@Autowired
private IVideoSynthesisService videoSynthesisService;
@Autowired
private VideoSynthesisLogMapper videoSynthesisLogMapper;
@Autowired
private MinIOService minIOService;
/**
* 视频合成接口
*/
@PostMapping("/synthesize")
@Operation(summary = "视频合成", description = "根据图片和音频生成视频")
public ResponseEntity<Map<String, Object>> synthesizeVideo(@Valid @RequestBody VideoSynthesisRequestDto requestDto) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始视频合成图片URL: {}, 音频URL: {}", requestDto.getImageUrl(), requestDto.getAudioUrl());
// 执行视频合成
VideoSynthesisLog synthesisLog = videoSynthesisService.synthesizeVideoAndSave(requestDto);
// 构建响应结果
result.put("success", synthesisLog.getSuccess());
result.put("message", synthesisLog.getTaskStatus());
result.put("requestId", synthesisLog.getRequestId());
result.put("taskId", synthesisLog.getTaskId());
result.put("taskStatus", synthesisLog.getTaskStatus());
result.put("videoUrl", synthesisLog.getVideoUrl());
result.put("videoDuration", synthesisLog.getVideoDuration());
result.put("videoRatio", synthesisLog.getVideoRatio());
result.put("processingTimeMs", synthesisLog.getProcessingTimeMs());
result.put("imageId", synthesisLog.getImageId());
result.put("audioId", synthesisLog.getAudioId());
result.put("ownerName", synthesisLog.getOwnerName());
result.put("ownerPhone", synthesisLog.getOwnerPhone());
result.put("modelProvider", synthesisLog.getModelProvider());
if (!synthesisLog.getSuccess()) {
result.put("errorMessage", synthesisLog.getErrorMessage());
return ResponseEntity.badRequest().body(result);
}
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("视频合成失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "视频合成失败: " + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据请求ID查询视频合成结果
*/
@GetMapping("/result/{requestId}")
@Operation(summary = "查询合成结果", description = "根据请求ID查询视频合成结果")
public ResponseEntity<Map<String, Object>> getSynthesisResult(
@Parameter(description = "请求ID", required = true)
@PathVariable String requestId) {
Map<String, Object> result = new HashMap<>();
try {
VideoSynthesisLog synthesisLog = videoSynthesisService.getVideoSynthesisLogByRequestId(requestId);
if (synthesisLog == null) {
result.put("success", false);
result.put("message", "未找到对应的视频合成记录");
return ResponseEntity.notFound().build();
}
result.put("success", true);
result.put("message", "查询成功");
result.put("requestId", synthesisLog.getRequestId());
result.put("taskId", synthesisLog.getTaskId());
result.put("taskStatus", synthesisLog.getTaskStatus());
result.put("videoUrl", synthesisLog.getVideoUrl());
result.put("videoDuration", synthesisLog.getVideoDuration());
result.put("videoRatio", synthesisLog.getVideoRatio());
result.put("processingTimeMs", synthesisLog.getProcessingTimeMs());
result.put("requestTime", synthesisLog.getRequestTime());
result.put("responseTime", synthesisLog.getResponseTime());
result.put("imageId", synthesisLog.getImageId());
result.put("audioId", synthesisLog.getAudioId());
result.put("ownerName", synthesisLog.getOwnerName());
result.put("ownerPhone", synthesisLog.getOwnerPhone());
result.put("modelProvider", synthesisLog.getModelProvider());
if (!synthesisLog.getSuccess()) {
result.put("errorMessage", synthesisLog.getErrorMessage());
}
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("查询视频合成结果失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据任务ID查询视频合成结果
*/
@GetMapping("/result/task/{taskId}")
@Operation(summary = "根据任务ID查询结果", description = "根据任务ID查询视频合成结果")
public ResponseEntity<Map<String, Object>> getSynthesisResultByTaskId(
@Parameter(description = "任务ID", required = true)
@PathVariable String taskId) {
Map<String, Object> result = new HashMap<>();
try {
VideoSynthesisLog synthesisLog = videoSynthesisService.getVideoSynthesisLogByTaskId(taskId);
if (synthesisLog == null) {
result.put("success", false);
result.put("message", "未找到对应的视频合成记录");
return ResponseEntity.notFound().build();
}
result.put("success", true);
result.put("message", "查询成功");
result.put("requestId", synthesisLog.getRequestId());
result.put("taskId", synthesisLog.getTaskId());
result.put("taskStatus", synthesisLog.getTaskStatus());
result.put("videoUrl", synthesisLog.getVideoUrl());
result.put("videoDuration", synthesisLog.getVideoDuration());
result.put("videoRatio", synthesisLog.getVideoRatio());
result.put("processingTimeMs", synthesisLog.getProcessingTimeMs());
result.put("requestTime", synthesisLog.getRequestTime());
result.put("responseTime", synthesisLog.getResponseTime());
result.put("imageId", synthesisLog.getImageId());
result.put("audioId", synthesisLog.getAudioId());
result.put("ownerName", synthesisLog.getOwnerName());
result.put("ownerPhone", synthesisLog.getOwnerPhone());
result.put("modelProvider", synthesisLog.getModelProvider());
if (!synthesisLog.getSuccess()) {
result.put("errorMessage", synthesisLog.getErrorMessage());
}
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("根据任务ID查询视频合成结果失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 分页查询视频合成日志列表
*/
@GetMapping("/list")
@Operation(summary = "查询视频合成日志列表", description = "分页查询视频合成日志")
public ResponseEntity<Map<String, Object>> getVideoSynthesisLogs(
@Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
@Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
@Parameter(description = "任务状态") @RequestParam(required = false) String taskStatus,
@Parameter(description = "模型") @RequestParam(required = false) String model,
@Parameter(description = "模型供应商") @RequestParam(required = false) String modelProvider,
@Parameter(description = "归属人姓名") @RequestParam(required = false) String ownerName,
@Parameter(description = "归属人电话") @RequestParam(required = false) String ownerPhone,
@Parameter(description = "是否成功") @RequestParam(required = false) Boolean success,
@Parameter(description = "开始时间") @RequestParam(required = false) String startTime,
@Parameter(description = "结束时间") @RequestParam(required = false) String endTime) {
Map<String, Object> result = new HashMap<>();
try {
Page<VideoSynthesisLog> page = new Page<>(pageNum, pageSize);
QueryWrapper<VideoSynthesisLog> queryWrapper = new QueryWrapper<>();
// 添加查询条件
if (taskStatus != null && !taskStatus.trim().isEmpty()) {
queryWrapper.eq("task_status", taskStatus);
}
if (model != null && !model.trim().isEmpty()) {
queryWrapper.like("model", model);
}
if (modelProvider != null && !modelProvider.trim().isEmpty()) {
queryWrapper.like("model_provider", modelProvider);
}
if (ownerName != null && !ownerName.trim().isEmpty()) {
queryWrapper.like("owner_name", ownerName);
}
if (ownerPhone != null && !ownerPhone.trim().isEmpty()) {
queryWrapper.like("owner_phone", ownerPhone);
}
if (success != null) {
queryWrapper.eq("success", success);
}
if (startTime != null && !startTime.trim().isEmpty()) {
queryWrapper.ge("request_time", startTime);
}
if (endTime != null && !endTime.trim().isEmpty()) {
queryWrapper.le("request_time", endTime);
}
// 按请求时间倒序排列
queryWrapper.orderByDesc("request_time");
// 执行查询
Page<VideoSynthesisLog> pageResult = videoSynthesisLogMapper.selectPage(page, queryWrapper);
result.put("success", true);
result.put("message", "查询成功");
result.put("data", pageResult.getRecords());
result.put("total", pageResult.getTotal());
result.put("pageNum", pageResult.getCurrent());
result.put("pageSize", pageResult.getSize());
result.put("pages", pageResult.getPages());
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("查询视频合成日志失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 根据MinIO路径播放视频
*/
@GetMapping("/play/{minioPath}")
@Operation(summary = "播放视频", description = "根据MinIO路径生成预签名URL播放视频")
public ResponseEntity<Map<String, Object>> playVideo(
@Parameter(description = "MinIO文件路径", required = true)
@PathVariable String minioPath,
@Parameter(description = "过期时间默认7天", required = false)
@RequestParam(value = "expires", defaultValue = "900") int expires) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始生成视频播放URLMinIO路径: {}, 过期时间: {}秒", 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<Map<String, Object>> playVideoByTaskId(
@Parameter(description = "任务ID", required = true)
@PathVariable String taskId,
@Parameter(description = "过期时间默认7天", required = false)
@RequestParam(value = "expires", defaultValue = "604800") int expires) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始根据任务ID播放视频任务ID: {}, 过期时间: {}秒", taskId, expires);
// 根据任务ID查询视频合成记录
QueryWrapper<VideoSynthesisLog> 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);
}
}
}