362 lines
16 KiB
Java
362 lines
16 KiB
Java
package com.imooc.controller;
|
||
|
||
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.imooc.base.BaseInfoProperties;
|
||
import com.imooc.bo.VlogBO;
|
||
import com.imooc.config.MinIOConfig;
|
||
import com.imooc.enums.YesOrNo;
|
||
import com.imooc.grace.result.GraceJSONResult;
|
||
import com.imooc.service.VlogService;
|
||
import com.imooc.utils.MinIOUtils;
|
||
import com.imooc.utils.PagedGridResult;
|
||
import com.qcloud.vod.model.VodUploadResponse;
|
||
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.*;
|
||
|
||
import com.imooc.utils.QcCloud;
|
||
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
@Slf4j
|
||
@Api(tags = "VlogController 短视频相关业务功能的接口")
|
||
@RequestMapping("vlog")
|
||
@RestController
|
||
@RefreshScope
|
||
public class VlogController extends BaseInfoProperties {
|
||
@Autowired
|
||
private VlogService vlogService;
|
||
@Autowired
|
||
private QcCloud qcCloud;
|
||
@Autowired
|
||
private MinIOConfig minIOConfig;
|
||
|
||
@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) {
|
||
String coverUrl=null; // 首帧图
|
||
String transVdUrl=null; // 转码后的视频地址
|
||
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");
|
||
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");
|
||
}
|
||
}
|
||
log.info("任务流 [截取首帧,视频转码] 完成, FileId: {}, 封面图 URL: {},视频地址: {}", fileId, coverUrl,transVdUrl);
|
||
// TODO: 更新数据库,存储首帧图,设置云端地址,删除minio视频文件
|
||
vlogService.updateVlogFirstImg(fileId,coverUrl,transVdUrl);
|
||
|
||
} 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);
|
||
// TODO: 更新数据库,发送站内信
|
||
vlogService.updateVlogStatus(fileId,2,label);
|
||
} else if ("pass".equals(suggestion)) {
|
||
// 审核通过,处理通过逻辑,修改视频状态为1,发送站内消息,告知审核结果
|
||
log.info("视频文件 {} 审核通过", fileId);
|
||
// TODO: 更新数据库,发送站内信
|
||
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);
|
||
// TODO: 更新数据库,发送站内信
|
||
vlogService.updateVlogStatus(fileId,3,"等待复审");
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 处理完成,返回成功,防止腾讯云重复发送回调
|
||
return GraceJSONResult.ok();
|
||
} catch (Exception e) {
|
||
log.error("处理腾讯云 VOD 回调异常: ", e);
|
||
return GraceJSONResult.error();
|
||
}
|
||
}
|
||
|
||
@PostMapping("publish")
|
||
public GraceJSONResult publish(@RequestBody VlogBO vlogBO) throws Exception {
|
||
String url = vlogBO.getUrl();
|
||
log.info("未审核视频地址:"+url);
|
||
String fileName = url.substring(url.lastIndexOf("/") + 1);
|
||
log.info("视频文件名称:"+fileName);
|
||
String fileId = qcCloud.uploadViaTempFile(fileName);
|
||
log.info("视频发布ID:"+fileId);
|
||
vlogBO.setFileId(fileId);
|
||
// 删除minio文件
|
||
// MinIOUtils.removeFile(minIOConfig.getBucketName(),fileName);
|
||
// log.info("删除minio文件:"+fileName);
|
||
|
||
// FIXME 校验VlogBO
|
||
vlogService.createVlog(vlogBO);
|
||
|
||
return GraceJSONResult.ok();
|
||
}
|
||
|
||
@GetMapping("indexList")
|
||
public GraceJSONResult indexList(@RequestParam(defaultValue = "") String userId,
|
||
@RequestParam(defaultValue = "") String search,
|
||
@RequestParam(defaultValue = "") String cityCode,
|
||
@RequestParam(defaultValue = "") String status,
|
||
@RequestParam Integer page,
|
||
@RequestParam Integer pageSize) {
|
||
|
||
if (page == null) {
|
||
page = COMMON_START_PAGE;
|
||
}
|
||
if (pageSize == null) {
|
||
pageSize = COMMON_PAGE_SIZE;
|
||
}
|
||
|
||
PagedGridResult gridResult = vlogService.getIndexVlogList(userId, search, cityCode,status, page, pageSize);
|
||
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);
|
||
}
|
||
}
|