1.开通视频点播
- 开通服务
- 点击立即开通
- 找到存储管理
- 启用存储地址
- 视频加密要设置转码并将其设置为默认
- 修改模板-点击编辑
- 上传视频测试
此时已经有了默认存储地址和默认转码 - 配置域名加速【域名已备案】
输入域名点击提交即可 - 配置DNS
点击眼睛并复制CNAME,前往DNS,添加记录
稍等一会域名管理就会显示已配置 - 此时上传视频成功后视频是无法预览的,需要配置HTTPS
前往SSL证书服务
选择免费证书即可
选择20,点击立即购买即可,我这边是已经买过了
点击创建证书
填写刚刚的加速域名、联系人后点击下一步(这一步就不放图了)等待1-15分钟就会审核通过 - 再次前往视频点播
点击配置
选择云盾就会有刚刚审核通过的证书,选择后点击确定即可,稍等一会即可
之后再次预览视频发现可以预览了
Java配置
- 创建RAM用户
填完信息选择api调用即可 - 分配权限
- 创建RAM角色
创建好后给它添加权限 AliyunVODFullAccess (和RAM用户一样的操作)
代码
- Maven依赖
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.4.6</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-vod</artifactId><version>2.15.8</version></dependency><!--还差个OSS的依赖,找不到了~~~-->
- 后台获取sts token
// 只有RAM用户(子账号)才能调用 AssumeRole 接口// 阿里云主账号的AccessKeys不能用于发起AssumeRole请求// 请首先在RAM控制台创建一个RAM用户,并为这个用户创建AccessKeysString accessKeyId = "accessKeyId ";String accessKeySecret = "accessKeySecret ";// AssumeRole API 请求参数: RoleArn, RoleSessionName, Policy, and DurationSeconds// RoleArn 需要在 RAM 控制台上获取String roleArn = "roleArn ";// RoleSessionName 是临时Token的会话名称,自己指定用于标识你的用户,主要用于审计,或者用于区分Token颁发给谁// 但是注意RoleSessionName的长度和规则,不要有空格,只能有'-' '_' 字母和数字等字符// 具体规则请参考API文档中的格式要求// 自定义即可String roleSessionName = "session-name";// 定制你的policyString policy = "{\n" +" \"Version\": \"1\",\n" +" \"Statement\": [\n" +" {\n" +" \"Action\": \"vod:*\",\n" +" \"Resource\": \"*\",\n" +" \"Effect\": \"Allow\"\n" +" }\n" +" ]\n" +"}";try {AssumeRoleResponse response = assumeRole(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy);// 过期时间response.getCredentials().getExpiration());// access key idresponse.getCredentials().getAccessKeyId();// access key secretresponse.getCredentials().getAccessKeySecret();// sts tokenresponse.getCredentials().getSecurityToken();} catch (ClientException | ParseException e) {e.printStackTrace();}
static AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName, String policy) throws ClientException {//构造default profile(参数留空,无需添加Region ID)/*说明:当设置SysEndpoint为sts.aliyuncs.com时,regionId可填可不填;反之,regionId必填,根据使用的服务区域填写,例如:cn-shanghai详情参考STS各地域的Endpoint,请参见接入地址。*/IClientProfile profile = DefaultProfile.getProfile("cn-shenzhen", accessKeyId, accessKeySecret);//用profile构造clientDefaultAcsClient client = new DefaultAcsClient(profile);// 创建一个 AssumeRoleRequest 并设置请求参数final AssumeRoleRequest request = new AssumeRoleRequest();request.setSysEndpoint("sts.aliyuncs.com");request.setSysMethod(MethodType.POST);request.setRoleArn(roleArn);request.setRoleSessionName(roleSessionName);request.setPolicy(policy);// 发起请求,并得到responsereturn client.getAcsResponse(request);}
- 获取上传凭证 - 用于上传视频
// AliStsResVo 自己封装的对象
public ReturnResult<AliUploadAuthResVo> uploadAuth(@RequestBody AliStsResVo vo) {// 点播服务所在的Region,接入服务中心为上海,则填cn-shanghaiString 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();}}
- 上传凭证有效期为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();}}
2.有关视频加密
目录文档
1.准备工作
- 开通KMS服务
在目录文档里即可找到 - 提交工单(只能提交工单让服务人员帮你创建,无法自己创建!)
2.创建转码模板
将不转码设为默认的原因是自动触发转码不支持HLS标准加密,所以需要先上传不转码,然后根据回调再去调用转码接口,实现手动转码
- 先将不转码模板设为默认模板
- 创建转码模板
3.设置上传完成回调 - 用于手动转码
4.创建回调接口
可以用frp搭一个,然后就是正常的restful接口
回调是POST请求,然后请求体我是用 @RequestBody String body接收的,不知道为什么,用对象接收就是不行
- 请求转码需要用到KMS加密,因此需要准备文档中准备工作的第三步搭建密钥管理服务生成AES_128密钥
// 示例代码 // 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);
- 请求转码
这样文件上传完成后就会转码生成加密文件了/*** 提交转码请求*/ 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; }
5.开通加密播放
6.获取视频信息或凭证
- 视频信息
/*** 获取视频信息 - 播放地址等* @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;}
- 获取视频凭证
/**** @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);}
- 用到的两个对象
@Data
@ApiModel("视频详细信息")
public class AliyunPlayInfo {@JSONField(name = "VideoBase")private VideoBase videoBase;@JSONField(name = "PlayInfoList")private String infoStr;private List<PlayInfo> playInfoList;@Datapublic 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;}@Datapublic 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;
}
此时获取的视频是加密的
可以测试一下
前往阿里在线诊断地址
选择视频播放
将上面获取的视频的地址放到Source中,点击播放。F12查看网络请求, 发现它一直往第四步请求转码中genEncryptConfigStr()方法中设置的setDecryptKeyUri发送请求,所以需要搭建一个解密的接口
7.解密
@GetMapping("play")public void play(@RequestParam String Ciphertext, HttpServletResponse response) throws IOException {//从KMS中解密出来,并Base64 decodebyte[] key = decrypt(Ciphertext);//设置headerresponse.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 decodereturn Base64.decodeBase64(plaintext);} catch (ClientException e) {e.printStackTrace();return null;}}
这样再次点击播放就能成功播放了
不过这里面我并没有进行安全认证,所以后续需要安全认证需要自己手动添加
3.后记:URL鉴权
开启URL鉴权后,在生成视频地址后面就会增加一个auth_key
但是此时在点击视频播放就会出现跨域问题,因此需要在
取值是根据自身情况进行设置