vlog/book-api/src/main/java/com/imooc/controller/VlogController.java

362 lines
16 KiB
Java
Raw Normal View History

2025-03-10 15:40:51 +08:00
package com.imooc.controller;
2025-04-03 11:25:24 +08:00
import com.fasterxml.jackson.databind.ObjectMapper;
2025-03-10 15:40:51 +08:00
import com.imooc.base.BaseInfoProperties;
import com.imooc.bo.VlogBO;
2025-04-29 22:44:28 +08:00
import com.imooc.config.MinIOConfig;
2025-03-10 15:40:51 +08:00
import com.imooc.enums.YesOrNo;
import com.imooc.grace.result.GraceJSONResult;
import com.imooc.service.VlogService;
2025-04-29 22:44:28 +08:00
import com.imooc.utils.MinIOUtils;
2025-03-10 15:40:51 +08:00
import com.imooc.utils.PagedGridResult;
2025-04-03 11:25:24 +08:00
import com.qcloud.vod.model.VodUploadResponse;
2025-03-10 15:40:51 +08:00
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
2025-04-03 11:25:24 +08:00
import com.imooc.utils.QcCloud;
import java.util.List;
import java.util.Map;
2025-03-10 15:40:51 +08:00
@Slf4j
@Api(tags = "VlogController 短视频相关业务功能的接口")
@RequestMapping("vlog")
@RestController
@RefreshScope
public class VlogController extends BaseInfoProperties {
@Autowired
private VlogService vlogService;
2025-04-03 11:25:24 +08:00
@Autowired
private QcCloud qcCloud;
2025-04-29 22:44:28 +08:00
@Autowired
private MinIOConfig minIOConfig;
2025-04-03 11:25:24 +08:00
@PostMapping("vodCallBack")
public GraceJSONResult vodCallBack(@RequestBody Map<String, Object> callbackData) {
try {
// 解析回调事件类型
String eventType = (String) callbackData.get("EventType");
log.info("收到腾讯云 VOD 回调, 事件类型: {}", eventType);
log.info(callbackData.toString());
if ("ProcedureStateChanged".equals(eventType)) {
// 获取 ProcedureStateChangeEvent
Object eventObject = callbackData.get("ProcedureStateChangeEvent");
if (eventObject instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> procedureStateChangeEvent = (Map<String, Object>) eventObject;
String fileId = (String) procedureStateChangeEvent.get("FileId");
String fileUrl = (String) procedureStateChangeEvent.get("FileUrl"); // 原视频地址
String status = (String) procedureStateChangeEvent.get("Status"); // FINISH
// 只处理完成状态
if ("FINISH".equals(status)) {
// 获取 MediaProcessResultSet可能包含任务流信息
List<Map<String, Object>> mediaProcessResultSet =
(List<Map<String, Object>>) procedureStateChangeEvent.get("MediaProcessResultSet");
if (mediaProcessResultSet != null) {
2025-04-03 12:15:27 +08:00
String coverUrl=null; // 首帧图
String transVdUrl=null; // 转码后的视频地址
2025-04-03 11:25:24 +08:00
for (Map<String, Object> processResult : mediaProcessResultSet) {
String type = (String) processResult.get("Type");
if ("CoverBySnapshot".equals(type)) {
// 任务流:首帧截图
Map<String, Object> coverBySnapshotTask =
(Map<String, Object>) processResult.get("CoverBySnapshotTask");
Map<String, Object> output = (Map<String, Object>) coverBySnapshotTask.get("Output");
2025-04-03 12:15:27 +08:00
coverUrl = (String) output.get("CoverUrl"); // 正确获取 CoverUrl
}
if("Transcode".equals(type)){
// 拿到output中的url
Map<String, Object> TranscodeTask =
(Map<String, Object>) processResult.get("TranscodeTask");
Map<String, Object> output = (Map<String, Object>) TranscodeTask.get("Output");
transVdUrl = (String) output.get("Url");
2025-04-03 11:25:24 +08:00
}
}
2025-04-07 15:19:45 +08:00
log.info("任务流 [截取首帧,视频转码] 完成, FileId: {}, 封面图 URL: {},视频地址: {}", fileId, coverUrl,transVdUrl);
2025-04-29 22:44:28 +08:00
// TODO: 更新数据库,存储首帧图,设置云端地址删除minio视频文件
2025-04-03 12:15:27 +08:00
vlogService.updateVlogFirstImg(fileId,coverUrl,transVdUrl);
2025-04-29 22:44:28 +08:00
2025-04-03 11:25:24 +08:00
} else {
log.warn("MediaProcessResultSet 为空,回调数据: {}", callbackData);
}
}
log.info("任务流完成, FileId: {}, Status: {}", fileId, status);
} else {
log.warn("ProcedureStateChangeEvent 为空或格式错误,回调数据: {}", callbackData);
}
}
if("ReviewAudioVideoComplete".equals(eventType)){
//处理审核结果
Map<String, Object> reviewEvent = (Map<String, Object>) callbackData.get("ReviewAudioVideoCompleteEvent");
if (reviewEvent != null) {
String status = (String) reviewEvent.get("Status"); // FINISH
if ("FINISH".equals(status)) {
Map<String, Object> input = (Map<String, Object>) reviewEvent.get("Input");
String fileId = (String) input.get("FileId"); // 查询的唯一标识
// 获取审核结果
Map<String, Object> output = (Map<String, Object>) reviewEvent.get("Output");
String suggestion = (String) output.get("Suggestion");
if ("block".equals(suggestion)) {
// 审核不通过修改视频状态为2写入reason发送站内消息告知审核结果
// label
//Porn色情
//Terror暴力
//Polity不适宜的信息
//Ad广告
//Illegal违法
//Abuse谩骂
//Moan娇喘。
String label = (String) output.get("Label"); // 违规内容
String subLabel = (String) output.get("SubLabel"); // 违规子标签
log.info("视频文件 {} 审核驳回, 原因: {} - {}", fileId, label, subLabel);
2025-04-07 15:19:45 +08:00
// TODO: 更新数据库,发送站内信
2025-04-03 11:25:24 +08:00
vlogService.updateVlogStatus(fileId,2,label);
} else if ("pass".equals(suggestion)) {
// 审核通过,处理通过逻辑,修改视频状态为1发送站内消息告知审核结果
log.info("视频文件 {} 审核通过", fileId);
2025-04-07 15:19:45 +08:00
// TODO: 更新数据库,发送站内信
2025-04-03 11:25:24 +08:00
vlogService.updateVlogStatus(fileId,1,"通过");
} else if ("review".equals(suggestion)){
// 建议复审修改状态为3发送站内消息告知审核结果
String label = (String) output.get("Label"); // 违规内容
String subLabel = (String) output.get("SubLabel"); // 违规子标签
log.info("视频文件 {} 建议复审, 原因: {} - {}", fileId, label, subLabel);
2025-04-07 15:19:45 +08:00
// TODO: 更新数据库,发送站内信
2025-04-03 11:25:24 +08:00
vlogService.updateVlogStatus(fileId,3,"等待复审");
}
}
}
}
// 处理完成,返回成功,防止腾讯云重复发送回调
return GraceJSONResult.ok();
} catch (Exception e) {
log.error("处理腾讯云 VOD 回调异常: ", e);
return GraceJSONResult.error();
}
}
2025-03-10 15:40:51 +08:00
@PostMapping("publish")
2025-04-03 11:25:24 +08:00
public GraceJSONResult publish(@RequestBody VlogBO vlogBO) throws Exception {
String url = vlogBO.getUrl();
2025-05-02 14:05:58 +08:00
log.info("未审核视频地址:"+url);
2025-04-03 11:25:24 +08:00
String fileName = url.substring(url.lastIndexOf("/") + 1);
2025-05-02 14:05:58 +08:00
log.info("视频文件名称:"+fileName);
2025-04-03 11:25:24 +08:00
String fileId = qcCloud.uploadViaTempFile(fileName);
2025-05-02 14:05:58 +08:00
log.info("视频发布ID:"+fileId);
2025-04-03 11:25:24 +08:00
vlogBO.setFileId(fileId);
2025-04-29 22:44:28 +08:00
// 删除minio文件
2025-05-02 14:05:58 +08:00
// MinIOUtils.removeFile(minIOConfig.getBucketName(),fileName);
// log.info("删除minio文件"+fileName);
2025-04-29 22:44:28 +08:00
// FIXME 校验VlogBO
2025-03-10 15:40:51 +08:00
vlogService.createVlog(vlogBO);
2025-04-03 11:25:24 +08:00
2025-03-10 15:40:51 +08:00
return GraceJSONResult.ok();
}
@GetMapping("indexList")
public GraceJSONResult indexList(@RequestParam(defaultValue = "") String userId,
@RequestParam(defaultValue = "") String search,
2025-04-07 15:19:45 +08:00
@RequestParam(defaultValue = "") String cityCode,
@RequestParam(defaultValue = "") String status,
2025-03-10 15:40:51 +08:00
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
2025-04-07 15:19:45 +08:00
PagedGridResult gridResult = vlogService.getIndexVlogList(userId, search, cityCode,status, page, pageSize);
2025-03-10 15:40:51 +08:00
return GraceJSONResult.ok(gridResult);
}
@GetMapping("detail")
public GraceJSONResult detail(@RequestParam(defaultValue = "") String userId,
@RequestParam String vlogId) {
return GraceJSONResult.ok(vlogService.getVlogDetailById(userId, vlogId));
}
@PostMapping("changeToPrivate")
public GraceJSONResult changeToPrivate(@RequestParam String userId,
@RequestParam String vlogId) {
vlogService.changeToPrivateOrPublic(userId,
vlogId,
YesOrNo.YES.type);
return GraceJSONResult.ok();
}
@PostMapping("changeToPublic")
public GraceJSONResult changeToPublic(@RequestParam String userId,
@RequestParam String vlogId) {
vlogService.changeToPrivateOrPublic(userId,
vlogId,
YesOrNo.NO.type);
return GraceJSONResult.ok();
}
@GetMapping("myPublicList")
public GraceJSONResult myPublicList(@RequestParam String userId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
page,
pageSize,
YesOrNo.NO.type);
return GraceJSONResult.ok(gridResult);
}
@GetMapping("myPrivateList")
public GraceJSONResult myPrivateList(@RequestParam String userId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
page,
pageSize,
YesOrNo.YES.type);
return GraceJSONResult.ok(gridResult);
}
@GetMapping("myLikedList")
public GraceJSONResult myLikedList(@RequestParam String userId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
PagedGridResult gridResult = vlogService.getMyLikedVlogList(userId,
page,
pageSize);
return GraceJSONResult.ok(gridResult);
}
@Value(("${nacos.counts}"))
private Integer nacosConuts;
@PostMapping("like")
public GraceJSONResult like(@RequestParam String userId,
@RequestParam String vlogerId,
@RequestParam String vlogId) {
// 我点赞的视频,关联关系保存到数据库
vlogService.userLikeVlog(userId, vlogId);
// 点赞后,视频和视频发布者的获赞都会 +1
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
// 我点赞的视频需要在redis中保存关联关系
redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");
log.info("nacosConuts="+nacosConuts);
String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
Integer counts=0;
if (StringUtils.isNotBlank(countsStr)){
counts=Integer.valueOf(countsStr);
if (counts>=nacosConuts){
vlogService.flushCounts(vlogId, counts);
}
}
return GraceJSONResult.ok();
}
@PostMapping("unlike")
public GraceJSONResult unlike(@RequestParam String userId,
@RequestParam String vlogerId,
@RequestParam String vlogId) {
// 我取消点赞的视频,关联关系删除
vlogService.userUnLikeVlog(userId, vlogId);
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
return GraceJSONResult.ok();
}
@PostMapping("totalLikedCounts")
public GraceJSONResult totalLikedCounts(@RequestParam String vlogId) {
return GraceJSONResult.ok(vlogService.getVlogBeLikedCounts(vlogId));
}
@GetMapping("followList")
public GraceJSONResult followList(@RequestParam String myId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
PagedGridResult gridResult = vlogService.getMyFollowVlogList(myId,
page,
pageSize);
return GraceJSONResult.ok(gridResult);
}
@GetMapping("friendList")
public GraceJSONResult friendList(@RequestParam String myId,
@RequestParam Integer page,
@RequestParam Integer pageSize) {
if (page == null) {
page = COMMON_START_PAGE;
}
if (pageSize == null) {
pageSize = COMMON_PAGE_SIZE;
}
PagedGridResult gridResult = vlogService.getMyFriendVlogList(myId,
page,
pageSize);
return GraceJSONResult.ok(gridResult);
}
}