第三次课程提交 声音系统的管理和提交
This commit is contained in:
parent
8f88132e32
commit
6034ffa8c5
|
@ -24,6 +24,8 @@ public class SystemConstant {
|
|||
//声音状态 0501-审核通过 0502"-审核不通过
|
||||
public static final String TRACK_STATUS_PASS="0501"; // 审核通过
|
||||
public static final String TRACK_STATUS_NO_PASS="0502"; // 审核不通过
|
||||
public static final String TRACK_STATUS_REVIEWING = "0503";// 审核中
|
||||
public static final String TRACK_STATUS_ARTIFICIAL = "0504";// 人工复审
|
||||
|
||||
//声音来源 0601-用户原创 0602-上传
|
||||
public static final String TRACK_SOURCE_USER="0601"; // 用户原创
|
||||
|
|
|
@ -46,6 +46,16 @@
|
|||
<artifactId>rabbit-util</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||
<version>3.1.1014</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-tms</artifactId>
|
||||
<version>3.1.1010</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -4,10 +4,12 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients
|
||||
@EnableScheduling //开启定时任务功能
|
||||
public class ServiceAlbumApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -76,6 +76,21 @@ public class AlbumInfoApiController {
|
|||
albumInfoService.updateAlbumInfo(id, albumInfoVo);
|
||||
return Result.ok();
|
||||
}
|
||||
/**
|
||||
* TODO 改接口登录才能访问
|
||||
* 查询当前用户专辑列表
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "查询当前用户专辑列表")
|
||||
@GetMapping("/albumInfo/findUserAllAlbumList")
|
||||
public Result<List<AlbumInfo>> findUserAllAlbumList(){
|
||||
//1.获取用户ID
|
||||
Long userId = AuthContextHolder.getUserId();
|
||||
//2.调用service方法查询
|
||||
List<AlbumInfo> list = albumInfoService.findUserAllAlbumList(userId);
|
||||
//3.响应结果
|
||||
return Result.ok(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
package com.atguigu.tingshu.album.api;
|
||||
|
||||
import com.atguigu.tingshu.album.service.TrackInfoService;
|
||||
import com.atguigu.tingshu.album.service.VodService;
|
||||
import com.atguigu.tingshu.common.result.Result;
|
||||
import com.atguigu.tingshu.common.util.AuthContextHolder;
|
||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||
import com.atguigu.tingshu.query.album.TrackInfoQuery;
|
||||
import com.atguigu.tingshu.vo.album.TrackInfoVo;
|
||||
import com.atguigu.tingshu.vo.album.TrackListVo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "声音管理")
|
||||
@RestController
|
||||
|
@ -15,5 +27,93 @@ public class TrackInfoApiController {
|
|||
@Autowired
|
||||
private TrackInfoService trackInfoService;
|
||||
|
||||
//这个接口是专门为了对上传的音频文件进行增删改查的
|
||||
//trackInfoService 这个接口是专门去写项目中关于声音的一些功能
|
||||
@Autowired
|
||||
private VodService vodService;
|
||||
|
||||
//用MultipartFile来接收文件
|
||||
@Operation(summary = "将音频文件上传到腾讯云点播平台")
|
||||
@PostMapping("/trackInfo/uploadTrack")
|
||||
public Result<Map<String,String>> uploadTrack(@RequestParam("file") MultipartFile file){
|
||||
Map<String,String> map=vodService.uploadTrack(file);
|
||||
return Result.ok(map);
|
||||
|
||||
}
|
||||
/**
|
||||
* TODO 该接口必须登录才能访问
|
||||
* 保存声音
|
||||
*
|
||||
* @param trackInfoVo
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "保存声音")
|
||||
@PostMapping("/trackInfo/saveTrackInfo")
|
||||
public Result saveTrackInfo(@Validated @RequestBody TrackInfoVo trackInfoVo) {
|
||||
Long userId = AuthContextHolder.getUserId();
|
||||
trackInfoService.saveTrackInfo(trackInfoVo, userId);
|
||||
return Result.ok();
|
||||
}
|
||||
/**
|
||||
* TODO 该接口必须登录才能访问
|
||||
* 分页条件查询当前用户声音列表
|
||||
*
|
||||
* @param page
|
||||
* @param limit
|
||||
* @param trackInfoQuery
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "分页条件查询当前用户声音列表")
|
||||
@PostMapping("/trackInfo/findUserTrackPage/{page}/{limit}")
|
||||
public Result<Page<TrackListVo>> findUserTrackPage(
|
||||
@PathVariable Long page,
|
||||
@PathVariable Long limit,
|
||||
@RequestBody TrackInfoQuery trackInfoQuery
|
||||
){
|
||||
//1.获取用户ID
|
||||
Long userId = AuthContextHolder.getUserId();
|
||||
trackInfoQuery.setUserId(userId);
|
||||
//2.封装分页对象:页码、页大小
|
||||
Page<TrackListVo> pageInfo = new Page<>(page, limit);
|
||||
//3.调用业务层分页获取结果
|
||||
pageInfo = trackInfoService.findUserTrackPage(pageInfo, trackInfoQuery);
|
||||
//4.响应结果
|
||||
return Result.ok(pageInfo);
|
||||
}
|
||||
/**
|
||||
* 查询声音信息
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "查询声音信息")
|
||||
@GetMapping("/trackInfo/getTrackInfo/{id}")
|
||||
public Result<TrackInfo> getTrackInfo(@PathVariable Long id){
|
||||
TrackInfo trackInfo = trackInfoService.getById(id);
|
||||
return Result.ok(trackInfo);
|
||||
}
|
||||
/**
|
||||
* 修改声音
|
||||
* @param id
|
||||
* @param trackInfoVo
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "修改声音")
|
||||
@PutMapping("/trackInfo/updateTrackInfo/{id}")
|
||||
public Result updateTrackInfo(@PathVariable Long id, @Validated @RequestBody TrackInfoVo trackInfoVo){
|
||||
trackInfoService.updateTrackInfo(id, trackInfoVo);
|
||||
return Result.ok();
|
||||
}
|
||||
/**
|
||||
* 删除声音
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "删除声音")
|
||||
@DeleteMapping("/trackInfo/removeTrackInfo/{id}")
|
||||
public Result removeTrackInfo(@PathVariable Long id){
|
||||
trackInfoService.removeTrackInfo(id);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package com.atguigu.tingshu.album.config;
|
||||
|
||||
|
||||
import com.qcloud.vod.VodUploadClient;
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
|
@ -18,4 +21,18 @@ public class VodConstantProperties {
|
|||
private String procedure;
|
||||
private String tempPath;
|
||||
private String playKey;
|
||||
/**
|
||||
* 注册用于文件上传客户端对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public VodUploadClient vodUploadClient() {
|
||||
return new VodUploadClient(secretId, secretKey);
|
||||
}
|
||||
@Bean
|
||||
public Credential credential(){
|
||||
return new Credential(secretId, secretKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.atguigu.tingshu.album.mapper;
|
||||
|
||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||
import com.atguigu.tingshu.query.album.TrackInfoQuery;
|
||||
import com.atguigu.tingshu.vo.album.TrackListVo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TrackInfoMapper extends BaseMapper<TrackInfo> {
|
||||
|
||||
|
||||
Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import com.atguigu.tingshu.vo.album.AlbumListVo;
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AlbumInfoService extends IService<AlbumInfo> {
|
||||
|
||||
|
||||
|
@ -23,4 +25,6 @@ public interface AlbumInfoService extends IService<AlbumInfo> {
|
|||
AlbumInfo getAlbumInfo(Long id);
|
||||
|
||||
void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo);
|
||||
|
||||
List<AlbumInfo> findUserAllAlbumList(Long userId);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.atguigu.tingshu.album.service;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
public interface AuditService {
|
||||
|
||||
//这个是专门封装出来为音频审核做的接口
|
||||
/**
|
||||
* 对文本进行审核
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
String auditText(String content);
|
||||
|
||||
/**
|
||||
* 对图片进行审核
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
String auditImage(MultipartFile file);
|
||||
|
||||
|
||||
/**
|
||||
* 发起审核任务
|
||||
* @param mediaFileId
|
||||
* @return 任务ID
|
||||
*/
|
||||
String startReviewTask(String mediaFileId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据任务ID 获取审核结果
|
||||
* @param taskId
|
||||
* @return 建议
|
||||
*/
|
||||
String getReviewResult(String taskId);
|
||||
|
||||
}
|
|
@ -1,8 +1,35 @@
|
|||
package com.atguigu.tingshu.album.service;
|
||||
|
||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||
import com.atguigu.tingshu.query.album.TrackInfoQuery;
|
||||
import com.atguigu.tingshu.vo.album.TrackInfoVo;
|
||||
import com.atguigu.tingshu.vo.album.TrackListVo;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface TrackInfoService extends IService<TrackInfo> {
|
||||
|
||||
|
||||
/**
|
||||
* 保存声音
|
||||
*
|
||||
* @param trackInfoVo
|
||||
* @param userId
|
||||
*/
|
||||
void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId);
|
||||
/**
|
||||
* 保存声音统计信息
|
||||
* @param trackId 声音ID
|
||||
* @param statType 统计类型
|
||||
* @param statNum 统计数值
|
||||
*/
|
||||
void saveTrackStat(Long trackId, String statType, int statNum);
|
||||
|
||||
Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery);
|
||||
|
||||
void updateTrackInfo(Long id, TrackInfoVo trackInfoVo);
|
||||
|
||||
void removeTrackInfo(Long id);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
package com.atguigu.tingshu.album.service;
|
||||
|
||||
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface VodService {
|
||||
|
||||
Map<String, String> uploadTrack(MultipartFile file);
|
||||
|
||||
TrackMediaInfoVo getMediaInfo(String mediaFileId);
|
||||
/**
|
||||
* 从点播平台删除音频
|
||||
* @param mediaFileId
|
||||
*/
|
||||
void deleteMedia(String mediaFileId);
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
|
|||
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
|
||||
import com.atguigu.tingshu.vo.album.AlbumListVo;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -173,4 +173,23 @@ public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AlbumInfo> findUserAllAlbumList(Long userId) {
|
||||
LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
//1.查询当前用户专辑列表
|
||||
queryWrapper.eq(AlbumInfo::getUserId, userId);
|
||||
//2.专辑状态为审核通过
|
||||
queryWrapper.eq(AlbumInfo::getStatus,SystemConstant.ALBUM_STATUS_PASS);
|
||||
//3.专辑ID,专辑标题
|
||||
queryWrapper.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle);
|
||||
//4.限制返回记录数,造成前端卡顿 TODO 后期前端改为带分页下拉框
|
||||
queryWrapper.last("limit 200");
|
||||
//5.按照专辑ID降序
|
||||
queryWrapper.orderByDesc(AlbumInfo::getId);
|
||||
return albumInfoMapper.selectList(queryWrapper);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
package com.atguigu.tingshu.album.service.impl;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import com.atguigu.tingshu.album.config.VodConstantProperties;
|
||||
import com.atguigu.tingshu.album.service.AuditService;
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.ims.v20201229.ImsClient;
|
||||
import com.tencentcloudapi.ims.v20201229.models.ImageModerationRequest;
|
||||
import com.tencentcloudapi.ims.v20201229.models.ImageModerationResponse;
|
||||
import com.tencentcloudapi.tms.v20201229.TmsClient;
|
||||
import com.tencentcloudapi.tms.v20201229.models.TextModerationRequest;
|
||||
import com.tencentcloudapi.tms.v20201229.models.TextModerationResponse;
|
||||
import com.tencentcloudapi.vod.v20180717.VodClient;
|
||||
import com.tencentcloudapi.vod.v20180717.models.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* @author: atguigu
|
||||
* @create: 2025-07-19 14:24
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AuditServiceImpl implements AuditService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private Credential credential;
|
||||
|
||||
@Autowired
|
||||
private VodConstantProperties vodConstantProperties;
|
||||
|
||||
/**
|
||||
* 审核文本
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String auditText(String content) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,clientProfile是可选的
|
||||
TmsClient client = new TmsClient(credential, vodConstantProperties.getRegion());
|
||||
//2.实例化一个请求对象,每个接口都会对应一个request对象
|
||||
TextModerationRequest req = new TextModerationRequest();
|
||||
//对文本进行Base64编码
|
||||
req.setContent(Base64.encode(content));
|
||||
//3.返回的resp是一个TextModerationResponse的实例,与请求对象对应
|
||||
TextModerationResponse resp = client.TextModeration(req);
|
||||
if (resp != null) {
|
||||
String suggestion = resp.getSuggestion();
|
||||
return suggestion.toLowerCase();
|
||||
}
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("文本审核失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对图片进行审核
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String auditImage(MultipartFile file) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,clientProfile是可选的
|
||||
ImsClient client = new ImsClient(credential, vodConstantProperties.getRegion());
|
||||
//2.实例化一个请求对象,每个接口都会对应一个request对象
|
||||
ImageModerationRequest req = new ImageModerationRequest();
|
||||
req.setFileContent(Base64.encode(file.getInputStream()));
|
||||
//3.返回的resp是一个ImageModerationResponse的实例,与请求对象对应
|
||||
ImageModerationResponse resp = client.ImageModeration(req);
|
||||
if (resp != null) {
|
||||
String suggestion = resp.getSuggestion();
|
||||
return suggestion.toLowerCase();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("图片审核失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起审核任务
|
||||
*
|
||||
* @param mediaFileId
|
||||
* @return 任务ID
|
||||
*/
|
||||
@Override
|
||||
public String startReviewTask(String mediaFileId) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,clientProfile是可选的
|
||||
VodClient client = new VodClient(credential, vodConstantProperties.getRegion());
|
||||
//2.实例化一个请求对象,每个接口都会对应一个request对象
|
||||
ReviewAudioVideoRequest req = new ReviewAudioVideoRequest();
|
||||
req.setFileId(mediaFileId);
|
||||
//3.返回的resp是一个ReviewAudioVideoResponse的实例,与请求对象对应
|
||||
ReviewAudioVideoResponse resp = client.ReviewAudioVideo(req);
|
||||
if (resp != null) {
|
||||
return resp.getTaskId();
|
||||
}
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("音视频审核任务发起失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据任务ID 获取审核结果
|
||||
*
|
||||
* @param taskId
|
||||
* @return 建议
|
||||
*/
|
||||
@Override
|
||||
public String getReviewResult(String taskId) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,clientProfile是可选的
|
||||
VodClient client = new VodClient(credential, vodConstantProperties.getRegion());
|
||||
//2.例化一个请求对象,每个接口都会对应一个request对象
|
||||
DescribeTaskDetailRequest req = new DescribeTaskDetailRequest();
|
||||
req.setTaskId(taskId);
|
||||
//3.返回的resp是一个DescribeTaskDetailResponse的实例,与请求对象对应
|
||||
DescribeTaskDetailResponse resp = client.DescribeTaskDetail(req);
|
||||
//4.解析任务状态以及审核任务建议结果
|
||||
if (resp != null) {
|
||||
String taskType = resp.getTaskType();
|
||||
//4.1 获取任务类型是否为音频审核
|
||||
if ("ReviewAudioVideo".equals(taskType)) {
|
||||
//4.2 获取任务状态是否为已完成
|
||||
String status = resp.getStatus();
|
||||
if ("FINISH".equals(status)) {
|
||||
ReviewAudioVideoTask reviewAudioVideoTask = resp.getReviewAudioVideoTask();
|
||||
if (reviewAudioVideoTask != null) {
|
||||
ReviewAudioVideoTaskOutput output = reviewAudioVideoTask.getOutput();
|
||||
String suggestion = output.getSuggestion();
|
||||
//4.3 获取建议
|
||||
return suggestion.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TencentCloudSDKException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,32 @@
|
|||
package com.atguigu.tingshu.album.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
|
||||
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
|
||||
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
|
||||
import com.atguigu.tingshu.album.service.AuditService;
|
||||
import com.atguigu.tingshu.album.service.TrackInfoService;
|
||||
import com.atguigu.tingshu.album.service.VodService;
|
||||
import com.atguigu.tingshu.common.constant.SystemConstant;
|
||||
import com.atguigu.tingshu.model.album.AlbumInfo;
|
||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||
import com.atguigu.tingshu.model.album.TrackStat;
|
||||
import com.atguigu.tingshu.query.album.TrackInfoQuery;
|
||||
import com.atguigu.tingshu.vo.album.TrackInfoVo;
|
||||
import com.atguigu.tingshu.vo.album.TrackListVo;
|
||||
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
|
@ -15,5 +35,176 @@ public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo
|
|||
|
||||
@Autowired
|
||||
private TrackInfoMapper trackInfoMapper;
|
||||
@Autowired
|
||||
private AlbumInfoMapper albumInfoMapper;
|
||||
@Autowired
|
||||
private VodService vodService;
|
||||
@Autowired
|
||||
private AuditService auditService;
|
||||
@Autowired
|
||||
private TrackStatMapper trackStatMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
|
||||
//1. 根据专辑id查询专辑信息 用于更新专辑声音数量
|
||||
AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
|
||||
//2. 保存声音信息
|
||||
//2.1 将VO转为PO对象
|
||||
TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
|
||||
//2.2 属性赋值
|
||||
//2.2.1 基本属性:用户ID,审核状态,封面图片,来源
|
||||
trackInfo.setUserId(userId);
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
|
||||
trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
|
||||
if (StringUtils.isBlank(trackInfo.getCoverUrl())) {
|
||||
//如果用户没有选择封面图片 则用户所属专辑的封面图片
|
||||
trackInfo.setCoverUrl(albumInfo.getCoverUrl());
|
||||
}
|
||||
//2.2.2 计算声音序号 现有专辑包含声音数量+1
|
||||
trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
|
||||
//2.2.3 查询点播平台获取音频详情:得到时长、大小、类型
|
||||
TrackMediaInfoVo mediaInfoVo = vodService.getMediaInfo(trackInfo.getMediaFileId());
|
||||
if (mediaInfoVo != null) {
|
||||
trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfoVo.getDuration()));
|
||||
trackInfo.setMediaSize(mediaInfoVo.getSize());
|
||||
trackInfo.setMediaType(mediaInfoVo.getType());
|
||||
}
|
||||
albumInfoMapper.updateById(albumInfo);
|
||||
//2.2.5 保存声音记录
|
||||
trackInfoMapper.insert(trackInfo);
|
||||
|
||||
//2.2.4 TODO 调用内容审核接口,发起内容审核,更新审核任务ID
|
||||
String text = trackInfo.getTrackTitle() + trackInfo.getTrackIntro();
|
||||
String suggestion = auditService.auditText(text);
|
||||
if ("pass".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
|
||||
//TODO 文本审核通过后,还需要进一步审核音频内容
|
||||
String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEWING);
|
||||
trackInfo.setReviewTaskId(reviewTaskId);
|
||||
} else if ("block".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
|
||||
} else if ("review".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_ARTIFICIAL);
|
||||
}
|
||||
trackInfoMapper.updateById(trackInfo);
|
||||
|
||||
//3. 更新专辑包含声音数量
|
||||
albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
|
||||
albumInfoMapper.updateById(albumInfo);
|
||||
|
||||
//3.新增声音统计信息
|
||||
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY, 0);
|
||||
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT, 0);
|
||||
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE, 0);
|
||||
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT, 0);
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* 保存声音统计信息
|
||||
*
|
||||
* @param trackId 声音ID
|
||||
* @param statType 统计类型:播放、点赞、收藏、评论
|
||||
* @param statNum 统计数值
|
||||
*/
|
||||
@Override
|
||||
public void saveTrackStat(Long trackId, String statType, int statNum) {
|
||||
TrackStat trackStat = new TrackStat();
|
||||
trackStat.setTrackId(trackId);
|
||||
trackStat.setStatType(statType);
|
||||
trackStat.setStatNum(statNum);
|
||||
trackStatMapper.insert(trackStat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
|
||||
return trackInfoMapper.findUserTrackPage(pageInfo, trackInfoQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
|
||||
//1. 根据id查询声音信息 得到"原有的"音频唯一标识
|
||||
TrackInfo trackInfo = trackInfoMapper.selectById(id);
|
||||
String oldMediaFileId = trackInfo.getMediaFileId();
|
||||
|
||||
//对文本进行审核
|
||||
String text = trackInfoVo.getTrackTitle() + trackInfoVo.getTrackIntro();
|
||||
String suggestion = auditService.auditText(text);
|
||||
if ("pass".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
|
||||
} else if ("block".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
|
||||
} else if ("review".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_ARTIFICIAL);
|
||||
}
|
||||
|
||||
//2. 判断音频文件是否发生更新,如果更新
|
||||
if (!trackInfoVo.getMediaFileId().equals(oldMediaFileId)) {
|
||||
// 2.1 调用点播平台获取最新音频详情信息
|
||||
TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
|
||||
if (mediaInfo != null) {
|
||||
trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
|
||||
trackInfo.setMediaUrl(trackInfoVo.getMediaUrl());
|
||||
trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfo.getDuration()));
|
||||
trackInfo.setMediaType(mediaInfo.getType());
|
||||
trackInfo.setMediaSize(mediaInfo.getSize());
|
||||
// 2.2 TODO 再次对变更后音频文件进行内容审核
|
||||
String reviewTaskId = auditService.startReviewTask(trackInfo.getMediaFileId());
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_REVIEWING);
|
||||
trackInfo.setReviewTaskId(reviewTaskId);
|
||||
|
||||
// 2.3原有音频从点播平台删除
|
||||
vodService.deleteMedia(oldMediaFileId);
|
||||
}
|
||||
}
|
||||
trackInfo.setTrackTitle(trackInfoVo.getTrackTitle());
|
||||
trackInfo.setTrackIntro(trackInfoVo.getTrackIntro());
|
||||
trackInfo.setCoverUrl(trackInfoVo.getCoverUrl());
|
||||
|
||||
|
||||
//3. 更新声音记录
|
||||
trackInfoMapper.updateById(trackInfo);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removeTrackInfo(Long id) {
|
||||
//1.根据ID查询要被删除声音记录 得到专辑ID跟序号
|
||||
TrackInfo trackInfo = trackInfoMapper.selectById(id);
|
||||
Long albumId = trackInfo.getAlbumId();
|
||||
Integer orderNum = trackInfo.getOrderNum();
|
||||
|
||||
//2.更新序号确保声音表中序号连续
|
||||
trackInfoMapper.update(
|
||||
null,
|
||||
new LambdaUpdateWrapper<TrackInfo>()
|
||||
.eq(TrackInfo::getAlbumId, albumId)
|
||||
.gt(TrackInfo::getOrderNum, orderNum)
|
||||
.setSql("order_num = order_num - 1")
|
||||
);
|
||||
|
||||
//3.删除声音
|
||||
trackInfoMapper.deleteById(id);
|
||||
|
||||
//4.删除统计信息
|
||||
trackStatMapper.delete(
|
||||
new LambdaQueryWrapper<TrackStat>()
|
||||
.eq(TrackStat::getTrackId, id)
|
||||
);
|
||||
|
||||
//5.更新专辑包含声音数量
|
||||
albumInfoMapper.update(null,
|
||||
new LambdaUpdateWrapper<AlbumInfo>().eq(AlbumInfo::getId, albumId)
|
||||
.setSql("include_track_count = include_track_count - 1")
|
||||
);
|
||||
|
||||
//6.删除点播平台音频文件
|
||||
vodService.deleteMedia(trackInfo.getMediaFileId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,14 +2,105 @@ package com.atguigu.tingshu.album.service.impl;
|
|||
|
||||
import com.atguigu.tingshu.album.config.VodConstantProperties;
|
||||
import com.atguigu.tingshu.album.service.VodService;
|
||||
import com.atguigu.tingshu.common.util.UploadFileUtil;
|
||||
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
|
||||
import com.qcloud.vod.VodUploadClient;
|
||||
import com.qcloud.vod.model.VodUploadRequest;
|
||||
import com.qcloud.vod.model.VodUploadResponse;
|
||||
import com.tencentcloudapi.common.Credential;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.vod.v20180717.VodClient;
|
||||
import com.tencentcloudapi.vod.v20180717.models.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class VodServiceImpl implements VodService {
|
||||
|
||||
@Autowired
|
||||
private VodConstantProperties vodConstantProperties;
|
||||
@Autowired
|
||||
private VodUploadClient vodUploadClient;
|
||||
@Autowired
|
||||
private Credential credential;
|
||||
|
||||
@Override
|
||||
public Map<String, String> uploadTrack(MultipartFile file) {
|
||||
//1.首先将上传文件保存到本地临时文件夹中 后期采取定时任务去清理临时文件夹
|
||||
try {
|
||||
String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
|
||||
//2.上传到腾讯云点播平台
|
||||
//2.1 构造上传请求对象
|
||||
VodUploadRequest request = new VodUploadRequest();
|
||||
request.setMediaFilePath(tempPath);
|
||||
//2.2 调用上传
|
||||
VodUploadResponse response = vodUploadClient.upload(vodConstantProperties.getRegion(), request);
|
||||
//2.3 获取上传结果得到音频媒体唯一标识mediaFileId,以及音频在线地址mediaUrl
|
||||
if (response != null) {
|
||||
String fileId = response.getFileId();
|
||||
String mediaUrl = response.getMediaUrl();
|
||||
return Map.of("mediaFileId", fileId, "mediaUrl", mediaUrl);
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.error("上传音频文件失败");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackMediaInfoVo getMediaInfo(String mediaFileId) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,
|
||||
VodClient client = new VodClient(credential, vodConstantProperties.getRegion());
|
||||
//2.实例化一个请求对象,每个接口都会对应一个request对象
|
||||
DescribeMediaInfosRequest req = new DescribeMediaInfosRequest();
|
||||
String[] fileIds1 = {mediaFileId};
|
||||
req.setFileIds(fileIds1);
|
||||
//3.返回的resp是一个DescribeMediaInfosResponse的实例,与请求对象对应
|
||||
DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req);
|
||||
//4.解析结果,获取基本信息中类型以及元数据时长跟大小
|
||||
if (resp != null) {
|
||||
MediaInfo mediaInfo = resp.getMediaInfoSet()[0];
|
||||
if (mediaInfo != null) {
|
||||
//4.1 获取基本信息
|
||||
MediaBasicInfo basicInfo = mediaInfo.getBasicInfo();
|
||||
//4.2 获取元数据
|
||||
MediaMetaData metaData = mediaInfo.getMetaData();
|
||||
//4.3 封装音频文件详情VO
|
||||
TrackMediaInfoVo trackMediaInfoVo = new TrackMediaInfoVo();
|
||||
trackMediaInfoVo.setType(basicInfo.getType());
|
||||
trackMediaInfoVo.setSize(metaData.getSize());
|
||||
trackMediaInfoVo.setDuration(metaData.getDuration());
|
||||
return trackMediaInfoVo;
|
||||
}
|
||||
}
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("获取音频信息失败");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMedia(String mediaFileId) {
|
||||
try {
|
||||
//1.实例化要请求产品的client对象,clientProfile是可选的
|
||||
VodClient client = new VodClient(credential, vodConstantProperties.getRegion());
|
||||
//2.实例化一个请求对象,每个接口都会对应一个request对象
|
||||
DeleteMediaRequest req = new DeleteMediaRequest();
|
||||
req.setFileId(mediaFileId);
|
||||
//3.返回的resp是一个DeleteMediaResponse的实例,与请求对象对应
|
||||
client.DeleteMedia(req);
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("删除失败");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package com.atguigu.tingshu.album.task;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
|
||||
import com.atguigu.tingshu.album.service.AuditService;
|
||||
import com.atguigu.tingshu.common.constant.SystemConstant;
|
||||
import com.atguigu.tingshu.model.album.TrackInfo;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: atguigu
|
||||
* @create: 2025-07-19 15:38
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ReviewTask {
|
||||
|
||||
@Autowired
|
||||
private TrackInfoMapper trackInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private AuditService auditService;
|
||||
|
||||
/**
|
||||
* 每5秒检查一次审核结果
|
||||
*/
|
||||
@Scheduled(cron = "0/5 * * * * ?")
|
||||
public void checkReviewResultTask() {
|
||||
log.info("开始检查审核任务");
|
||||
//1.查询审核状态为"审核中"声音列表
|
||||
List<TrackInfo> trackInfoList = trackInfoMapper.selectList(
|
||||
new LambdaQueryWrapper<TrackInfo>()
|
||||
.eq(TrackInfo::getStatus, SystemConstant.TRACK_STATUS_REVIEWING)
|
||||
.select(TrackInfo::getId, TrackInfo::getReviewTaskId)
|
||||
.last("limit 100")
|
||||
);
|
||||
//2.遍历列表,查询审核结果
|
||||
if (CollUtil.isNotEmpty(trackInfoList)) {
|
||||
for (TrackInfo trackInfo : trackInfoList) {
|
||||
String suggestion = auditService.getReviewResult(trackInfo.getReviewTaskId());
|
||||
if (StringUtils.isNotBlank(suggestion)) {
|
||||
//3.根据审核任务结果更新声音审核状态
|
||||
if ("pass".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
|
||||
} else if ("block".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
|
||||
} else if ("review".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_ARTIFICIAL);
|
||||
}
|
||||
trackInfoMapper.updateById(trackInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,34 @@
|
|||
|
||||
|
||||
<mapper namespace="com.atguigu.tingshu.album.mapper.TrackInfoMapper">
|
||||
|
||||
<select id="findUserTrackPage" resultType="com.atguigu.tingshu.vo.album.TrackListVo">
|
||||
select
|
||||
ti.id track_id,
|
||||
ti.track_title,
|
||||
ti.cover_url,
|
||||
ti.media_duration,
|
||||
ti.status,
|
||||
max(if(stat_type = '0701', stat_num, 0)) playStatNum,
|
||||
max(if(stat_type = '0702', stat_num, 0)) collectStatNum,
|
||||
max(if(stat_type = '0703', stat_num, 0)) praiseStatNum,
|
||||
max(if(stat_type = '0704', stat_num, 0)) commentStatNum
|
||||
from track_info ti inner join track_stat stat
|
||||
on stat.track_id = ti.id and stat.is_deleted = 0
|
||||
<where>
|
||||
<if test="vo.userId != null">
|
||||
and ti.user_id = #{vo.userId}
|
||||
</if>
|
||||
<if test="vo.status != null and vo.status != ''">
|
||||
and status = #{vo.status}
|
||||
</if>
|
||||
<if test="vo.trackTitle != null and vo.trackTitle != ''">
|
||||
and track_title like concat('%',#{vo.trackTitle},'%')
|
||||
</if>
|
||||
and ti.is_deleted = 0
|
||||
</where>
|
||||
group by ti.id
|
||||
order by ti.id desc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue