1、视频播放
- mixin混入 采用sts方式播放
-
accessKeyId
accessKeySecret
securityToken
region
均为后端crypto加密配置,进行解密 - skinLayout为皮肤配置栏,可删除对应组件,使用自定义组件components
- 更多配置可查看阿里云播放器SDK--web播放器--属性和接口说明
1-1、main.js
//main.js
Vue.mixin({
methods: {
//创建视频
$createPlayer(id, key, vid, picUrl) {
key.accessKeyId = decrypt(key.accessKeyId)
key.accessKeySecret = decrypt(key.accessKeySecret)
key.securityToken = decrypt(key.securityToken)
key.region = decrypt(key.region)
return new Aliplayer({
id,
autoplay: false,
width: "100%",
//支持播放地址播放,此播放优先级最高
// source,
//播放方式四:使用STS方式播放
vid,
region: key.region,
controlBarVisibility: "always",
// vid: '10c0875db475494b891a8fc7f9b259d2',
accessKeyId: key.accessKeyId,
accessKeySecret: key.accessKeySecret,
securityToken: key.securityToken,
isLive: false,
defaultDefinition: 'LD',
cover: picUrl,
controlBarVisibility: 'always',
components: [{
name: 'RateComponent',
type: AliPlayerComponent.RateComponent,
}, ],
// https://help.aliyun.com/document_detail/62948.html#-
skinLayout: [{
name: 'bigPlayButton',
align: 'blabs',
x: 328,
y: '50%'
},
{
name: 'H5Loading',
align: 'cc',
},
{
name: 'errorDisplay',
align: 'tlabs',
x: 0,
y: 0
},
{
name: 'infoDisplay'
},
{
name: 'tooltip',
align: 'blabs',
x: 0,
y: 56
}, // 悬浮在按钮上的提示
{
name: 'thumbnail'
},
{
name: 'controlBar',
align: 'blabs',
x: 0,
y: 0, // 控制视频的控件
children: [{
name: 'progress',
align: 'blabs',
x: 0,
y: 44
}, // 进度
{
name: 'playButton',
align: 'tl',
x: 15,
y: 12
}, // 播放按钮
{
name: 'timeDisplay',
align: 'tl',
x: 10,
y: 7
}, // 时间线
// {
// name: 'fullScreenButton',
// align: 'tr',
// x: 10,
// y: 12
// }, // 全屏按钮按钮
// {name:"subtitle", align:"tr",x:5, y:12}, // 字幕
// {name:"setting", align:"tr",x:15, y:12}, // 设置
{
name: 'volume',
align: 'tr',
x: 5,
y: 10
}, // 音量
// {name: "snapshot", align: "tr", x: 5, y: 12 }
],
},
],
// components: [{
// name: 'ProgressComponent',
// type: ProgressComponent
// }, ]
}, )
},
}
})
1-2、相关页面播放(进度条不是很流畅,后期手写进度条videoProgress.js)
//相关页面播放
if (this.player) {
this.player.dispose() //销毁
this.player = null
}
let list =this.videoList[this.videoIndex]
this.videoKey = storage.get('videosts')
this.player = this.$createPlayer('my_video', this.videoKey, list.videoId, list.picUrl)
this.player.on('ended', (e) => {
if (item) item.canClick = true
})
let progressPlaied = document.querySelector('.prism-progress-played')
let currentText = document.querySelector('.prism-time-display .current-time')
//快进快退10s
document.onkeydown = (e) => {
let videotimes = this.player.getDuration() //视频时长
let playnum = Math.ceil(this.player.getCurrentTime()) //视频当前时间,单位:s
if (e && e.keyCode === 37) {
// 按 向左键
playnum = parseInt(playnum - 10)
if (playnum >= 0) {
this.player.seek(playnum)
progressPlaied.style.width = `${((playnum / videotimes) * 100).toFixed(6)}%`
} else {
this.player.seek(0)
progressPlaied.style.width = 0
currentText.innerText = '00:00'
}
} else if (e && e.keyCode === 39) {
// 按 向右键
playnum = parseInt(playnum + 10)
if (playnum <= videotimes) {
this.player.seek(playnum)
progressPlaied.style.width = `${((playnum / videotimes) * 100).toFixed(6)}%`
} else {
this.player.seek(Math.ceil(videotimes))
progressPlaied.style.width = `100%`
}
}
}
2、富文本编辑器上传视频 (未完)
2-1、扩展视频按钮
// html
<input
type='file'
style='display: none;'
id='getVideoFile'
@change="selectVideoSource($event)"
multiple
accept='video/*'
>
// js 初始化编辑器中
// 扩展视频按钮
class InsertVideoMenu extends BtnMenu {
constructor(editor) {
const $elem = E.$(`<div class="w-e-menu" data-title="插入视频">
<i class="iconfont"></i>
</div>`);
super($elem, editor);
}
// 菜单点击事件
clickHandler() {
var aPlayers = self.$refs.wangEditorContainer.getElementsByClassName('aliyun-video-player');
if(aPlayers.length >= 10){
self.$message.error('最多可添加10个视频')
}else{
document.getElementById('getVideoFile').click()
}
}
tryChangeActive() {
}
}
3、上传视频
3-1、需求
- 后台管理系统上传视频(可多个),上传时显示进度,上传完成显示视频标题。hover时可以选择删除
初始状态
视频上传中
上传成功
3-2、代码
html
<el-form-item class="video-form-item" label="视频文件:">
<div ref="videoBox" id="video-box">
<!-- 添加的视频 -->
<div class="item flex-box" v-for="(item, idx) in videoList" :key="idx">
<div class="aliyun-video-player">
<div v-if="item.progress == 100 || item.progress > 100">
<i class="el-icon-video-play"></i>
<div class="video-name">{{ item.videoName }}</div>
<div class="edit-player-tip">此处不支持视频播放</div>
<div class="edit-player-masker"></div>
<div class="aliyun-video-close-btn" @click="deleteVideo(item, idx)">
<span class="iconfont iconguanbi4"></span>
</div>
</div>
<div class="aliyun-video-progress-box" v-else>
<div class="current">{{ item.progress }}%</div>
<div class="aliyun-video-progress-total"><div class="aliyun-video-progress-current" :style="{ width: item.progress + '%' }"></div></div>
</div>
</div>
</div>
<!-- 视频上传 (input file的样式修改麻烦 uploadClick用于点击这个隐藏的input)-->
<div class="upload-div" @click="uploadClick">
<i class="el-icon-plus"></i>
<p>点击上传视频</p>
</div>
<input type="file" style="display: none" id="getVideoFile" multiple accept="video/*" @change="selectVideoSource($event)" />
</div>
</el-form-item>
js
/*
* 上传SDK 详见官网 https://help.aliyun.com/document_detail/52204.html 视频信息,进度等均可以在回调中拿到
* paramData -- 可以携带自己想要的信息 title:"标题",CateId:"分类ID",
* videoMap:判断所有上传是否结束的对象 { uid:boolean }
*/
// mounted 中根据正式环境的不同选择不同的分类
mounted() {
this.CateId = window.location.host == '正式环境host' ? '2057' : '2056'
},
// 上传视频
selectVideoSource(e, insertVideoFn) {
var file = e.target.files
if (file.length > 0) {
var large = file.length
this.setJavascriptUpload(file, large)
e.target.value = ''
}
},
setJavascriptUpload(file, large) {
// 初始化上传
this.toAliyunUpload()
// 添加文件
for (let i = 0; i < large; i++) {
if (file[i].type.indexOf('video') < 0 && file[i].type.indexOf('flash') < 0) {
this.$message.error('有一个文件格式不对')
continue
}
// 视频文件过大
if (file[i].size / 1024 / 1024 > 1 * 1024) {
this.$message.error('有一个文件过大')
continue
}
var uid = Math.random().toString().slice(2)
var paramsData = {
Vod: {
Title: file[i].name,
CateId: this.CateId, // 分类id
uid: uid,
TemplateGroupId: 'c9f0925ae6b5386c8681729d19985f47', // 指定转码模板组
},
}
this.videoMap[uid] = false
this.uploader.addFile(file[i], '', '', '', JSON.stringify(paramsData))
let obj = {
uid,
progress: 0,
videoName: '',
}
this.videoList.push(obj)
}
this.uploader.startUpload()
},
toAliyunUpload() {
var self = this
this.uploader = new AliyunUpload.Vod({
userId: '245578911051344621',
region: 'cn-shenzhen',
//分片大小默认1 MB,不能小于100 KB
partSize: 1048576,
//并行上传分片个数,默认5
parallel: 10,
//网络原因失败时,重新上传次数,默认为3
retryCount: 3,
//网络原因失败时,重新上传间隔时间,默认为2秒
retryDuration: 2,
//是否上报上传日志到视频点播,默认为true
enableUploadProgress: true,
//开始上传
onUploadstarted: function (uploadInfo) {
//获取STSToken
self.$api
.getVideoStsToken()
.then((res) => {
if (res.data) {
if (res.data.code == 200 && res.data.data) {
var data = res.data.data
self.sts = {
accessKeyId: decrypt(data.accessKeyId, ''),
accessKeySecret: decrypt(data.accessKeySecret, ''),
secretToken: decrypt(data.securityToken, ''),
}
self.uploader.setSTSToken(uploadInfo, self.sts.accessKeyId, self.sts.accessKeySecret, self.sts.secretToken)
} else {
var uid = uploadInfo.videoInfo.uid
self.videoMap[uid] = true
self.videoList.forEach((item, idx) => {
if (item.uid == uid) {
self.videoList.splice(idx, 1)
}
})
self.$message.error(res.data.msg || '获取STSToken失败')
}
} else {
var uid = uploadInfo.videoInfo.uid
self.videoMap[uid] = true
self.videoList.forEach((item, idx) => {
if (item.uid == uid) {
self.videoList.splice(idx, 1)
}
})
self.$message.error('一个视频上传失败')
}
})
.catch((err) => {
console.log(err)
var uid = uploadInfo.videoInfo.uid
self.videoMap[uid] = true
self.videoList.forEach((item, idx) => {
if (item.uid == uid) {
self.videoList.splice(idx, 1)
}
})
self.$message.error(JSON.stringify(err) || '获取STSToken失败')
})
},
//文件上传成功
onUploadSucceed: function (uploadInfo) {
var uid = uploadInfo.videoInfo.uid
self.videoMap[uid] = true
self.videoList.forEach((item) => {
if (item.uid == uid) {
item['videoId'] = uploadInfo.videoId
item.videoName = uploadInfo.file.name
}
})
self.$message.success('您有一个视频已上传完成')
},
//文件上传失败
onUploadFailed: function (uploadInfo, code, message) {
self.$message.error('一个视频上传失败')
var uid = uploadInfo.videoInfo.uid
self.videoList.forEach((item, idx) => {
if (item.uid == uid) {
self.videoList.splice(idx, 1)
}
})
},
//文件上传进度,单位:字节
onUploadProgress: function (uploadInfo, totalSize, loadedPercent) {
var uid = uploadInfo.videoInfo.uid
self.videoList.forEach((item) => {
if (item.uid == uid) {
item.progress = Math.ceil(loadedPercent * 100)
}
})
},
//STS token超时
onUploadTokenExpired: function (uploadInfo) {
//重新获取STS token,恢复上传
self.$axios
.get('/kd-group/medio/stsToken')
.then((res) => {
if (res && res.data.code == 200 && res.data.data) {
var data = res.data.data
self.sts = {
accessKeyId: decrypt(data.accessKeyId, ''),
accessKeySecret: decrypt(data.accessKeySecret, ''),
secretToken: decrypt(data.securityToken, ''),
}
self.uploader.setSTSToken(uploadInfo, self.sts.accessKeyId, self.sts.accessKeySecret, self.sts.secretToken)
} else {
self.$message.error(res.data.msg || '获取STSToken失败')
}
})
.catch((err) => {
self.$message.error(JSON.stringify(err) || '获取STSToken失败')
})
},
//全部文件上传结束
onUploadEnd: function (uploadInfo) {
// console.log("onUploadEnd: uploaded all the files");
},
})
},
showVideoLoading() {
var flag = true
for (var key in this.videoMap) {
if (!this.videoMap[key]) {
flag = false
return
}
}
return flag
},
3-3、关于官网的配置
-
入口
注册开通
视频点播入口
模块 -
分类管理 所谓CateId (区分生产环境和测试环境视频存放的位置)
分类管理 1.png
分类管理 2.png -
转码模板组 (格式、清晰度等)
转码模板组 -
回调设置
回调设置.png