第四次课:阿里云视频点播
分类: springboot 专栏: 在线教育项目实战 标签: 阿里云视频点播
2023-05-05 20:59:11 1342浏览
视频点播
视频点播(ApsaraVideo for VoD)是集音视频采集、编辑、上传、自动化转码处理、媒体资源管理、分发加速于一体的一站式音视频点播解决方案。
应用场景
- 音视频网站:无论是初创视频服务企业,还是已拥有海量视频资源,可定制化的点播服务帮助客户快速搭建拥有极致观看体验、安全可靠的视频点播应用。
- 短视频:集音视频拍摄、特效编辑、本地转码、高速上传、自动化云端转码、媒体资源管理、分发加速、播放于一体的完整短视频解决方案。目前已帮助1000+APP快速实现手机短视频功能。
- 直播转点播:将直播流同步录制为点播视频,用于回看。并支持媒资管理、媒体处理(转码及内容审核/智能首图等AI处理)、内容制作(云剪辑)、CDN分发加速等一系列操作。
- 在线教育:为在线教育客户提供简单易用、安全可靠的视频点播服务。可通过控制台/API等多种方式上传教学视频,强大的转码能力保证视频可以快速发布,覆盖全网的加速节点保证学生观看的流畅度。防盗链、视频加密等版权保护方案保护教学内容不被窃取。
- 视频生产制作:提供在线可视化剪辑平台及丰富的OpenAPI,帮助客户高效处理、制作视频内容。除基础的剪切拼接、混音、遮标、特效、合成等一系列功能外,依托云剪辑及点播一体化服务还可实现标准化、智能化剪辑生产,大大降低视频制作的槛,缩短制作时间,提升内容生产效率。
- 内容审核:应用于短视频平台、传媒行业审核等场景,帮助客户从从语音、文字、视觉等多维度精准识别视频、封面、标题或评论的违禁内容进行AI智能审核与人工审核。
功能介绍
视频转码:比如普通原画视频可以转成高清,标清等
分发加速:播放的速度更快,尽量少提示正在缓存中
主要用到:上传和管理
开通视频点播云平台
选择视频点播服务
产品->企业应用->视频云->视频点播
开通视频点播
选择使用流量计费
资费说明
https://www.aliyun.com/price/product?spm=a2c4g.11186623.2.12.7fbd59b9vmXVN6#/vod/detail
- 后付费
- 套餐包
- 欠费说明
- 计费案例:https://help.aliyun.com/document_detail/64032.html?spm=a2c4g.11186623.4.3.363db1bcfdvxB5
整体流程
使用视频点播实现音视频上传、存储、处理和播放的整体流程如下:
- 用户获取上传授权。
- VoD下发 上传地址和凭证 及 VideoId。
- 用户上传视频保存视频ID(VideoId)。
- 用户服务端获取播放凭证。
- VoD下发带时效的播放凭证。
- 用户服务端将播放凭证下发给客户端完成视频播放。
视频点播服务的基本使用
完整的参考文档
https://help.aliyun.com/product/29932.html?spm=a2c4g.11186623.6.540.3c356a58OEmVZJ
设置转码模板并加密
选择全局设置 > 转码设置,单击添加转码模板组。
在视频转码模板组页面,根据业务需求选择封装格式和清晰度。
或直接将已有的模板设置为默认即可
可以设置视频加密,这样别人拿到我的播放地址也无法播放
分类管理
选择全局设置 > 分类管理
上传视频文件
选择媒资库 > 音视频,单击上传音视频
配置域名
加密的视频最好是设置一下这个域名
在控制台查看视频
此时视频可以在阿里云控制台播放
获取web播放器代码
java上传视频到阿里云
看着官方的文档操作即可
@ApiOperation(value = "上传视频到阿里云视频点播") @PostMapping public ResultDto uploadVod(MultipartFile vod){ try { String fileName = vod.getOriginalFilename(); String title = fileName.substring(0, fileName.lastIndexOf(".")); UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, vod.getInputStream()); /* 是否使用默认水印(可选),指定模板组ID时,根据模板组配置确定是否使用默认水印*/ //request.setShowWaterMark(true); /* 自定义消息回调设置及上传加速设置(可选), Extend为自定义扩展设置,MessageCallback为消息回调设置,AccelerateConfig为上传加速设置(上传加速功能需要先申请开通后才能使用)*/ //request.setUserData("{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackType\":\"http\",\"CallbackURL\":\"http://example.aliyundoc.com\"},\"AccelerateConfig\":{\"Type\":\"oss\",\"Domain\":\"****Bucket.oss-accelerate.aliyuncs.com\"}}"); /* 视频分类ID(可选) */ //request.setCateId(0); /* 视频标签,多个用逗号分隔(可选) */ //request.setTags("标签1,标签2"); /* 视频描述(可选)*/ //request.setDescription("视频描述"); /* 封面图片(可选)*/ //request.setCoverURL("http://cover.example.com/image_01.jpg"); /* 模板组ID(可选)*/ //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56****"); /* 工作流ID(可选)*/ //request.setWorkflowId("d4430d07361f0*be1339577859b0****"); /* 存储区域(可选)*/ //request.setStorageLocation("in-201703232118266-5sejd****.oss-cn-shanghai.aliyuncs.com"); /* 开启默认上传进度回调 */ // request.setPrintProgress(true); /* 设置自定义上传进度回调(必须继承 VoDProgressListener) */ /*默认关闭。如果开启了这个功能,上传过程中服务端会在日志中返回上传详情。如果不需要接收此消息,需关闭此功能*/ // request.setProgressListener(new PutObjectProgressListener()); /* 设置应用ID*/ //request.setAppId("app-100****"); /* 点播服务接入点 */ //request.setApiRegionId("cn-shanghai"); /* ECS部署区域*/ // request.setEcsRegionId("cn-shanghai"); UploadVideoImpl uploader = new UploadVideoImpl(); UploadStreamResponse response = uploader.uploadStream(request); System.out.print("RequestId=" + response.getRequestId() + "\n"); //请求视频点播服务的请求ID if (response.isSuccess()) { System.out.print("VideoId=" + response.getVideoId() + "\n"); } else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 System.out.print("VideoId=" + response.getVideoId() + "\n"); System.out.print("ErrorCode=" + response.getCode() + "\n"); System.out.print("ErrorMessage=" + response.getMessage() + "\n"); throw new JfException(Integer.valueOf(response.getCode()),response.getMessage()); } return ResultDto.success("上传成功",response.getVideoId()); } catch (IOException e) { e.printStackTrace(); return ResultDto.error("上传失败"); } }
设置文件上传大小的限制
spring.servlet.multipart.maxFileSize=10MB spring.servlet.multipart.maxRequestSize=10MB
java获取视频播放地址
备注:根据视频id获取到
对于不加密的视频来说,只要拿到播放地址就可以直接播放。但对于加密的视频来说,拿到播放地址也无法播放。
java获取播放凭证(重要)
备注:根据视频id获取到
对于加密视频的播放,只能用这个凭证的方式
java删除视频
删除的时候可以批量删除多个
视频播放测试
分两种:根据地址播放和根据凭证播放
- 根据地址播放
var player = new Aliplayer({ id: 'J_prismPlayer', source: '<your play URL>',//播放地址,可以是第三方点播地址,或阿里云点播服务中的播放地址。 },function(player){ console.log('The player is created.') });
- 根据凭证播放
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title>点播私有加密播放测试用例</title> <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.9.19/skins/default/aliplayer-min.css" /> <script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.9.19/aliplayer-min.js"></script> </head> <body> <div class="prism-player" id="J_prismPlayer"></div> <script> var player = new Aliplayer({ id: 'J_prismPlayer', width: '100%', vid : '<your video ID>',//必选参数。可以通过点播控制台(路径:媒资库>音/视频)查询。示例:1e067a2831b641db90d570b6480f****。 playauth : '<your PlayAuth>',//必选参数。参数值可通过调用GetVideoPlayAuth接口获取。 encryptType: 1, //当播放私有加密流时需要设置本参数值为1。其它情况无需设置。 playConfig:{EncryptType:'AliyunVoDEncryption'}, //当您输出的M3U8流中,含有其他非私有加密流时,需要指定此参数。 },function(player){ console.log('The player is created.') }); </script> </body> </html>
以上写法都是html里的写法,下面是vue的写法
参考文章:
https://developer.aliyun.com/article/646391
整理如下:
播放器组件vue代码
<template> <div class="prism-player" :id="playerId" :style="playStyle"></div> </template> <script> export default { name: "Aliplayer", props: { //媒体转码服务的媒体Id。 vid: { type: String, default: "" }, //播放权证 playauth: { type: String, default: "" }, //容器的大小 height: { type: String, default: "460px" }, //容器的大小 width: { type: String, default: "100%" }, //视频的高度大小 videoWidth: { type: String, default: "100%" }, //视频的宽度大小 videoHeight: { type: String, default: "100%" }, //播放器自动加载,目前仅h5可用 preload: { type: Boolean, default: false }, //播放器默认封面图片,请填写正确的图片url地址。需要autoplay为’false’时,才生效 cover: { type: String, default: "" }, //播放内容是否为直播,直播时会禁止用户拖动进度条。 isLive: { type: Boolean, default: false }, //播放器是否自动播放,在移动端autoplay属性会失效。 autoplay: { type: Boolean, default: false }, //播放器自动循环播放。 rePlay: { type: Boolean, default: false }, //指定使用H5播放器。 useH5Prism: { type: Boolean, default: false }, //H5是否内置播放,有的Android浏览器不起作用。 playsinline: { type: Boolean, default: false }, //默认为‘hover’。可选的值为:‘click’、‘hover’、‘always’。 controlBarVisibility: { type: String, default: "hover" }, /*** * *指定播放地址格式,只有使用vid的播放方式时支持 可选值为’mp4’、’m3u8’、’flv’、’mp3’,默认为空,仅H5支持。 * */ format: { type: String, default: "m3u8" }, /*** * * 指定返回音频还是视频,只有使用vid的播放方式时支持。 可选值为’video’和’audio’,默认为’video’ ‘audio’主要是针对只包含音频的视频格式,比如音频的mp4,仅H5支持。 * */ mediaType: { type: String, default: "video" }, /*** * 指定排序方式,只有使用vid + plauth播放方式时支持。 ‘desc’表示按倒序排序(即:从大到小排序) ‘asc’表示按正序排序(即:从小到大排序) 默认值:‘asc’,仅H5支持。 * */ qualitySort: { type: String, default: "asc" }, /** * 加密类型,播放点播私有加密视频时,设置值为1,默认值为0。 * */ encryptType: { type: Number, default: 1 }, playStyle: { type: String, default: "" }, aliplayerSdkPath: { // Aliplayer 代码的路径 type: String, default: "https://g.alicdn.com/de/prismplayer/2.9.3/aliplayer-min.js" }, }, data() { return { playerId: "aliplayer_" + Math.random().toString(36).substr(2), scriptTagStatus: 0, isReload: false, instance: null }; }, created() { if (window.Aliplayer !== undefined) { // 如果全局对象存在,说明编辑器代码已经初始化完成,直接加载编辑器 this.scriptTagStatus = 2; this.initAliplayer(); } else { // 如果全局对象不存在,说明编辑器代码还没有加载完成,需要加载编辑器代码 this.insertScriptTag(); } }, mounted() { if (window.Aliplayer !== undefined) { // 如果全局对象存在,说明编辑器代码已经初始化完成,直接加载编辑器 this.scriptTagStatus = 2; this.initAliplayer(); } else { // 如果全局对象不存在,说明编辑器代码还没有加载完成,需要加载编辑器代码 this.insertScriptTag(); } }, methods: { insertScriptTag() { const _this = this; let playerScriptTag = document.getElementById("playerScriptTag"); // 如果这个tag不存在,则生成相关代码tag以加载代码 if (playerScriptTag === null) { playerScriptTag = document.createElement("script"); playerScriptTag.type = "text/javascript"; playerScriptTag.src = this.aliplayerSdkPath; playerScriptTag.id = "playerScriptTag"; let s = document.getElementsByTagName("head")[0]; s.appendChild(playerScriptTag); } if (playerScriptTag.loaded) { _this.scriptTagStatus++; } else { playerScriptTag.addEventListener("load", () => { _this.scriptTagStatus++; playerScriptTag.loaded = true; _this.initAliplayer(); }); } _this.initAliplayer(); }, initAliplayer() { const _this = this; // scriptTagStatus 为 2 的时候,说明两个必需引入的 js 文件都已经被引入,且加载完成 if ( _this.scriptTagStatus === 2 && (_this.instance === null || _this.reloadPlayer) ) { _this.instance && _this.instance.dispose(); // document.querySelector("#" +_this.playerId).innerHTML = ""; // Vue 异步执行 DOM 更新,这样一来代码执行到这里的时候可能 template 里面的 script 标签还没真正创建 // 所以,我们只能在 nextTick 里面初始化 Aliplayer _this.$nextTick(() => { _this.instance = window.Aliplayer({ id: _this.playerId, qualitySort:_this.qualitySort, format:_this.format, mediaType:_this.mediaType, vid: _this.vid, playauth: _this.playauth, width: _this.width, height: _this.height, videoWidth: _this.videoWidth, videoHeight: _this.videoHeight, preload: _this.preload, playsinline:_this.playsinline, isLive: _this.isLive, rePlay: _this.rePlay, autoplay: _this.autoplay, useH5Prism: _this.useH5Prism, controlBarVisibility: _this.controlBarVisibility, encryptType: _this.encryptType, }); // 绑定事件,当 AliPlayer 初始化完成后,将编辑器实例通过自定义的 ready 事件交出去 _this.instance.on("ready", () => { this.$emit("ready", _this.instance); }); _this.instance.on("play", () => { this.$emit("play", _this.instance); }); _this.instance.on("pause", () => { this.$emit("pause", _this.instance); }); _this.instance.on("ended", () => { this.$emit("ended", _this.instance); }); _this.instance.on("liveStreamStop", () => { this.$emit("liveStreamStop", _this.instance); }); _this.instance.on("m3u8Retry", () => { this.$emit("m3u8Retry", _this.instance); }); _this.instance.on("hideBar", () => { this.$emit("hideBar", _this.instance); }); _this.instance.on("waiting", () => { this.$emit("waiting", _this.instance); }); _this.instance.on("snapshoted", () => { this.$emit("snapshoted", _this.instance); }); _this.instance.on("timeupdate", () => { this.$emit("timeupdate", _this.instance); }); _this.instance.on("requestFullScreen", () => { this.$emit("requestFullScreen", _this.instance); }); _this.instance.on("cancelFullScreen", () => { this.$emit("cancelFullScreen", _this.instance); }); _this.instance.on("error", () => { this.$emit("error", _this.instance); }); }); } }, /** * 播放视频 */ play: function () { this.instance.play(); }, /** * 暂停视频 */ pause: function () { this.instance.pause(); }, /** * 重播视频 */ replay: function () { this.instance.replay(); }, /** * 跳转到某个时刻进行播放 * @argument time 的单位为秒 */ seek: function (time) { this.instance.seek(time); }, /** * 获取当前时间 单位秒 */ getCurrentTime: function () { return this.instance.getCurrentTime(); }, /** *获取视频总时长,返回的单位为秒 * @returns 返回的单位为秒 */ getDuration: function () { return this.instance.getDuration(); }, /** 获取当前的音量,返回值为0-1的实数ios和部分android会失效 */ getVolume: function () { return this.instance.getVolume(); }, /** 设置音量,vol为0-1的实数,ios和部分android会失效 */ setVolume: function (vol) { this.instance.setVolume(vol); }, /** *直接播放视频url,time为可选值(单位秒)目前只支持同种格式(mp4/flv/m3u8)之间切换暂不支持直播rtmp流切换 *@argument url 视频地址 *@argument time 跳转到多少秒 */ loadByUrl: function (url, time) { this.instance.loadByUrl(url, time); }, /** * 设置播放速度 *@argument speed 速度 */ setSpeed: function (speed) { this.instance.setSpeed(speed); }, /** * 设置播放器大小w,h可分别为400px像素或60%百分比chrome浏览器下flash播放器分别不能小于397x297 *@argument w 播放器宽度 *@argument h 播放器高度 */ setPlayerSize: function (w, h) { this.instance.setPlayerSize(w, h); }, /** *目前只支持H5播放器。 暂不支持不同格式视频间的之间切换。 暂不支持直播rtmp流切换。 */ replayByVidAndPlayAuth: function (vid, accId, accSecret, stsToken, authInfo, domainRegion) { this.instance.replayByVidAndPlayAuth(vid, accId, accSecret, stsToken, authInfo, domainRegion); }, /*** * 重新设置vid和权限,目前只支持H5播放器。 暂不支持不同格式视频间的之间切换。 暂不支持直播rtmp流切换。 * @param vid 视频ID * @param playauth 播放权限 */ replayByVidAndAuthInfo: function (vid, playauth) { this.instance.replayByVidAndAuthInfo(vid, playauth); }, /** * 目前只支持HTML5界面上的重载功能,暂不支持直播rtmp流切换m3u8)之间切换,暂不支持直播rtmp流切换 *@argument vid 视频id *@argument playauth 播放凭证 */ reloaduserPlayInfoAndVidRequestMts: function (vid, playauth) { this.instance.reloaduserPlayInfoAndVidRequestMts(vid, playauth); }, /*** *设置截图参数 * @param width 宽度 * @param height 高度 * @param rate 截图质量 */ setSanpshotProperties: function (width, height, rate) { this.instance.setSanpshotProperties(width, height, rate); }, /** * 设置封面地址 * @param cover 封面地址 */ setCover: function (cover) { this.instance.setCover(cover); }, reloadPlayer: function () { this.isReload = true; this.initAliplayer(); this.isReload = false; } } }; </script> <style> @import url(https://g.alicdn.com/de/prismplayer/2.9.3/skins/default/aliplayer-min.css); </style>
特别注意:
在线播放视频的vue代码
<template> <div class="app-container"> <el-button type="" @click="seeVideo('e4113840ee0e71ed804f0764a0fd0102')">查看第一个视频</el-button> <el-button type="" @click="seeVideo('34ae63b0ee0371ed80380675b3ed0102')">查看第二个视频</el-button> <!--阿里云播放器--> <el-dialog class="video" @close="colseVideo()" :visible.sync="playShow" > <ali-player v-if="playAuth" :vid="vid" :playauth="playAuth" qualitySort="asc" format="m3u8" mediaType="video" :encryptType=1 ref="player" :autoplay=false :isLive=false :rePlay=false :preload=true controlBarVisibility="hover" :useH5Prism=true > </ali-player> </el-dialog> </div> </template> <script> import { getAuth } from '@/api/vod' import VueAliplayer from '@/components/AliPlayer' export default { components: { "ali-player": VueAliplayer }, data() { return { playShow: false, vid: '', //视频vid playAuth: '', //鉴权地址 }; }, methods: { colseVideo(){ // //重新子组件初始化 this.$refs.player.initAliplayer() }, seeVideo(vid) { var that = this that.vid='' that.playAuth='' //根据vid去查凭证 getAuth(vid).then(res => { that.vid = vid that.playAuth = res.data that.playShow = true }) }, } } </script> <style > .video .el-dialog__header { padding: 0; } .video .el-dialog__body { padding: 0; } </style>
遇到的坑:明明已经获取到了凭证但就是无法播放!!!
原因是:子组件里面需要用到父组件传过来的播放凭证 ,而我们父组件的凭证是发送ajax请求到后台拿到的,还没等到父组件拿到这个凭证的时候,子组件就已经加载了,导致始终播放不了。
解决思路:让子组件延迟加载。
最终的demo效果如下
删除课程
如果用户确定删除,则首先删除视频,小节,章节,描述,课程
可以考虑加个事务
好博客就要一起分享哦!分享海报
此处可发布评论
评论(2)展开评论