谷粒随享
学习目标:
功能入口:运行小程序-->我的-->创作中心-->声音-->点击 + 添加声音
业务需求:当创作者新增专辑后,创作者将自己录制的音视频文件保存到声音。
需求:点击添加声音的时候会触发一个查询所有专辑列表,主要目的是为了让专辑与声音进行挂钩!
主要是根据userId,查询专辑Id 与专辑标题,然后按照专辑Id 进行降序排列。
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/27
AlbumInfoApiController控制器
/**
* TODO 登录后才能访问
* 查询用户发布专辑列表,用于下拉列表展示
*
* @return
*/
@Operation(summary = "查询用户发布专辑列表,用于下拉列表展示")
@GetMapping("/albumInfo/findUserAllAlbumList")
public Result<List<AlbumInfo>> getUserAllAlbumList() {
Long userId = AuthContextHolder.getUserId();
List<AlbumInfo> list = albumInfoService.getUserAllAlbumList(userId);
return Result.ok(list);
}
AlbumInfoService接口
/**
* 查询用户发布专辑列表,用于下拉列表展示
* @param userId
* @return
*/
List<AlbumInfo> getUserAllAlbumList(Long userId);
AlbumInfoServiceImpl实现类
/**
* 查询用户发布专辑列表,用于下拉列表展示
*
* @param userId
* @return
*/
@Override
public List<AlbumInfo> getUserAllAlbumList(Long userId) {
//1.构建查询条件
LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
// 用户ID
queryWrapper.eq(AlbumInfo::getUserId, userId);
// 限制查询字段
queryWrapper.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle);
// 按照ID降序
queryWrapper.orderByDesc(AlbumInfo::getId);
// SQL 最后拼接 limit 200
queryWrapper.last("limit 200");
//2.执行查询专辑表
return albumInfoMapper.selectList(queryWrapper);
}
腾讯云点播服务面向音视频、图片等媒体,提供制作上传、存储、转码、媒体处理、媒体 AI、加速分发播放、版权保护等一体化高品质媒体服务。使用腾讯云服务可以为音视频文件的存储、传输、处理和分发提供可靠、高效和安全的解决方案。这可以节省你自己构建和维护存储基础设施的成本和精力,并为用户提供更好的音视频体验。
快速接入流程:云点播 快速入门-文档中心-腾讯云 (tencent.com)
微信扫码登录
关注公众号
搜索云点播
微信认证
实名认证
立即开通服务
右边:点击访问管理
需求:主播录制的音频文件需要上传到腾讯云-云点播云服务器,在声音表
中存储音频文件腾讯云地址。
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/29
准备工作:
在nacos配置中心service-album-dev.yaml
中定义点播服务相关配置信息
vod:
appId: 1255727855 #需要修改为自己的
secretId: AKIDTOFybJvQqCWnDdyDNRQJ54xkT8hBbxCK #需要修改为自己的
secretKey: DKLH87saCmKZowS09IPRLE4pVCqQuKeu #需要修改为自己的
region: ap-beijing #需要修改为自己的
procedure: SimpleAesEncryptPreset #任务流
#tempPath: /root/tingshu/tempPath
tempPath: D:\code\workspace2023\tingshu\temp
playKey: wrTwwu8U3DRSRDgC8l7q #播放加密key
通过配置类读取(已提供)
package com.atguigu.tingshu.album.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix="vod") //读取节点
@Data
public class VodConstantProperties {
private Integer appId;
private String secretId;
private String secretKey;
//https://cloud.tencent.com/document/api/266/31756#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
private String region;
private String procedure;
private String tempPath;
private String playKey;
}
TrackInfoApiController控制器:
package com.atguigu.tingshu.album.api;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.common.result.Result;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
@Tag(name = "声音管理")
@RestController
@RequestMapping("api/album")
@SuppressWarnings({"all"})
public class TrackInfoApiController {
@Autowired
private TrackInfoService trackInfoService;
@Autowired
private VodService vodService;
/**
* 上传本地音频文件到腾讯云点播平台
*
* @param file 声音文件
* @return 上传成功后点播平台:音频文件唯一标识、音频文件播放地址
*/
@Operation(summary = "上传本地音频文件到腾讯云点播平台")
@PostMapping("/trackInfo/uploadTrack")
public Result<Map<String, String>> uploadTrack(MultipartFile file) {
Map<String, String> mapResult = vodService.uploadTrack(file);
return Result.ok(mapResult);
}
}
VodService接口
package com.atguigu.tingshu.album.service;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
public interface VodService {
/**
* 上传本地音频文件到腾讯云点播平台
* @param file 声音文件
* @return 上传成功后点播平台:音频文件唯一标识、音频文件播放地址
*/
Map<String, String> uploadTrack(MultipartFile file);
}
VodServiceImpl实现类 云点播 Java SDK-开发指南-文档中心-腾讯云 (tencent.com) Java 语言实现声音上传功能API
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.execption.GuiguException;
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.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.HashMap;
import java.util.Map;
/**
* 跟腾讯云点播交互业务类
*/
@Slf4j
@Service
public class VodServiceImpl implements VodService {
@Autowired
private VodConstantProperties props;
/**
* 上传本地音频文件到腾讯云点播平台
*
* @param file 声音文件
* @return 上传成功后点播平台:音频文件唯一标识、音频文件播放地址
*/
@Override
public Map<String, String> uploadTrack(MultipartFile file) {
try {
//1.将文件上传到本地指定临时目录下得到本地上传路径
String uploadTempPath = UploadFileUtil.uploadTempPath(props.getTempPath(), file);
//2.调用腾讯云点播接口,将文件上传到云点播平台
//2.1 初始化一个上传客户端对象VodUploadClient
VodUploadClient client = new VodUploadClient(props.getSecretId(), props.getSecretKey());
//2.2 构造上传请求对象,设置媒体文件本地路径
VodUploadRequest request = new VodUploadRequest();
request.setMediaFilePath(uploadTempPath);
//2.3 调用上传
VodUploadResponse response = client.upload(props.getRegion(), request);
//3.上传成功后获取文件唯一标识、文件在线地址
if (response != null) {
String fileId = response.getFileId();
String mediaUrl = response.getMediaUrl();
//封装Map 设置云点播平台文件唯一标识 文件播放地址
Map<String, String> mapResult = new HashMap<>();
mapResult.put("mediaFileId", fileId);
mapResult.put("mediaUrl", mediaUrl);
return mapResult;
}
return null;
} catch (Exception e) {
log.error("[专辑服务]上传文件到点播平台异常:{}", e);
throw new RuntimeException(e);
}
}
}
上传之后可以在:音视频管理 - 媒资管理 - 云点播 - 控制台 (tencent.com)-应用管理-点击主应用-媒资管理-音视频管理看是否有音频
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/31
前端传递Json 字符串,此时我们可以使用封装好的TrackInfoVo实体类进行接收,方便处理数据
涉及到的表:
track_info 声音信息表
track_stat 声音统计表
album_info 专辑表
TrackInfoApiController控制器
/**
* TODO 该接口必须才能访问
* 内容创作者、运营人员保存声音
*
* @return
*/
@Operation(summary = "保存声音")
@PostMapping("/trackInfo/saveTrackInfo")
public Result saveTrackInfo(@RequestBody @Validated TrackInfoVo trackInfoVo) {
//1.先获取登录用户ID
Long userId = AuthContextHolder.getUserId();
//2.调用业务层保存声音
trackInfoService.saveTrackInfo(userId, trackInfoVo);
return Result.ok();
}
TrackInfoService接口
/**
* 内容创作者、运营人员保存声音
* @param userId 当前登录用户ID
* @param trackInfoVo 声音VO对象
*/
void saveTrackInfo(Long userId, TrackInfoVo trackInfoVo);
/**
* 保存声音统计信息
* @param id
* @param statType
*/
void saveTrackStat(Long id, String statType);
TrackInfoServiceImpl实现类
package com.atguigu.tingshu.album.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.atguigu.tingshu.album.config.VodConstantProperties;
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.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.util.UploadFileUtil;
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.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {
@Autowired
private TrackInfoMapper trackInfoMapper;
@Autowired
private VodConstantProperties props;
@Autowired
private AlbumInfoMapper albumInfoMapper;
@Autowired
private VodService vodService;
@Autowired
private TrackStatMapper trackStatMapper;
/**
* 内容创作者、运营人员保存声音
*
* @param userId 当前登录用户ID
* @param trackInfoVo 声音VO对象
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveTrackInfo(Long userId, TrackInfoVo trackInfoVo) {
//1. 封装声音VO对象 保存声音
//1.1 将提交声音VO转为PO对象
TrackInfo trackInfo = BeanUtil.copyProperties(trackInfoVo, TrackInfo.class);
//1.2 手动为声音对象赋值 用户ID、声音来源、状态、声音序号、媒体文件详情
trackInfo.setUserId(userId);
trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId());
Long count = trackInfoMapper.selectCount(queryWrapper);
trackInfo.setOrderNum(count.intValue() + 1);
//1.3 调用腾讯云点播获取媒体文件详情接口获取 声音时长、声音类型
TrackMediaInfoVo mediaInfoVo = vodService.getTrackMediaInfo(trackInfo.getMediaFileId());
if (mediaInfoVo != null) {
trackInfo.setMediaType(mediaInfoVo.getType());
trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfoVo.getDuration()));
trackInfo.setMediaSize(mediaInfoVo.getSize());
}
//1.4 保存声音
trackInfoMapper.insert(trackInfo);
//2.初始化保存声音统计信息
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
//3.为声音所属专辑包含声音数量+1
AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
albumInfoMapper.updateById(albumInfo);
}
}
初始化统计数据
/**
* 新增声音统计信息
* @param trackId
* @param statType
*/
@Override
public void saveTrackStat(Long trackId, String statType) {
TrackStat trackStat = new TrackStat();
trackStat.setTrackId(trackId);
trackStat.setStatType(statType);
trackStat.setStatNum(0);
trackStatMapper.insert(trackStat);
}
获取流媒体数据方法实现 参考地址API Explorer - 云 API - 控制台 (tencent.com)
VodService
package com.atguigu.tingshu.album.service;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
public interface VodService {
/**
* 根据点播平台文件唯一标识获取文件详情
* @param mediaFileId
* @return
*/
TrackMediaInfoVo getTrackMediaInfo(String mediaFileId);
}
VodServiceImpl
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.execption.GuiguException;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
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;
/**
* 跟腾讯云点播交互业务类
*/
@Slf4j
@Service
public class VodServiceImpl implements VodService {
@Autowired
private VodConstantProperties props;
/**
* 根据点播平台文件唯一标识获取文件详情
*
* @param mediaFileId
* @return
*/
@Override
public TrackMediaInfoVo getTrackMediaInfo(String mediaFileId) {
try {
//1. 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey
Credential cred = new Credential(props.getSecretId(), props.getSecretKey());
//2. 实例化要请求产品的client对象,clientProfile是可选的
VodClient client = new VodClient(cred, props.getRegion());
//3. 实例化一个请求对象,每个接口都会对应一个request对象
DescribeMediaInfosRequest req = new DescribeMediaInfosRequest();
String[] fileIds1 = {mediaFileId};
req.setFileIds(fileIds1);
//4.调用媒体描述API接口,返回的resp是一个DescribeMediaInfosResponse的实例
DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req);
if (resp != null) {
//4.1 解析响应结果中 文件大小,时长,文件类型
MediaInfo[] mediaInfoSet = resp.getMediaInfoSet();
if (mediaInfoSet != null && mediaInfoSet.length == 1) {
MediaInfo mediaInfo = mediaInfoSet[0];
//获取媒体基本信息
MediaBasicInfo basicInfo = mediaInfo.getBasicInfo();
String type = basicInfo.getType();
//获取媒体元信息
MediaMetaData metaData = mediaInfo.getMetaData();
Float duration = metaData.getDuration();
Long size = metaData.getSize();
//封装媒体信息VO对象
TrackMediaInfoVo vo = new TrackMediaInfoVo();
vo.setType(type);
vo.setDuration(duration);
vo.setSize(size);
return vo;
}
}
} catch (Exception e) {
log.error("[专辑服务]获取云点播平台媒体信息异常:{}", e);
throw new GuiguException(500, "获取云点播平台媒体信息异常");
}
return null;
}
}
功能入口:运行小程序-->我的-->创作中心-->声音-->查询当前用户的声音列表,如下图所示:
查询分析:需要根据用户Id,状态或标题查询当前声音列表!这三个条件被封装到一个实体类中 TrackInfoQuery,返回结果对象封装到 TrackListVo 实体类中 修改下评论数属性:commentStatNum
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/33
TrackInfoApiController 控制器
/**
* TODO 必须登录才可以访问
* 获取当前登录声音分页列表
*
* @param page 页码
* @param limit 页大小
* @param trackInfoQuery 查询条件
* @return
*/
@Operation(summary = "获取当前登录声音分页列表")
@PostMapping("/trackInfo/findUserTrackPage/{page}/{limit}")
public Result<Page<TrackListVo>> getUserTrackByPage(@PathVariable int page, @PathVariable int limit, @RequestBody TrackInfoQuery trackInfoQuery) {
//1.获取用户ID
Long userId = AuthContextHolder.getUserId();
//2.封装分页查询对象
trackInfoQuery.setUserId(userId);
//3.调用业务层进行分页
Page<TrackListVo> PageInfo = new Page<>(page, limit);
PageInfo = trackInfoService.getUserTrackByPage(PageInfo, trackInfoQuery);
return Result.ok(PageInfo);
}
TrackInfoService接口
/**
* 获取当前登录声音分页列表
* @param pageInfo MP分页对象
* @param trackInfoQuery 查询声音条件对象
* @return
*/
Page<TrackListVo> getUserTrackByPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery);
TrackInfoServiceImpl实现类
/**
* 获取当前登录声音分页列表
* @param pageInfo MP分页对象
* @param trackInfoQuery 查询声音条件对象
* @return
*/
@Override
public Page<TrackListVo> getUserTrackByPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
return trackInfoMapper.getUserTrackByPage(pageInfo, trackInfoQuery);
}
TrackInfoMapper接口
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;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface TrackInfoMapper extends BaseMapper<TrackInfo> {
/**
* MP框架发现参数中包含分页对象,自动完成分页查询(自动查询总记录数,总页数,当前页数据自动封装到Page对象中)
* @param pageInfo
* @param trackInfoQuery
* @return
*/
Page<TrackListVo> getUserTrackByPage(Page<TrackListVo> pageInfo, @Param("vo") TrackInfoQuery trackInfoQuery);
}
SQL实现:
#需求:查询当前创作者声音分页查询,需要显示声音基本信息、声音各项统计信息
#关联查询表:声音表、声音统计表
#关联方式:外连接、内连接均可
#关联字段:统计表声音ID 跟 声音表主键 关联
#查询条件:用户ID,状态、声音标题、删除标识
select * from track_info where id = 51946;
select * from track_stat where track_id = 51946;
# 关联查询
select
ti.id trackId,
ti.track_title,
ti.album_id,
ti.cover_url,
ti.media_duration,
ti.status,
ts.stat_type,
ts.stat_num
from track_info ti left join track_stat ts on ts.track_id = ti.id;
#根据声音ID进行分组
select
ti.id trackId,
ti.track_title,
ti.album_id,
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 left join track_stat ts on ts.track_id = ti.id
group by ti.id
#增加查询条件 用户ID,状态、声音标题、删除标识
select
ti.id trackId,
ti.track_title,
ti.album_id,
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 left join track_stat ts on ts.track_id = ti.id
where user_id = ? and status = ? and track_title like concat('%', ?, '%') and ti.is_deleted = 0
group by ti.id
order by ti.id desc
TrackInfoMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.tingshu.album.mapper.TrackInfoMapper">
<!--查询当前创作者发布声音列表-包含统计信息-->
<select id="getUserTrackPage" resultType="com.atguigu.tingshu.vo.album.TrackListVo">
select
ti.id trackId,
ti.track_title,
ti.album_id,
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 left join track_stat ts on ts.track_id = ti.id
<where>
<if test="vo.userId != null">
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>
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/35
TrackInfoApiController控制器
/**
* 根据声音ID查询声音信息
*
* @param id
* @return
*/
@Operation(summary = "根据声音ID查询声音信息")
@GetMapping("/trackInfo/getTrackInfo/{id}")
public Result<TrackInfo> getTrackInfo(@PathVariable Long id) {
TrackInfo trackInfo = trackInfoService.getById(id);
return Result.ok(trackInfo);
}
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/37
TrackInfoApiController控制器
传递声音Id ,封装好的TrackInfoVo 实体类。
/**
* 修改声音
*
* @param id
* @return
*/
@Operation(summary = "修改声音信息")
@PutMapping("/trackInfo/updateTrackInfo/{id}")
public Result updateTrackInfo(@PathVariable Long id, @RequestBody @Validated TrackInfoVo trackInfoVo) {
trackInfoService.updateTrackInfo(id, trackInfoVo);
return Result.ok();
}
TrackInfoService接口
/**
* 修改声音
*
* @param id 声音ID
* @param trackInfoVo 修改后声音信息
* @return
*/
void updateTrackInfo(Long id, TrackInfoVo trackInfoVo);
TrackInfoServiceImpl实现类
/**
* 修改声音
*
* @param id 声音ID
* @param trackInfoVo 修改后声音信息
* @return
*/
@Override
public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
//1.判断声音文件是否变更,如果变更更新声音媒体文件信息(类型、大小、时长)
//1.1 根据声音ID查询声音对象
TrackInfo trackInfo = trackInfoMapper.selectById(id);
String orginalMediaFileId = trackInfo.getMediaFileId();
BeanUtil.copyProperties(trackInfoVo, trackInfo);
//1.2 查询数据库中声音唯一标识跟提交VO对象中唯一标识比对
//1.3 如果不一致说明变更,调用腾讯云点播接口获取变更后声音信息
if (!orginalMediaFileId.equals(trackInfoVo.getMediaFileId())) {
TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
trackInfo.setMediaType(trackMediaInfo.getType());
trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfo.getDuration()));
trackInfo.setMediaSize(trackMediaInfo.getSize());
}
//2.根据主键更新声音信息
trackInfoMapper.updateById(trackInfo);
}
涉及的表: track_info,album_info,track_stat,media
YAPI接口地址:http://192.168.200.6:3000/project/11/interface/api/39
TrackInfoApiController控制器
/**
* TODO 该接口需要登录才能访问
* 删除声音
*
* @param id
* @return
*/
@Operation(summary = "根据声音ID删除声音")
@DeleteMapping("/trackInfo/removeTrackInfo/{id}")
public Result removeTrackInfo(@PathVariable Long id) {
trackInfoService.removeTrackInfo(id);
return Result.ok();
}
TrackInfoService接口:
/**
* 删除声音
* @param id
*/
void removeTrackInfo(Long id);
TrackInfoServiceImpl实现类
/**
* 删除声音
* <p>
* 1.更新序号大于删除声音列表,更新序号 对序号减一
* 2.删除声音记录
* 3.删除声音统计记录
* 4.更新专辑包含声音数量
* 5.调用腾讯云点播平台将声音音频文件删除
*
* @param id
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void removeTrackInfo(Long id) {
//1.更新序号大于删除声音列表,更新序号 对序号减一
//1.1 先获取删除声音信息 获取序号
TrackInfo trackInfo = trackInfoMapper.selectById(id);
//1.2 批量更新比当前声音序号大声音序号值
trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
//2.删除声音记录
trackInfoMapper.deleteById(id);
//3.删除声音统计记录
LambdaQueryWrapper<TrackStat> trackStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
trackStatLambdaQueryWrapper.eq(TrackStat::getTrackId, id);
trackStatMapper.delete(trackStatLambdaQueryWrapper);
//4.更新专辑包含声音数量
AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
albumInfoMapper.updateById(albumInfo);
//5.调用腾讯云点播平台将声音音频文件删除
vodService.deleteTrackMedia(trackInfo.getMediaFileId());
}
TrackInfoMapper
/**
* 更新声音序号值
* @param albumId
* @param orderNum
*/
void updateOrderNum(@Param("albumId") Long albumId, @Param("orderNum") Integer orderNum);
TrackInfoMapper.xml
<update id="updateOrderNum">
update track_info set order_num = order_num - 1 where album_id = #{albumId} and order_num > #{orderNum} and is_deleted = 0
</update>
VodService接口与实现类
/**
* 删除云点播平台文件
* @param mediaFileId
*/
void deleteTrackMedia(String mediaFileId);
API Explorer - 云 API - 控制台 (tencent.com)
/**
* 删除云点播平台文件
*
* @param mediaFileId
*/
@Override
public void deleteTrackMedia(String mediaFileId) {
try {
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential(prop.getSecretId(), prop.getSecretKey());
// 实例化一个http选项,可选的,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("vod.tencentcloudapi.com");
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
VodClient client = new VodClient(cred, "", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DeleteMediaRequest req = new DeleteMediaRequest();
req.setFileId(mediaFileId);
// 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应
DeleteMediaResponse resp = client.DeleteMedia(req);
// 输出json格式的字符串回包
log.info(DeleteMediaResponse.toJsonString(resp));
} catch (Exception e) {
log.error("【专辑服务】删除元点播媒体文件异常:{}", e);
}
}