1、視頻播放
- mixin混入 采用sts方式播放
-
accessKeyIdaccessKeySecretsecurityTokenregion均為后端crypto加密配置,進行解密 - skinLayout為皮膚配置欄,可刪除對應(yīng)組件,使用自定義組件components
- 更多配置可查看阿里云播放器SDK--web播放器--屬性和接口說明
1-1、main.js
//main.js
Vue.mixin({
methods: {
//創(chuàng)建視頻
$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%",
//支持播放地址播放,此播放優(yōu)先級最高
// 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}, // 設(shè)置
{
name: 'volume',
align: 'tr',
x: 5,
y: 10
}, // 音量
// {name: "snapshot", align: "tr", x: 5, y: 12 }
],
},
],
// components: [{
// name: 'ProgressComponent',
// type: ProgressComponent
// }, ]
}, )
},
}
})
1-2、相關(guān)頁面播放(進度條不是很流暢,后期手寫進度條videoProgress.js)
//相關(guān)頁面播放
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、需求
- 后臺管理系統(tǒng)上傳視頻(可多個),上傳時顯示進度,上傳完成顯示視頻標題。hover時可以選擇刪除

初始狀態(tài)

視頻上傳中

上傳成功
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 詳見官網(wǎng) https://help.aliyun.com/document_detail/52204.html 視頻信息,進度等均可以在回調(diào)中拿到
* paramData -- 可以攜帶自己想要的信息 title:"標題",CateId:"分類ID",
* videoMap:判斷所有上傳是否結(jié)束的對象 { uid:boolean }
*/
// mounted 中根據(jù)正式環(huán)境的不同選擇不同的分類
mounted() {
this.CateId = window.location.host == '正式環(huán)境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', // 指定轉(zhuǎn)碼模板組
},
}
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,
//并行上傳分片個數(shù),默認5
parallel: 10,
//網(wǎng)絡(luò)原因失敗時,重新上傳次數(shù),默認為3
retryCount: 3,
//網(wǎng)絡(luò)原因失敗時,重新上傳間隔時間,默認為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)
}
})
},
//文件上傳進度,單位:字節(jié)
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,恢復(fù)上傳
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失敗')
})
},
//全部文件上傳結(jié)束
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、關(guān)于官網(wǎng)的配置
-
入口
注冊開通
視頻點播入口
模塊 -
分類管理 所謂CateId (區(qū)分生產(chǎn)環(huán)境和測試環(huán)境視頻存放的位置)
分類管理 1.png
分類管理 2.png -
轉(zhuǎn)碼模板組 (格式、清晰度等)
轉(zhuǎn)碼模板組 -
回調(diào)設(shè)置
回調(diào)設(shè)置.png






