提交 28d93861 编写于 作者: F fengyw

增加点播私有化的功能

上级 0992ee2a
......@@ -143,7 +143,7 @@
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-common-polyv</artifactId>
<artifactId>roncoo-education-common-video</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
......
......@@ -18,7 +18,7 @@
<modules>
<module>roncoo-education-common-log</module>
<module>roncoo-education-common-core</module>
<module>roncoo-education-common-polyv</module>
<module>roncoo-education-common-video</module>
<module>roncoo-education-common-service</module>
</modules>
</project>
......@@ -16,7 +16,7 @@ public enum VodPlatformEnum {
/**
* 私有云
*/
PRIVATE(1, "私有云(待开发)", "pri%"),
PRIVATE(1, "私有", "pri%"),
/**
* 保利威
......
......@@ -76,9 +76,9 @@ public final class BeanUtil<T extends Serializable> {
return cn.hutool.core.bean.BeanUtil.toBeanIgnoreCase(map, clazz, true);
}
public static Map<String, String> beanToStringMap(Object obj) {
public static Map<String, Object> beanToStringMap(Object obj) {
try {
Map<String, String> resultMap = new HashMap<>();
Map<String, Object> resultMap = new HashMap<>();
//获取类的属性描述器
BeanInfo beaninfo = Introspector.getBeanInfo(obj.getClass(), Object.class);
//获取类的属性集
......
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.common.polyv.vod;
import lombok.Data;
import java.io.Serializable;
/**
* @author LYQ
*/
@Data
public class CallbackVodAuthCode implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 跑马灯显示内容
*/
private String showText;
/**
* 课时ID
*/
private Long periodId;
}
......@@ -10,8 +10,8 @@
<version>12.0.0-RELEASE</version>
</parent>
<artifactId>roncoo-education-common-polyv</artifactId>
<name>roncoo-education-common-polyv</name>
<artifactId>roncoo-education-common-video</artifactId>
<name>roncoo-education-common-video</name>
<dependencies>
<dependency>
......
package com.roncoo.education.common.video;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.roncoo.education.common.core.enums.VodPlatformEnum;
import com.roncoo.education.common.core.tools.JSUtil;
import com.roncoo.education.common.video.impl.polyv.PolyvVodUtil;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvVideoInfoResp;
import com.roncoo.education.common.video.impl.priyun.PrivateYunVodUtil;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunPlayTokenRes;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunVideoClarityResp;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunVideoInfoResp;
import com.roncoo.education.common.video.req.VideoConfig;
import com.roncoo.education.common.video.req.VodPlayConfigReq;
import com.roncoo.education.common.video.resp.VodInfoResp;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
/**
* 视频点播工具类
*
* @author fengyw
*/
@Slf4j
public final class VodUtil {
private VodUtil() {
}
/**
* 视频云初始化
*
* @param req
*/
public static void init(VideoConfig req) {
if (VodPlatformEnum.POLYV.getCode().equals(req.getVodPlatform())) {
// 设置视频回调地址
String callbackUrl = req.getWebsiteDomain() + "gateway/course/api/callback/polyv/upload";
PolyvVodUtil.setCallback(req.getPolyvAppId(), req.getPolyvAppSecret(), callbackUrl);
// 开启加密,使用web授权
PolyvVodUtil.setPlaysafe(req.getPolyvUserId(), req.getPolyvSecretKey(), "1", "web");
// 设置授权播放和防录屏跑马灯地址
String marqueeUrl = req.getWebsiteDomain() + "gateway/course/api/callback/polyv/vod/auth";
PolyvVodUtil.setMarquee(req.getPolyvAppId(), req.getPolyvAppSecret(), marqueeUrl);
} else if (VodPlatformEnum.PRIVATE.getCode().equals(req.getVodPlatform())) {
// 无需初始化
}
}
/**
* 获取上传配置,web端上传视频
*
* @return json
*/
public static String getUploadConfig(VideoConfig req) {
if (VodPlatformEnum.POLYV.getCode().equals(req.getVodPlatform())) {
return JSUtil.toJsonString(PolyvVodUtil.getUploadConfig(req.getPolyvUserId(), req.getPolyvSecretKey(), req.getPolyvWriteToken()));
} else if (VodPlatformEnum.PRIVATE.getCode().equals(req.getVodPlatform())) {
// 上传回调地址
String callbackUrl = req.getWebsiteDomain() + "gateway/course/api/callback/priyun/vod/upload";
return JSUtil.toJsonString(PrivateYunVodUtil.getUploadConfig(req.getPriYunAccessKeyId(), req.getPriYunAccessKeySecret(), req.getPriYunUrl(), callbackUrl, ""));
}
return "";
}
/**
* 获取视频信息
*
* @param req
* @param vid
* @return
*/
public static VodInfoResp getVideoInfo(VideoConfig req, String vid) {
VodInfoResp resp = new VodInfoResp();
resp.setVodPlatform(req.getVodPlatform());
resp.setVid(vid);
if (VodPlatformEnum.POLYV.getCode().equals(req.getVodPlatform())) {
List<PolyvVideoInfoResp> responseList = PolyvVodUtil.getVideoInfo(Collections.singletonList(vid), req.getPolyvUserId(), req.getPolyvSecretKey());
if (CollectionUtil.isEmpty(responseList)) {
return null;
}
PolyvVideoInfoResp.BasicInfo basicInfo = responseList.get(0).getBasicInfo();
// 视频状态码(60/61:已发布、10:等待编码、20:正在编码、40:编码失败、50:等待审核、51:审核不通过、-1:已删除)
if (basicInfo.getStatus() == 60 || basicInfo.getStatus() == 61) {
// 审核通过
resp.setDuration(basicInfo.getDuration());
resp.setCoverUrl(basicInfo.getCoverURL());
resp.setFileSize(basicInfo.getSize());
} else {
log.warn("保利威-getVideoInfo={}", JSUtil.toJsonString(basicInfo));
}
} else if (VodPlatformEnum.PRIVATE.getCode().equals(req.getVodPlatform())) {
PrivateYunVideoInfoResp videoInfoResp = PrivateYunVodUtil.getVideoInfo(req.getPriYunUrl(), req.getPriYunAccessKeyId(), req.getPriYunAccessKeySecret(), vid, "");
if (ObjectUtil.isNotNull(videoInfoResp)) {
resp.setDuration(Integer.valueOf(videoInfoResp.getVideoDuration()));
resp.setCoverUrl(videoInfoResp.getVideoThumbnail());
resp.setFileSize(Long.valueOf(videoInfoResp.getVideoSize()));
}
}
return resp;
}
/**
* 删除视频
*
* @param req
* @param vid
* @return
*/
public static void deleteVideo(VideoConfig req, String vid) {
if (VodPlatformEnum.POLYV.getCode().equals(req.getVodPlatform())) {
PolyvVodUtil.delete(vid, req.getPolyvUserId(), req.getPolyvSecretKey());
} else if (VodPlatformEnum.PRIVATE.getCode().equals(req.getVodPlatform())) {
PrivateYunVodUtil.delete(req.getPriYunUrl(), req.getPriYunAccessKeyId(), req.getPriYunAccessKeySecret(), vid, "");
}
}
/**
* 获取视频播放配置,返回播放器需要的参数
*
* @param req
* @param playConfigReq
* @return
*/
public static String getPlayConfig(VideoConfig req, VodPlayConfigReq playConfigReq) {
if (VodPlatformEnum.POLYV.getCode().equals(req.getVodPlatform())) {
// 返回播放配置
return JSUtil.toJsonString(PolyvVodUtil.getSignForPlay(req.getPolyvUserId(), req.getPolyvSecretKey(), playConfigReq));
} else if (VodPlatformEnum.PRIVATE.getCode().equals(req.getVodPlatform())) {
// 播放授权地址
String authUrl = req.getWebsiteDomain() + "gateway/course/api/callback/priyun/auth";
PrivateYunPlayTokenRes tokenResponse = PrivateYunVodUtil.token(req.getPriYunUrl(), authUrl, req.getPriYunAccessKeyId(), req.getPriYunAccessKeySecret(), playConfigReq.getVid(), "", playConfigReq.getExpiresIn().toString(), playConfigReq.getViewerId());
PrivateYunVideoClarityResp playUrls = tokenResponse.getVideoClarityResp();
if (ObjectUtil.isNotNull(playUrls)) {
playUrls.setSdUrl(playUrls.getSdUrl() + "?token=" + tokenResponse.getToken());
playUrls.setHdUrl(playUrls.getHdUrl() + "?token=" + tokenResponse.getToken());
}
return JSUtil.toJsonString(playUrls);
}
return "";
}
}
package com.roncoo.education.common.polyv;
package com.roncoo.education.common.video.impl.polyv;
import com.roncoo.education.common.core.tools.JSUtil;
import lombok.extern.slf4j.Slf4j;
......
package com.roncoo.education.common.polyv;
package com.roncoo.education.common.video.impl.polyv;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
......@@ -6,7 +6,7 @@ import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.roncoo.education.common.core.tools.JSUtil;
import com.roncoo.education.common.core.tools.MD5Util;
import com.roncoo.education.common.polyv.vod.CallbackVodAuthCode;
import com.roncoo.education.common.video.req.VodPlayConfigReq;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
......@@ -220,10 +220,10 @@ public class PolyvSignUtil {
* @param code 播放COde
* @return 解码结果
*/
public static CallbackVodAuthCode decodeForPlay(String code) {
public static VodPlayConfigReq.VodAuthCode decodeForPlay(String code) {
try {
code = replace(code);
return JSUtil.parseObject(new String(SecureUtil.des(Base64.decode(PolyvHttpUtil.KEY)).decrypt(Base64.decode(URLDecoder.decode(code, StandardCharsets.UTF_8.name())))), CallbackVodAuthCode.class);
return JSUtil.parseObject(new String(SecureUtil.des(Base64.decode(PolyvHttpUtil.KEY)).decrypt(Base64.decode(URLDecoder.decode(code, StandardCharsets.UTF_8.name())))), VodPlayConfigReq.VodAuthCode.class);
} catch (Exception e) {
log.error("保利威视,解密出错", e);
return null;
......
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.common.polyv;
package com.roncoo.education.common.video.impl.polyv;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
......@@ -15,12 +15,11 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.roncoo.education.common.core.tools.JSUtil;
import com.roncoo.education.common.core.tools.MD5Util;
import com.roncoo.education.common.polyv.vod.CallbackVodAuthCode;
import com.roncoo.education.common.polyv.vod.req.PlayConfigReq;
import com.roncoo.education.common.polyv.vod.resp.PolyvGetKeyframeResp;
import com.roncoo.education.common.polyv.vod.resp.PolyvPlayResponse;
import com.roncoo.education.common.polyv.vod.resp.PolyvVideoInfoResp;
import com.roncoo.education.common.polyv.vod.resp.PolyvVodUploadConfig;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvGetKeyframeResp;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvPlayResponse;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvVideoInfoResp;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvVodUploadConfig;
import com.roncoo.education.common.video.req.VodPlayConfigReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
......@@ -136,8 +135,7 @@ public final class PolyvVodUtil {
config.setPtime(System.currentTimeMillis());
config.setSign(MD5Util.md5(key + config.getPtime()));
config.setHash(MD5Util.md5(config.getPtime() + token));
// 默认分类
config.setCategoryId("0");
config.setCategoryId("1");
return config;
}
......@@ -246,7 +244,7 @@ public final class PolyvVodUtil {
return PolyvHttpUtil.SUCCESS_CODE.equals(resultJson.getInt("code"));
}
public static PolyvPlayResponse getSignForPlay(String userId, String secretKey, PlayConfigReq playConfigReq) {
public static PolyvPlayResponse getSignForPlay(String userId, String secretKey, VodPlayConfigReq playConfigReq) {
// 根据时间戳、vid、密钥生成sign值
String ts = String.valueOf(System.currentTimeMillis());
// 获取播放token
......@@ -281,7 +279,7 @@ public final class PolyvVodUtil {
dto.setSign(MD5Util.md5(secretKey + map.get("videoId") + ts));
dto.setTs(ts);
dto.setToken(dataJson.getStr("token"));
dto.setCode(encodeForPlay(playConfigReq.getCallbackVodAuthCode()));
dto.setCode(encodeForPlay(playConfigReq.getVodAuthCode()));
return dto;
}
......@@ -291,7 +289,7 @@ public final class PolyvVodUtil {
* @param authCode 请求参数
* @return 获取结果
*/
private static String encodeForPlay(CallbackVodAuthCode authCode) {
private static String encodeForPlay(VodPlayConfigReq.VodAuthCode authCode) {
log.debug("获取codePolyvCode={}", JSONUtil.toJsonStr(authCode));
try {
return URLUtil.encodeQuery(Base64.encode(SecureUtil.des(Base64.decode(PolyvHttpUtil.KEY)).encrypt(JSUtil.toJsonString(authCode))), StandardCharsets.UTF_8);
......@@ -308,7 +306,7 @@ public final class PolyvVodUtil {
* @param secretKey 签名秘钥
* @return 签名结果
*/
public static String getCallbackSign(Map<String, String> paramMap, String secretKey) {
public static String getCallbackSign(Map<String, Object> paramMap, String secretKey) {
if (CollectionUtil.isEmpty(paramMap)) {
return null;
}
......
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.common.polyv.vod.resp;
package com.roncoo.education.common.video.impl.polyv.vod.resp;
import java.io.Serializable;
......
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.common.polyv.vod.resp;
package com.roncoo.education.common.video.impl.polyv.vod.resp;
import lombok.Data;
import lombok.experimental.Accessors;
......
/**
* Copyright 2015-现在 广州市领课网络科技有限公司
*/
package com.roncoo.education.common.video.impl.priyun;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunConfigResp;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunPlayTokenRes;
import com.roncoo.education.common.video.impl.priyun.resp.PrivateYunVideoInfoResp;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* 私有化点播工具类
*
* @author wujing
*/
@Slf4j
public final class PrivateYunVodUtil {
/**
* 成功编码
*/
private static final Integer SUCCESS_CODE = 200;
private PrivateYunVodUtil() {
}
public static PrivateYunConfigResp getUploadConfig(String vcloudAccessKeyId, String vcloudAccessKeySecret, String vcloudUrl, String callbackUrl, String state) {
PrivateYunConfigResp privateVodConfig = new PrivateYunConfigResp();
privateVodConfig.setAccessKeyId(vcloudAccessKeyId);
privateVodConfig.setUploadUrl(vcloudUrl + "v1/upload/");
privateVodConfig.setCallbackUrl(callbackUrl);
privateVodConfig.setState(state);
privateVodConfig.setSignatureNonce(String.valueOf(System.currentTimeMillis()));
Map<String, String> paramMap = new HashMap<>();
paramMap.put("accessKeyId", privateVodConfig.getAccessKeyId());
paramMap.put("signatureNonce", privateVodConfig.getSignatureNonce());
privateVodConfig.setSign(getSign(paramMap, vcloudAccessKeySecret));
return privateVodConfig;
}
/**
* 查询视频信息
*
* @param vcloudUrl 点播私有化域名路径
* @param accessKeyId 私有化配置accessKeyId
* @param secretKey 私有化配置accessKeyIdsecretKey
* @param videoVid 视频vid
* @param state 自定义字段(企业ID)
* @return
*/
public static PrivateYunVideoInfoResp getVideoInfo(String vcloudUrl, String accessKeyId, String secretKey, String videoVid, String state) {
String requestUrl = vcloudUrl + "v1/video/detail";
Map<String, String> paramMap = new HashMap<>();
paramMap.put("accessKeyId", accessKeyId);
paramMap.put("signatureNonce", String.valueOf(System.currentTimeMillis()));
// 签名
paramMap.put("sign", getSign(paramMap, secretKey));
paramMap.put("videoVid", videoVid);
paramMap.put("state", state);
// 请求
String result = HttpUtil.post(requestUrl, JSONUtil.toJsonStr(paramMap));
log.info("私有化视--查询视频信息响应结果:{}", result);
JSONObject resultJson = JSONUtil.parseObj(result);
if (SUCCESS_CODE.equals(resultJson.getInt("code"))) {
return JSONUtil.toBean(resultJson.getStr("data"), PrivateYunVideoInfoResp.class);
}
log.info("私有化视--查询视频信息失败:{}", result);
return null;
}
/**
* 删除视频
*
* @param vcloudUrl 点播私有化域名路径
* @param accessKeyId 私有化配置accessKeyId
* @param secretKey 私有化配置accessKeyIdsecretKey
* @param videoVid 视频vid
* @param state 自定义字段(企业ID)
* @return
*/
public static String delete(String vcloudUrl, String accessKeyId, String secretKey, String videoVid, String state) {
String requestUrl = vcloudUrl + "v1/video/delete";
Map<String, String> paramMap = new HashMap<>();
paramMap.put("accessKeyId", accessKeyId);
paramMap.put("signatureNonce", String.valueOf(System.currentTimeMillis()));
// 签名
paramMap.put("sign", getSign(paramMap, secretKey));
paramMap.put("videoVid", videoVid);
paramMap.put("state", state);
// 请求
String result = HttpUtil.post(requestUrl, JSONUtil.toJsonStr(paramMap));
log.info("私有化视--删除视频响应结果:{}", result);
JSONObject resultJson = JSONUtil.parseObj(result);
if (SUCCESS_CODE.equals(resultJson.getInt("code"))) {
return resultJson.getStr("msg");
}
log.info("私有化视--删除视频响应结果失败:{}", result);
return resultJson.getStr("data");
}
/**
* token接口
*
* @param vcloudUrl 点播私有化域名路径
* @param authUrl 授权地址,请求播放时调用该接口
* @param accessKeyId 私有化配置accessKeyId
* @param secretKey 私有化配置accessKeyIdsecretKey
* @param videoVid 视频vid
* @param state 自定义字段(企业ID)
* @param expires 过期时间,单位:S(默认0,不过期)
* @param viewId 观看者id,建议不同的观看者使用不同的id
* @return
*/
public static PrivateYunPlayTokenRes token(String vcloudUrl, String authUrl, String accessKeyId, String secretKey, String videoVid, String state, String expires, String viewId) {
String requestUrl = vcloudUrl + "v1/video/token";
Map<String, String> paramMap = new HashMap<>();
paramMap.put("accessKeyId", accessKeyId);
paramMap.put("signatureNonce", String.valueOf(System.currentTimeMillis()));
// 签名
paramMap.put("sign", getSign(paramMap, secretKey));
paramMap.put("videoVid", videoVid);
paramMap.put("state", state);
paramMap.put("expires", expires);
paramMap.put("viewId", viewId);
paramMap.put("authUrl", authUrl);
// 请求
String result = HttpUtil.post(requestUrl, JSONUtil.toJsonStr(paramMap));
log.info("私有化视--获取token响应结果:{}", result);
JSONObject resultJson = JSONUtil.parseObj(result);
if (SUCCESS_CODE.equals(resultJson.getInt("code"))) {
return JSONUtil.toBean(resultJson.getStr("data"), PrivateYunPlayTokenRes.class);
}
log.info("私有化视--获取token响应结果:{}", result);
return null;
}
private static String getSign(Object param, String key) {
// 排序
Map<String, Object> paramMap = JSONUtil.parseObj(JSONUtil.toJsonStr(param));
SortedMap<String, Object> treeMap = new TreeMap<>(paramMap);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
if (!"sign".equals(entry.getKey()) && StrUtil.isNotBlank(String.valueOf(entry.getValue()))) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
sb.append("key=").append(key);
return SecureUtil.md5(sb.toString());
}
}
package com.roncoo.education.common.video.impl.priyun.enums;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 视频状态
*
* @author LYQ
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum PrivateYunVideoStatusEnum {
/**
* 上传中
*/
UPLOADING(1, "上传中"),
/**
* 上传失败
*/
UPLOAD_FAIL(2, "上传失败"),
/**
* 转码中
*/
TRANSCODING(3, "转码中"),
/**
* 转码失败
*/
TRANSCODE_FAIL(4, "转码失败"),
/**
* 转码完成
*/
COMPLETE(5, "完成");
/**
* 编码
*/
private final Integer code;
/**
* 描述
*/
private final String desc;
}
package com.roncoo.education.common.video.impl.priyun.req;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author fengyw
*/
@Data
@Accessors(chain = true)
public class PrivateYunVodAuth {
private String videoVid;
private String viewId;
private String state;
}
package com.roncoo.education.common.video.impl.priyun.req;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author fengyw
*/
@Data
@Accessors(chain = true)
public class PrivateYunVodUpload {
private String videoVid;
private int videoStatus;
}
package com.roncoo.education.common.video.impl.priyun.resp;
import lombok.Data;
@Data
public class PrivateYunConfigResp {
private String uploadUrl;
private String callbackUrl;
private String accessKeyId;
private String state;
private String tags;
private String signatureNonce;
private String sign;
}
package com.roncoo.education.common.video.impl.priyun.resp;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 获取token返回信息
*
* @author LYQ
*/
@Data
@Accessors(chain = true)
public class PrivateYunPlayTokenRes implements Serializable {
private static final long serialVersionUID = 1L;
private String videoVid;
private String token;
private PrivateYunVideoClarityResp videoClarityResp;
}
package com.roncoo.education.common.video.impl.priyun.resp;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* <p>
* 视频清晰度播放地址
* </p>
*
* @author zhandehuang
* @version 1.0
* @date 2022/5/27 0027
*/
@Data
@Accessors(chain = true)
public class PrivateYunVideoClarityResp {
private static final long serialVersionUID = 1L;
private String sdUrl;
private String hdUrl;
}
package com.roncoo.education.common.video.impl.priyun.resp;
import lombok.Data;
import java.io.Serializable;
/**
* 查询视频信息
*
* @author LYQ
*/
@Data
public class PrivateYunVideoInfoResp implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 视频vid
*/
private String videoVid;
/**
* 视频缩略图地址
*/
private String videoThumbnail;
/**
* 视频分辨率
*/
private String videoDefinition;
/**
* 视频时长
*/
private String videoDuration;
/**
* 视频MD5
*/
private String videoMd5;
/**
* 视频名称
*/
private String videoName;
/**
* 视频码率
*/
private String videoRate;
/**
* 视频大小
*/
private String videoSize;
/**
* 视频状态(1:上传中;2:上传失败;3:转码中;4:转码失败;5:转码完成)
*/
private String videoStatus;
}
package com.roncoo.education.common.video.req;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 视频云配置
*
* @author fengyw
*/
@Data
@Accessors(chain = true)
public class VideoConfig implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 网关域名
*/
private String websiteDomain;
/**
* 点播平台(1:私有云、2:保利威、3:百家云)
*/
private Integer vodPlatform;
/**
* 点播跑马灯(0:关闭、1:开启)
*/
private Boolean vodEnableMarquee = false;
/**
* 保利威--账号ID
*/
private String polyvUserId;
/**
* 保利威--写入令牌
*/
private String polyvWriteToken;
/**
* 保利威--读取秘钥
*/
private String polyvReadToken;
/**
* 保利威--安全秘钥
*/
private String polyvSecretKey;
/**
* 保利威--应用ID
*/
private String polyvAppId;
/**
* 保利威--应用秘钥
*/
private String polyvAppSecret;
/**
* 私有化,Url
*/
private String priYunUrl;
/**
* 私有化,AccessKeyId
*/
private String priYunAccessKeyId;
/**
* 私有化,AccessKeySecret
*/
private String priYunAccessKeySecret;
}
package com.roncoo.education.common.polyv.vod.req;
package com.roncoo.education.common.video.req;
import com.roncoo.education.common.polyv.vod.CallbackVodAuthCode;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
......@@ -8,14 +7,14 @@ import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 查询视频信息
* 点播-播放请求参数
*
* @author LYQ
* @author fengyw
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
public class PlayConfigReq implements Serializable {
public class VodPlayConfigReq implements Serializable {
private static final long serialVersionUID = 2222356652726536710L;
......@@ -30,11 +29,11 @@ public class PlayConfigReq implements Serializable {
/**
* 是否为移动端
*/
private Boolean appWatch;
private Boolean appWatch = false;
/**
* 终端类型(1:pc,2:h5,3:android,4:ios,5:微信小程序)
*/
private String terminal;
private String terminal = "1";
/**
* 观看者ID
*/
......@@ -50,17 +49,19 @@ public class PlayConfigReq implements Serializable {
/**
* 透传字段
*/
private String extraParams;
private String extraParams = "HTML5";
private CallbackVodAuthCode callbackVodAuthCode;
private VodAuthCode vodAuthCode;
public PlayConfigReq(String vid, Boolean appWatch, String terminal, String viewerId, String viewerIp, String viewerName, CallbackVodAuthCode callbackVodAuthCode) {
this.vid = vid;
this.appWatch = appWatch;
this.terminal = terminal;
this.viewerId = viewerId;
this.viewerIp = viewerIp;
this.viewerName = viewerName;
this.callbackVodAuthCode = callbackVodAuthCode;
@Data
public static class VodAuthCode {
/**
* 用户ID
*/
private Long userId;
/**
* 课时ID
*/
private Long periodId;
}
}
package com.roncoo.education.common.video.resp;
import lombok.Data;
import java.io.Serializable;
/**
* 查询视频信息
*
* @author fengyw
*/
@Data
public class VodInfoResp implements Serializable {
private static final long serialVersionUID = 2222356652726536710L;
/**
* 视频云平台
*/
private Integer vodPlatform;
/**
* 视频id
*/
private String vid;
/**
* 时长(单位:秒)
*/
private Integer duration;
/**
* 封面URL
*/
private String coverUrl;
/**
* 源文件大小,单位:字节
*/
private Long fileSize;
}
......@@ -33,7 +33,7 @@
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-common-polyv</artifactId>
<artifactId>roncoo-education-common-video</artifactId>
</dependency>
<!-- test -->
......
package com.roncoo.education.course.service.admin.biz;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.roncoo.education.common.core.base.Page;
import com.roncoo.education.common.core.base.PageUtil;
import com.roncoo.education.common.core.base.Result;
import com.roncoo.education.common.core.enums.ResourceTypeEnum;
import com.roncoo.education.common.core.tools.BeanUtil;
import com.roncoo.education.common.core.tools.JSUtil;
import com.roncoo.education.common.core.tools.MD5Util;
import com.roncoo.education.common.service.BaseBiz;
import com.roncoo.education.common.video.VodUtil;
import com.roncoo.education.course.dao.CourseChapterPeriodDao;
import com.roncoo.education.course.dao.ResourceDao;
import com.roncoo.education.course.dao.impl.mapper.entity.CourseChapterPeriod;
......@@ -51,6 +54,8 @@ public class AdminResourceBiz extends BaseBiz {
VodConfig vodConfig = feignSysConfig.getVod();
AdminVodConfigResp resp = new AdminVodConfigResp();
resp.setVodPlatform(vodConfig.getVodPlatform());
resp.setVodUploadConfig(VodUtil.getUploadConfig(vodConfig));
resp.setPolyvConfig(getCofigByPolyv(vodConfig));
return Result.success(resp);
}
......@@ -133,12 +138,19 @@ public class AdminResourceBiz extends BaseBiz {
* @return 删除结果
*/
public Result<String> delete(Long id) {
Resource resource = dao.getById(id);
if (ObjectUtil.isNull(resource)) {
return Result.error("资源不存在");
}
List<CourseChapterPeriod> record = courseChapterPeriodDao.listByResourceId(id);
if (CollUtil.isNotEmpty(record)) {
log.warn("资源引用={}", JSUtil.toJsonString(record.stream().map(CourseChapterPeriod::getPeriodName).collect(Collectors.toList())));
return Result.error("该资源存在引用,暂不能删除");
}
if (dao.deleteById(id) > 0) {
if (ResourceTypeEnum.VIDEO.getCode().equals(resource.getResourceType()) || ResourceTypeEnum.AUDIO.getCode().equals(resource.getResourceType())) {
VodUtil.deleteVideo(feignSysConfig.getVod(), resource.getVideoVid());
}
return Result.success("操作成功");
}
return Result.error("操作失败");
......
......@@ -15,7 +15,12 @@ public class AdminVodConfigResp {
@ApiModelProperty(value = "使用平台")
private Integer vodPlatform;
@ApiModelProperty(value = "视频云上传配置")
private String vodUploadConfig;
@Deprecated
private PolyvConfig polyvConfig;
@Deprecated
private PriConfig priConfig;
/**
......@@ -49,7 +54,6 @@ public class AdminVodConfigResp {
@NoArgsConstructor
@AllArgsConstructor
public static class PriConfig {
// TODO
@ApiModelProperty(value = "sign")
private String sign;
}
......
package com.roncoo.education.course.service.api;
import com.roncoo.education.common.polyv.vod.CallbackVodUpload;
import com.roncoo.education.common.service.BaseController;
import com.roncoo.education.common.video.impl.polyv.vod.CallbackVodUpload;
import com.roncoo.education.course.service.api.biz.ApiCallbackBiz;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
......
package com.roncoo.education.course.service.api.biz;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.roncoo.education.common.core.enums.VideoStatusEnum;
import com.roncoo.education.common.core.tools.BeanUtil;
import com.roncoo.education.common.core.tools.JSUtil;
import com.roncoo.education.common.polyv.PolyvVodUtil;
import com.roncoo.education.common.polyv.vod.CallbackEventTypeEnum;
import com.roncoo.education.common.polyv.vod.CallbackVodUpload;
import com.roncoo.education.common.polyv.vod.resp.PolyvVideoInfoResp;
import com.roncoo.education.common.video.VodUtil;
import com.roncoo.education.common.video.impl.polyv.PolyvVodUtil;
import com.roncoo.education.common.video.impl.polyv.vod.CallbackEventTypeEnum;
import com.roncoo.education.common.video.impl.polyv.vod.CallbackVodUpload;
import com.roncoo.education.common.video.resp.VodInfoResp;
import com.roncoo.education.course.dao.ResourceDao;
import com.roncoo.education.course.dao.impl.mapper.entity.Resource;
import com.roncoo.education.system.feign.interfaces.IFeignSysConfig;
......@@ -17,9 +17,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
/**
* 课程分类
*
......@@ -48,12 +45,11 @@ public class ApiCallbackBiz {
if (CallbackEventTypeEnum.PASS.getCode().equals(callbackVodUpload.getType())) {
// 视频审核完成处理
List<PolyvVideoInfoResp> responseList = PolyvVodUtil.getVideoInfo(Collections.singletonList(callbackVodUpload.getVid()), vodConfig.getPolyvUserId(), vodConfig.getPolyvSecretKey());
if (CollUtil.isNotEmpty(responseList)) {
PolyvVideoInfoResp videoResponse = responseList.get(0);
VodInfoResp videoResponse = VodUtil.getVideoInfo(vodConfig, callbackVodUpload.getVid());
if (ObjectUtil.isNotNull(videoResponse)) {
Resource resource = resourceDao.getByVideoVid(callbackVodUpload.getVid());
if (ObjectUtil.isNotEmpty(resource)) {
resource.setVideoLength(videoResponse.getBasicInfo().getDuration().toString());
resource.setVideoLength(videoResponse.getDuration().toString());
resource.setVideoStatus(VideoStatusEnum.SUCCES.getCode());
resourceDao.updateById(resource);
}
......
......@@ -2,15 +2,17 @@ package com.roncoo.education.course.service.auth.biz;
import cn.hutool.core.util.ObjectUtil;
import com.roncoo.education.common.config.ThreadContext;
import com.roncoo.education.common.core.base.BaseException;
import com.roncoo.education.common.core.base.Result;
import com.roncoo.education.common.core.enums.*;
import com.roncoo.education.common.polyv.PolyvVodUtil;
import com.roncoo.education.common.polyv.vod.CallbackVodAuthCode;
import com.roncoo.education.common.polyv.vod.req.PlayConfigReq;
import com.roncoo.education.common.polyv.vod.resp.PolyvPlayResponse;
import com.roncoo.education.common.service.BaseBiz;
import com.roncoo.education.course.dao.*;
import com.roncoo.education.common.video.VodUtil;
import com.roncoo.education.common.video.impl.polyv.PolyvVodUtil;
import com.roncoo.education.common.video.impl.polyv.vod.resp.PolyvPlayResponse;
import com.roncoo.education.common.video.req.VodPlayConfigReq;
import com.roncoo.education.course.dao.CourseChapterPeriodDao;
import com.roncoo.education.course.dao.ResourceDao;
import com.roncoo.education.course.dao.UserCourseDao;
import com.roncoo.education.course.dao.UserStudyDao;
import com.roncoo.education.course.dao.impl.mapper.entity.CourseChapterPeriod;
import com.roncoo.education.course.dao.impl.mapper.entity.Resource;
import com.roncoo.education.course.dao.impl.mapper.entity.UserCourse;
......@@ -34,8 +36,6 @@ import java.math.BigDecimal;
@RequiredArgsConstructor
public class AuthCourseBiz extends BaseBiz {
@NotNull
private final CourseDao dao;
@NotNull
private final CourseChapterPeriodDao periodDao;
@NotNull
......@@ -100,24 +100,21 @@ public class AuthCourseBiz extends BaseBiz {
}
private void polyvSign(AuthCourseSignReq req, Resource resource, AuthCourseSignResp resp) {
PlayConfigReq polyvSign = new PlayConfigReq();
polyvSign.setViewerIp(req.getClientIp());
polyvSign.setViewerId(ThreadContext.userId().toString());
polyvSign.setVid(resource.getVideoVid());
// 获取code
CallbackVodAuthCode authCode = new CallbackVodAuthCode();
authCode.setPeriodId(req.getPeriodId());
authCode.setShowText("领课开源");
VodPlayConfigReq playConfigReq = new VodPlayConfigReq();
playConfigReq.setVid(resource.getVideoVid());
playConfigReq.setViewerId(ThreadContext.userId().toString());
playConfigReq.setViewerIp(req.getClientIp());
VodPlayConfigReq.VodAuthCode authCode = new VodPlayConfigReq.VodAuthCode();
authCode.setUserId(ThreadContext.userId());
polyvSign.setCallbackVodAuthCode(authCode);
authCode.setPeriodId(req.getPeriodId());
playConfigReq.setVodAuthCode(authCode);
// 视频云配置
VodConfig vodConfig = feignSysConfig.getVod();
resp.setVodPlatform(vodConfig.getVodPlatform());
resp.setVodPlayConfig(VodUtil.getPlayConfig(vodConfig, playConfigReq));
PolyvPlayResponse polyvSignResponse = PolyvVodUtil.getSignForPlay(vodConfig.getPolyvUserId(), vodConfig.getPolyvSecretKey(), polyvSign);
if (ObjectUtil.isEmpty(polyvSignResponse)) {
throw new BaseException("系统繁忙,请重试");
}
PolyvPlayResponse polyvSignResponse = PolyvVodUtil.getSignForPlay(vodConfig.getPolyvUserId(), vodConfig.getPolyvSecretKey(), playConfigReq);
resp.setTs(polyvSignResponse.getTs());
resp.setSign(polyvSignResponse.getSign());
resp.setToken(polyvSignResponse.getToken());
......
......@@ -37,15 +37,25 @@ public class AuthCourseSignResp implements Serializable {
@ApiModelProperty(value = "播放vid")
private String vid;
@ApiModelProperty(value = "点播平台")
private Integer vodPlatform;
@ApiModelProperty(value = "点播播放配置参数")
private String vodPlayConfig;
@Deprecated
@ApiModelProperty(value = "播放ts")
private String ts;
@Deprecated
@ApiModelProperty(value = "播放sign")
private String sign;
@Deprecated
@ApiModelProperty(value = "播放token")
private String token;
@Deprecated
@ApiModelProperty(value = "播放code")
private String code;
}
......@@ -17,6 +17,10 @@
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-common-video</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
......
package com.roncoo.education.system.feign.interfaces.vo;
import com.roncoo.education.common.video.req.VideoConfig;
import lombok.Data;
import lombok.experimental.Accessors;
......@@ -12,48 +13,8 @@ import java.io.Serializable;
*/
@Data
@Accessors(chain = true)
public class VodConfig implements Serializable {
public class VodConfig extends VideoConfig implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 网关域名
*/
private String websiteDomain;
/**
* 点播平台(1:私有云、2:保利威、3:百家云)
*/
private Integer vodPlatform;
/**
* 保利威--账号ID
*/
private String polyvUserId;
/**
* 保利威--写入令牌
*/
private String polyvWriteToken;
/**
* 保利威--读取秘钥
*/
private String polyvReadToken;
/**
* 保利威--安全秘钥
*/
private String polyvSecretKey;
/**
* 保利威--应用ID
*/
private String polyvAppId;
/**
* 保利威--应用秘钥
*/
private String polyvAppSecret;
}
......@@ -20,7 +20,7 @@
<dependency>
<groupId>com.roncoo</groupId>
<artifactId>roncoo-education-common-polyv</artifactId>
<artifactId>roncoo-education-common-video</artifactId>
</dependency>
<dependency>
<groupId>com.roncoo</groupId>
......
......@@ -3,8 +3,8 @@ package com.roncoo.education.system.service.admin.biz;
import cn.hutool.json.JSONObject;
import com.roncoo.education.common.core.base.Result;
import com.roncoo.education.common.core.tools.BeanUtil;
import com.roncoo.education.common.polyv.PolyvVodUtil;
import com.roncoo.education.common.service.BaseBiz;
import com.roncoo.education.common.video.impl.polyv.PolyvVodUtil;
import com.roncoo.education.system.dao.SysConfigDao;
import com.roncoo.education.system.dao.impl.mapper.entity.SysConfig;
import com.roncoo.education.system.dao.impl.mapper.entity.SysConfigExample;
......
......@@ -9,8 +9,8 @@ import com.roncoo.education.common.core.enums.SmsPlatformEnum;
import com.roncoo.education.common.core.enums.StoragePlatformEnum;
import com.roncoo.education.common.core.enums.VodPlatformEnum;
import com.roncoo.education.common.core.tools.BeanUtil;
import com.roncoo.education.common.polyv.PolyvVodUtil;
import com.roncoo.education.common.service.BaseBiz;
import com.roncoo.education.common.video.VodUtil;
import com.roncoo.education.system.dao.SysConfigDao;
import com.roncoo.education.system.dao.impl.mapper.entity.SysConfig;
import com.roncoo.education.system.dao.impl.mapper.entity.SysConfigExample;
......@@ -148,12 +148,8 @@ public class AdminSysConfigBiz extends BaseBiz {
public Result<String> init() {
Map<String, String> configMap = dao.listByExample(new SysConfigExample()).stream().collect(Collectors.toMap(SysConfig::getConfigKey, SysConfig::getConfigValue));
VodConfig vodConfig = BeanUtil.objToBean(configMap, VodConfig.class);
// 设置视频回调地址
String callbackUrl = vodConfig.getWebsiteDomain() + "gateway/course/api/callback/polyv/upload";
PolyvVodUtil.setCallback(vodConfig.getPolyvAppId(), vodConfig.getPolyvAppSecret(), callbackUrl);
// 开启加密,使用web授权
PolyvVodUtil.setPlaysafe(vodConfig.getPolyvUserId(), vodConfig.getPolyvSecretKey(), "1", "web");
// 初始化
VodUtil.init(vodConfig);
return Result.success("操作成功");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册