wanghongbo

垫片上传、切换相关逻辑修改

... ... @@ -51,6 +51,13 @@ public class BackupMaterialController {
return backupMaterialService.getByRoom(roomId);
}
/**
* @description 修改审片间垫片配置
* @author W5669
* @date 2025/7/24
* @param backupChangeDto
* @return ResultBean
*/
@PostMapping("change")
ResultBean change(@RequestBody BackupChangeDto backupChangeDto){
return backupMaterialService.change(backupChangeDto);
... ...
... ... @@ -18,5 +18,7 @@ public class BackupUploadVo {
private Long roomId;
//1:垫片1,2:垫片2
private Integer backupOrder;
//垫片状态 0-默认 1-当前选中
private String backupStatus;
}
... ...
package com.wondertek.dto;
import lombok.Data;
import java.util.List;
/**
* @Description: 切换频道源请求参数
* @DateTime: 2020/7/25 10:05
*/
@Data
public class ChangeSourceParam {
private String taskId;
private List<SourceUrl> sourceUrls;
private String backupUrl;
/**
* 是否切当前任务使用的源至pri=0的源;
* true,如果当前任务使用非pri=0的源则切至pri=0的源【即:如果当前任务在垫片上则切至主源上】;
* false,不执行切换源操作;
* 默认false
*/
private boolean switchMaster;
}
\ No newline at end of file
... ...
package com.wondertek.dto;
import lombok.Data;
@Data
public class SourceUrl {
//输入源
private String sourceUrl;
//输入源优先级
private int pri;
}
\ No newline at end of file
... ...
... ... @@ -2,35 +2,40 @@ package com.wondertek.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wondertek.dto.BackupChangeDto;
import com.wondertek.dto.BackupMaterialDto;
import com.wondertek.dto.BackupUploadVo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.wondertek.dto.*;
import com.wondertek.entity.BackupConfig;
import com.wondertek.entity.BackupMaterial;
import com.wondertek.entity.StreamTask;
import com.wondertek.enums.PlayTypeEnum;
import com.wondertek.exception.BusinessException;
import com.wondertek.mapper.BackupConfigMapper;
import com.wondertek.mapper.BackupMaterialMapper;
import com.wondertek.mapper.StreamTaskMapper;
import com.wondertek.service.BackupMaterialService;
import com.wondertek.service.FileService;
import com.wondertek.util.FileUtils;
import com.wondertek.util.PageBean;
import com.wondertek.util.ResultBean;
import com.wondertek.util.UUIDUtil;
import com.wondertek.util.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper, BackupMaterial> implements BackupMaterialService {
@Resource
... ... @@ -41,6 +46,12 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
private String realPath;
@Resource
private BackupConfigMapper backupConfigMapper;
@Resource
private StreamTaskMapper streamTaskMapper;
@Value("${transcode.switchStreamUrl}")
private String switchStreamUrl;
@Value("${transcode.swapBackupUrl}")
private String swapBackupUrl;
@Override
... ... @@ -66,22 +77,30 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
@Override
public ResultBean upload(MultipartFile backupFile, BackupUploadVo backupUploadVo) {
//上传文件
//校验
if(!"mp4".equalsIgnoreCase(backupUploadVo.getFileType())){
throw new BusinessException("仅支持上传mp4格式的垫片文件!");
}
//对应垫片任务
LambdaQueryWrapper<StreamTask> backupWrapper = new LambdaQueryWrapper<>();
backupWrapper.eq(StreamTask::getRoomId,backupUploadVo.getRoomId());
String palyType = backupUploadVo.getBackupOrder() == 1? PlayTypeEnum.BACKUP1.getCode() : PlayTypeEnum.BACKUP2.getCode();
backupWrapper.eq(StreamTask::getPlayType,palyType);
StreamTask streamTask = streamTaskMapper.selectOne(backupWrapper);
if (streamTask == null){
return ResultBean.error("未找到该直播间对应的垫片任务");
}
//文件上传
String fileId = UUIDUtil.randomUUID();
String fileName = backupUploadVo.getBackupName() + "." + backupUploadVo.getFileType();
///home/wondertek/material_file_assets/dianpian/2025/07/24/roomid/
String filedir = FileUtils.generateDianPianDir(backupUploadVo.getRoomId().toString(), realPath);
String destFilePath = filedir + fileName;//文件上传目录
String destFilePath = filedir + fileName;//文件上传目录,绝对路径
try {
fileService.upload(backupFile, destFilePath);
} catch (Exception e) {
return ResultBean.error("上传文件异常");
}
//保存垫片素材表
BackupMaterial backupMaterial = new BackupMaterial();
backupMaterial.setFileId(fileId);
... ... @@ -103,21 +122,85 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
backupConfig.setRoomId(backupUploadVo.getRoomId());
backupConfig.setBackupId(backupMaterial.getId());
backupConfig.setBackupOrder(backupUploadVo.getBackupOrder());
backupConfig.setBackupStatus(backupUploadVo.getBackupStatus());
backupConfigMapper.insertOrUpdate(backupConfig);
//对应垫片任务切源(转码平台演示环境已挂载统一存储)
LambdaQueryWrapper<StreamTask> wrapper1 = new LambdaQueryWrapper<>();
wrapper1.eq(StreamTask::getRoomId,backupUploadVo.getRoomId());
wrapper1.eq(StreamTask::getPlayType,"play");
//对应垫片任务切源(转码平台演示环境已挂载统一存储),请求转码平台修改垫片任务直播源
changeChannelSource(streamTask.getTaskId(), destFilePath);
//判断是否需要修改当前播出流的垫片
if("1".equals(backupConfig.getBackupOrder())){
//切换播出流垫片(主、备)
LambdaQueryWrapper<StreamTask> playWrapper = new LambdaQueryWrapper<>();
playWrapper.eq(StreamTask::getRoomId,backupUploadVo.getRoomId());
playWrapper.eq(StreamTask::getPlayType,"play");
List<StreamTask> playTasks = streamTaskMapper.selectList(playWrapper);
if(CollectionUtil.isNotEmpty(playTasks)){
playTasks.forEach(playTask -> {
changeChannelSource(playTask.getTaskId(), destFilePath);
});
}
}
return ResultBean.ok("上传成功");
}
private void changeBackup(String taskId, String destFilePath) {
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("taskId", taskId);
paramsMap.put("backupUrl", destFilePath);
HttpResponse execute = null;
try {
execute = HttpRequest.post(swapBackupUrl)
.header("Content-Type", "application/json")
.body(JSONUtils.obj2json(paramsMap)).timeout(30000).execute();
if (execute.isOk()) {
log.info("-->请求转码系统换垫片接口,url:{},paramsMap:{}",swapBackupUrl,paramsMap);
String body = execute.body();
ResponseData response = JSONUtils.jsonToObject(body, new TypeReference<ResponseData>() {
});
if (response.getResultCode().equals("0")) {
log.info("请求转码系统换垫片接口成功");
}else {
log.info("请求转码系统换垫片接口响应失败,response:{}",response);
}
} else {
log.error("请求转码系统换垫片接口失败,url:{},body:{}", swapBackupUrl, execute.body());
}
} catch (Exception e) {
log.error("请求转码系统换垫片接口失败,url:{}", swapBackupUrl, e);
}
}
private void changeChannelSource(String taskId, String destFilePath) {
ChangeSourceParam param = new ChangeSourceParam();
param.setTaskId(taskId);
SourceUrl sourceUrl = new SourceUrl();
sourceUrl.setSourceUrl(destFilePath);
sourceUrl.setPri(0);
param.setSourceUrls(Arrays.asList(sourceUrl));
HttpResponse execute = null;
try {
execute = HttpRequest.post(switchStreamUrl)
.header("Content-Type", "application/json")
.body(JSONUtils.obj2json(param)).timeout(30000).execute();
if (execute.isOk()) {
log.info("-->请求转码系统切换直播源接口,url:{},paramsMap:{}",switchStreamUrl,param);
String body = execute.body();
ResponseData response = JSONUtils.jsonToObject(body, new TypeReference<ResponseData>() {
});
if (response.getResultCode().equals("0")) {
log.info("请求转码系统切换直播源接口成功");
}else {
log.info("请求转码系统切换直播源接口响应失败,response:{}",response);
}
} else {
log.error("请求转码系统切换直播源接口失败,url:{},body:{}", switchStreamUrl, execute.body());
}
} catch (Exception e) {
log.error("请求转码系统切换直播源接口失败,url:{}", switchStreamUrl, e);
}
}
@Override
public ResultBean getByRoom(Long roomId) {
LambdaQueryWrapper<BackupConfig> wrapper = new LambdaQueryWrapper<>();
... ... @@ -135,8 +218,19 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
backupConfigs.forEach(backupConfig -> {
if(backupConfig.getBackupId().equals(backupChangeDto.getBackupId())){
backupConfig.setBackupStatus("1");
//将播放流的垫片配置切到此垫片上
//将播放流的垫片配置切到此垫片上,播放流主、备都切换
LambdaQueryWrapper<StreamTask> playWrapper = new LambdaQueryWrapper<>();
playWrapper.eq(StreamTask::getRoomId,backupChangeDto.getRoomId());
playWrapper.eq(StreamTask::getPlayType,"play");
List<StreamTask> playTasks = streamTaskMapper.selectList(playWrapper);
if(CollectionUtil.isNotEmpty(playTasks)){
String backupPath = realPath + backupConfig.getBackupPath();
playTasks.forEach(playTask -> {
changeChannelSource(playTask.getTaskId(), backupPath);
});
}
}else {
//将其他垫片配置切到默认状态
backupConfig.setBackupStatus("0");
}
backupConfigMapper.updateById(backupConfig);
... ...
... ... @@ -62,8 +62,13 @@ mybatis-plus:
transcode:
delayTimeUrl: http://192.168.1.237:9002/api/v1/delayTime # 延迟接口
blockStatusUrl: http://192.168.1.237:9002/api/v1/blockStatus # 屏蔽/恢复
switchStreamUrl: http://192.168.1.237:9002/api/v1/switchStream # 切换频道源
swapBackupUrl: http://192.168.1.237:9002/api/v1/swapBackup # 切垫片
getTaskDetail: http://192.168.1.237:9002/api/v1/getTaskDetail
file:
realPath: /home/wondertek/material_file_assets/
crp:
user:
username: admin
... ...