只有添加分发加速的域名才能使用HLS加密,同时也要做HTTPS证书添加,不然也会报错。
1、这是电脑端视频播放页面效果
2、这个手机端H5视频播放页面效果
3、在网站后台上传你的视频内容
4、上传完之后可以进行预览
5、在阿里云控制台设置就好自己的转码模板
将不转码设为默认的原因是自动触发转码不支持HLS标准加密,所以需要先上传不转码,然后根据回调再去调用转码接口,实现手动转码
6、设置上传完成回调 - 用于手动转码
7、创建回调接口
可以用frp搭一个,然后就是正常的restful接口
回调是POST请求,然后请求体我是用 @RequestBody String body接收的,不知道为什么,用对象接收就是不行
请求转码需要用到KMS加密,因此需要准备文档中准备工作的第三步搭建密钥管理服务生成AES_128密钥
// 示例代码
技术开发QQ 735660248
// getClient()是我封装的获取client对象的方法
IAcsClient client = getClient();
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysVersion("2016-01-20");
// 一定要和自己的服务地区相匹配
request.setSysDomain("kms.cn-shenzhen.aliyuncs.com");
request.setSysAction("GenerateDataKey");
// kms服务仅支持HTTPS
request.setSysProtocol(ProtocolType.HTTPS);
// 提交工单后,工作人员会帮你生成,前往KMS控制台就能看到
request.putQueryParameter("KeyId", "KMS控制台中的id");
request.putQueryParameter("KeySpec", "AES_128");
CommonResponse response = client.getCommonResponse(request);
// 封装了一个对象来存储aes_128
aes128 = JSON.parseObject(response.getData(), AliyunGenAes128Vo.class);
log.info("生成AES_128 {}", aes128);
8、请求转码
/**
* 提交转码请求
*/
public static void submitTranscodeJobs(String videoId) throws ClientException {
IAcsClient client = getClient();
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("vod.cn-shenzhen.aliyuncs.com");
request.setSysVersion("2017-03-21");
request.setSysAction("SubmitTranscodeJobs");
// 转码模板
request.putQueryParameter("TemplateGroupId", "转码模板id");
request.putQueryParameter("VideoId", videoId);
request.putQueryParameter("EncryptConfig", genEncryptConfigStr());
CommonResponse response = client.getCommonResponse(request);
log.info("发送转码请求成功 {}", response.getData());
}
/**
* 获取加密配置字符串
*/
private static String genEncryptConfigStr() throws ClientException {
// 上面生成的aes128对象
AliyunGenAes128Vo aes128 = genAes128();
AliyunEncryptConfig encryptConfig = new AliyunEncryptConfig();
encryptConfig.setCipherText(aes128.getCiphertextBlob());
encryptConfig.setKeyServiceType("KMS");
// 自己的服务,等会创建接口
encryptConfig.setDecryptKeyUri("http://test.abc.com/play?Ciphertext=" + aes128.getCiphertextBlob());
String jsonString = JSON.toJSONString(encryptConfig);
log.info("加密信息 {}", jsonString);
return jsonString;
}
这样文件上传完成后就会转码生成加密文件了
9、开通加密播放
10、获取视频信息或凭证
/**
* 获取视频信息 - 播放地址等
* @param videoId 阿里云视频id
*/
public static AliyunPlayInfo getPlayInfo(String videoId) throws Exception {
IAcsClient client = getClient();
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("vod.cn-shenzhen.aliyuncs.com");
request.setSysVersion("2017-03-21");
request.setSysAction("GetPlayInfo");
request.putQueryParameter("VideoId", videoId);
CommonResponse response = client.getCommonResponse(request);
AliyunPlayInfo playInfo = JSON.parseObject(response.getData(), AliyunPlayInfo.class);
JSONObject jsonObject = JSONObject.parseObject(playInfo.getInfoStr());
String listJson = jsonObject.getString("PlayInfo");
playInfo.setPlayInfoList(JSON.parseArray(listJson, AliyunPlayInfo.PlayInfo.class));
return playInfo;
}
11、获取上传凭证 - 用于上传视频
// AliStsResVo 自己封装的对象
public ReturnResult<AliUploadAuthResVo> uploadAuth(@RequestBody AliStsResVo vo) {
// 点播服务所在的Region,接入服务中心为上海,则填cn-shanghai
String regionId = "cn-shenzhen";
IClientProfile profile = DefaultProfile.getProfile(regionId, vo.getKeyId(), vo.getKeySecret(), vo.getToken());
DefaultAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("vod.cn-shenzhen.aliyuncs.com");
request.setSysVersion("2017-03-21");
request.setSysAction("CreateUploadVideo");
request.putQueryParameter("Title", vo.getFileName());
request.putQueryParameter("FileName", vo.getFilePath());
try {
CommonResponse response = client.getCommonResponse(request);
AliUploadAuthResVo uploadAuthResVo = JSON.parseObject(response.getData(), AliUploadAuthResVo.class);
return ReturnResult.success(uploadAuthResVo);
} catch (ClientException e) {
e.printStackTrace();
return ReturnResult.error();
}
}
12、上传凭证有效期为3000秒, 刷新凭证
public ReturnResult<AliUploadAuthResVo> refreshUploadAuth(@RequestBody AliStsResVo vo) {
DefaultProfile profile = DefaultProfile.getProfile("cn-shenzhen", vo.getKeyId(), vo.getKeySecret(), vo.getToken());
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("vod.cn-shenzhen.aliyuncs.com");
request.setSysVersion("2017-03-21");
request.setSysAction("RefreshUploadVideo");
request.putQueryParameter("VideoId", vo.getVideoId());
try {
CommonResponse response = client.getCommonResponse(request);
AliUploadAuthResVo uploadAuthResVo = JSON.parseObject(response.getData(), AliUploadAuthResVo.class);
return ReturnResult.success(uploadAuthResVo);
} catch (Exception e) {
e.printStackTrace();
return ReturnResult.error();
}
}
13、CRMEB阿里云视频加密
设置上传完成回调 - 用于手动转码
14、这样文件上传完成后就会转码生成加密文件了
开通加密播放
15、获取视频凭证
/**
*
* @param videoId 阿里云视频id
* @param timeout 凭证有效期 100-3000 秒
*/
public static AliyunPlayAuth getPlayAuth(String videoId, String timeout) throws Exception {
IAcsClient client = getClient();
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("vod.cn-shenzhen.aliyuncs.com");
request.setSysVersion("2017-03-21");
request.setSysAction("GetVideoPlayAuth");
request.putQueryParameter("VideoId", videoId);
request.putQueryParameter("AuthInfoTimeout", timeout);
CommonResponse response = client.getCommonResponse(request);
return JSON.parseObject(response.getData(), AliyunPlayAuth.class);
}
16、用到的两个对象
@Data
@ApiModel("视频详细信息")
public class AliyunPlayInfo {
@JSONField(name = "VideoBase")
private VideoBase videoBase;
@JSONField(name = "PlayInfoList")
private String infoStr;
private List<PlayInfo> playInfoList;
@Data
public static class VideoBase {
@ApiModelProperty("阿里云视频id")
@JSONField(name = "VideoId")
private String videoId;
@ApiModelProperty("封面地址")
@JSONField(name = "CoverURL")
private String coverURL;
@ApiModelProperty("阿里云视频名")
@JSONField(name = "Title")
private String title;
@ApiModelProperty("视频时长 秒")
@JSONField(name = "Duration")
private String duration;
}
@Data
public static class PlayInfo {
@ApiModelProperty("视频字节")
@JSONField(name = "Size")
private Long size;
@ApiModelProperty("播放地址")
@JSONField(name = "PlayURL")
private String playURL;
@ApiModelProperty("帧率")
@JSONField(name = "Fps")
private String fps;
@ApiModelProperty("高")
@JSONField(name = "Height")
private String height;
@ApiModelProperty("宽")
@JSONField(name = "Width")
private String width;
@ApiModelProperty("FD:流畅。\n" +
"LD:标清。\n" +
"SD:高清。\n" +
"HD:超清\n" +
"OD:原画。\n" +
"2K:2K。\n" +
"4K:4K。\n" +
"SQ:普通音质。\n" +
"HQ:高音质。\n" +
"AUTO:自适应码率。")
@JSONField(name = "Definition")
private String definition;
}
}
@Data
@ApiModel("视频播放凭证")
public class AliyunPlayAuth {
@JSONField(name = "PlayAuth")
@ApiModelProperty("凭证")
private String playAuth;
@JSONField(name = "VideoMeta")
@ApiModelProperty("视频信息")
private AliyunPlayInfo.VideoBase videoMeta;
}
17、此时获取的视频是加密的
可以测试一下
前往阿里在线诊断地址
选择视频播放
将上面获取的视频的地址放到Source中,点击播放。F12查看网络请求, 发现它一直往第四步请求转码中genEncryptConfigStr()方法中设置的setDecryptKeyUri发送请求,所以需要搭建一个解密的接口
解密
@GetMapping("play")
public void play(@RequestParam String Ciphertext, HttpServletResponse response) throws IOException {
//从KMS中解密出来,并Base64 decode
byte[] key = decrypt(Ciphertext);
//设置header
response.setHeader("Access-Control-Allow-Origin", "*");
response.setStatus(200);
response.setContentLength(key.length);
//返回base64decode之后的密钥
response.getOutputStream().write(key);
}
private byte[] decrypt(String ciphertext) {
DecryptRequest request = new DecryptRequest();
request.setCiphertextBlob(ciphertext);
request.setSysProtocol(ProtocolType.HTTPS);
try {
DecryptResponse response = AliyunVideoUtils.getClient().getAcsResponse(request);
String plaintext = response.getPlaintext();
//注意:需要base64 decode
return Base64.decodeBase64(plaintext);
} catch (ClientException e) {
e.printStackTrace();
return null;
}
}
18、这样再次点击播放就能成功播放了
不过这里面我并没有进行安全认证,所以后续需要安全认证需要自己手动添加
设置URL鉴权
19、开启URL鉴权后,在生成视频地址后面就会增加一个auth_key
但是此时在点击视频播放就会出现跨域问题,因此需要在HTTP头这里设置