阿里播放器Aliplayer遇到的所有坑
1,关于阿里播放器使用过的几种播放方式
url (source)
① 要在创建播放器前要拿到资源否则会报错
② 在有不同清晰度的资源时 直接调用 player.loadByUrl() 方法会报错 官网给出的例子:JSON.stringify({ 'FD': videoUrl.Fd, 'SD': videoUrl.Sd }) (首次可以播,但在切换时资源路径会出错,官网的demo只有单个视频,无法测试切换)
解决方法是 直接抛弃 player.loadByUrl() ,每次销毁播放器,然后重新创建。
vid+playauth:
这种方式清晰度不需要自己设置,但坑比较多。在F5刷新后视频组件会丢失,只剩下封面,并且此类型必须额外写入一些配置,指定清晰度等等。
这种方式切换视频源不用player.loadByUrl() ,要用 player.replayByVidAndPlayAuth(this.vid, this.playauth) 方法
2,需注意这几种事件的坑,在记录上报,播放时常要在 播放中playing 而不是 播放play 中执行,播放完毕后顺序播放可以用自带组件,这里是自己实现,但是有个bug是 ended播放完毕回调中 事件会执行两次!这里是设置了个开关来限制的。
3,配置中有个 skinLayout 可以设置一些播放组件,其中 setting 里自带倍速,字幕,音轨,清晰度,但是字幕和音轨这里用不到,还没法去掉。但是注释了setting又会导致 倍速和清晰度不见了。
这里官方提供了 components组件
<template>
<!-- 容器 -->
<div class="container">
<!-- 音频播放器 -->
<transition name="el-zoom-in-top">
<div v-show="isShowPlayer" class="audioWrapper">
<div class="header">
<div class="title">正在播放 {{playingAudioName}}</div>
<img class="close" src="@/assets/image/close.png" alt="关闭播放器" @click="closePlayer">
</div>
<div class="audio-box" v-loading="playerLoading">
<img :src="play?pauseIcon:playIcon" alt="播放暂停" @click="playHandle()">
<div class="audio-progress">
<el-slider v-model="sliderVal" :format-tooltip="formatTooltip" :min="sliderMin" :max="sliderMax" @change="sliderChange"></el-slider>
<div id="aliPlayer"></div>
<div class="audio-info">
<div>
<span class="current-time">{{currentTime}}</span>
<span class="time-middle">/</span>
<em class="time-long">{{duration}}</em>
</div>
<div class="util-box">
<span @click="isShowRateList = !isShowRateList">倍速{{rateVal}}x</span>
<ul v-if="isShowRateList">
<li v-for="(t,i) in playBackRateList" :key="i" @click="changeRate(t)">{{t}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</transition>
</div>
</template> <script>
import { courseStore } from "@/store/course.js";
import { tokenStore } from "@/store/user.js";
export default {
layout: 'detail',
name: 'CourseCatalogue', // 校验动态路由参数的有效性
validate({ params, query }) { },
// 获取详情数据
async asyncData({ $axios, params }) {
return { }
}, // 处理数据
created() { }, mounted() {
// 初始化播放器
this.createPlayer() }, // 销毁定时器及阿里播放器
beforeDestroy() {
this.stopReportLearning()
if (this.player) {
this.player.dispose()
this.player = null
}
}, //
computed: { },
data() {
return {
store: courseStore(), // 课程商店
userStore: tokenStore(), // 用户商店 seeked: true, // 是否可续播
// 播放相关
canplay: false,// 是否可以播放
isShowPlayer: false,// 是否显示播放器
playerLoading: true, // 播放器loading
playingAudioName: '', // 正在播放的课程名称
player: null, // 播放器
timer: null, // 学习上报定时器
playDate: '', // 当前视频的时间戳
opener: true,
playerUrl: '/a.m3u8', // 播放的资源路径
sliderVal: 0, // 滑块当前时长。
sliderMin: 0,
sliderMax: 0, // 滑块的总时长。
currentTime: '00:00', // 当前播放时间
duration: '00:00', // 总时长
play: false, // 播放ing?暂停?
// 播放/暂停图标
playIcon: require('@/assets/image/play.png'),
pauseIcon: require('@/assets/image/pause.png'),
isShowRateList: false, // 是否展示倍速列表
rateVal: 1, // 当前倍速
playBackRateList: [0.25, 0.5, 0.75, '正常', 1.25, 1.5, 1.75, 2], // 倍速
}
},
methods: {
// 获取vid+playauth
getVid() { },// 初始化播放器
createPlayer() {
let prop = {
id: "aliPlayer",
source: this.playerUrl,
mediaType: "audio",
width: "100%",
height: "100%",
autoplay: false, // 自动播放
isLive: false, // 直播
rePlay: false, // 循环播放
playsinline: true, //H5是否内置播放
preload: true, //播放器自动加载
language: "zh-cn", // 语言
cover: '', //播放器默认封面图片,需要autoplay为’false’时,才生效
controlBarVisibility: "hover", //控制面板的实现 ‘click’ 点击出现、‘hover’ 浮动出现、‘always’ 一直在
useH5Prism: true //指定使用H5播放器
} this.player = new Aliplayer(prop, function (player) {
console.log("The player is created");
}) // 播放 (由暂停恢复为播放时触发)
this.player.on('play', () => {
this.play = true
}) // 暂停
this.player.on('pause', () => {
this.play = false
this.stopReportLearning()
}) // 播放ing (播放中,会触发多次)
this.player.on('playing', () => {
// console.log('播放中ing') // 学习记录上报
this.learningReport()
}) // 可以播放
this.player.on('canplay', () => {
this.playerLoading = false
const courseInfo = this.store.getCourseInfo
if (this.canplay && this.seeked && courseInfo.duration && courseInfo.newestLessonId === courseInfo.lessonId) {
this.seeked = false
this.player.seek(courseInfo.duration)
}
}) // 等待缓冲
this.player.on('waiting', () => {
this.playerLoading = true
}) // 时长发生变动时
this.player.on('timeupdate', () => {
this.updateTime()
}) // 播放出错
this.player.on('error', () => {
this.$message.error('播放出错')
this.stopReportLearning()
this.sliderVal = 0
this.play = false
this.playerLoading = true
this.isShowPlayer = false
this.store.setIsPlaying(false)
}) // 播放完毕
this.player.on("ended", () => {
if (this.opener) {
this.opener = false
console.log('播放完了!') // 停止学习上报
this.stopReportLearning()
this.playDate = '' // 调用子组件方法,自动播放下一个
const courseInfo = this.store.getCourseInfo
this.$refs.CourseCurriculum.createdPlayList(courseInfo.courseId, courseInfo.lessonId)
}
});
}, // 学习记录上报
learningReport() { // 先清空
this.stopReportLearning() const courseInfo = this.store.getCourseInfo
const lessonAudioVideo = courseInfo.lessonAudioVideo // 播放时长小于1时不进行上报
// if (curTime <= 1) {
// return
// } if (this.playDate === '') {
const nowDate = new Date
this.playDate = nowDate.getTime()
} // 学次唯一值
const userInfo = this.userStore.getUserInfo
const key = `${userInfo.userId}_${courseInfo.orderId}_${courseInfo.projectId}_${courseInfo.courseId}_${courseInfo.lessonId}_${this.playDate}`;
const sessionKey = this.$md5(key) this.timer = setInterval(() => {
const curTime = parseInt(this.player.getCurrentTime())
this.$axios.$post('/hadoop/learning/learningRecordSend', {
sessionKey: sessionKey,
orderId: courseInfo.orderId,
projectId: courseInfo.projectId,
courseId: courseInfo.courseId,
courseCatalogId: courseInfo.lessonId,
resourceType: lessonAudioVideo.type,
resourceId: lessonAudioVideo.audioId,
duration: curTime
}).then(() => { }).catch((err) => {
if (err.code === 10009) this.player.pause()
});
}, 5000)
}, // 停止上报学习记录
stopReportLearning() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
}, // 关闭播放器
closePlayer() {
this.isShowPlayer = false
this.store.setIsPlaying(false)
this.stopReportLearning()
this.play = false
this.playerLoading = true
this.player.pause()
}, // 播放/暂停
playHandle() {
this.play = !this.play
this.play ? this.player.play() : this.player.pause()
}, // 更新时间
updateTime() {
if (!Number.isFinite(this.player.getDuration())) {
this.currentTime = Number.MAX_SAFE_INTEGER;
this.currentTime = '00:00';
} else {
const total = this.formatTime(this.player.getDuration())
const current = this.formatTime(this.player.getCurrentTime())
this.duration = `${total.min}:${total.sec}`
this.currentTime = `${current.min}:${current.sec}`
this.sliderVal = Math.floor(this.player.getCurrentTime())
this.sliderMax = Math.floor(this.player.getDuration())
}
}, // 格式化毫秒,返回String型分秒对象
formatTime(time) {
// 如果没获取到
if (!time) return { min: '00', sec: '00' }
return {
min: Math.floor(time / 60).toString().padStart(2, '0'),
sec: Math.floor(time % 60).toString().padStart(2, '0')
}
}, // 格式化毫秒数,对应elm滑块组件
formatTooltip(val) {
const time = this.formatTime(val)
return `${time.min}:${time.sec}`
}, // 滑块松动后触发。更新当前时长,
// 时长发生变动会init里的方法进行更新数据
sliderChange(val) {
this.player.seek(this.sliderVal)
}, // 倍速改变时
changeRate(t) {
if (t === '正常') t = 1;
this.rateVal = t
this.player.setSpeed(t)
this.isShowRateList = false
},
}
}
</script>
视频播放代码:
<template>
<div class="wrap">
<!-- 视频区域 -->
<div class="video" :class="{'w1': sideBarFlag}"> <!-- 视频 -->
<div class="player" id="aliVideoPlayer"></div> </div> <!-- 侧边栏区域 --> </div>
</template> <script>
import { courseStore } from "@/store/course.js";
import { tokenStore } from "@/store/user.js";
export default {
layout: 'index',
async asyncData({ $axios, query }) {
const [chapterList] = await Promise.all([
// 获取视频资源
// $axios.$get(`/resources/resources/video/${lessonAudioVideo.videoId}`),
// 获取课程列表
$axios.$get('/learning/user/project/pc/catalog/v1', {
params: {
projectId: query.projectId,
courseId: query.courseId
}
}),
])
return {
// videoData,
chapterList
}
},
data() {
return {
store: courseStore(), // 课程商店
userStore: tokenStore(), // 用户商店
courseInfo: {},// 当前播放的课程相关信息
player: null, // 播放器
opener: true,
playerUrl: '', // 播放的资源url
vid: '', // vid + playauth
playauth: '',
lessonName: '', // 当前播放的课次名称
seeked: true, // 是否可续播
speed: 1, // 倍速
// 侧边栏
sideBarFlag: true,
// 目录/笔记
listFlag: true,
// 学习上报定时器
timer: null,
// 当前视频的时间戳
playDate: '',
}
}, beforeMount() {
this.courseInfo = this.store.getCourseInfo
// 获取视频资源url
// this.playerUrl = this.courseInfo.lessonAudioVideo.url
}, async mounted() {
// 获取视频vid+playauth
const videoInfo = await this.getVid()
this.playerUrl = JSON.stringify({ 'FD': videoInfo.Fd, 'SD': videoInfo.Sd })
// this.vid = videoInfo.VideoId
// this.playauth = videoInfo.PlayAuth
// 初始化播放器
this.createPlayer()
}, // 销毁定时器
beforeDestroy() {
this.stopReportLearning()
if (this.player) {
this.player.dispose()
this.player = null
}
}, methods: {
// 获取vid+playauth
getVid() {
return this.$axios.$get(`/file/sys/file/getVideoPlayUrl`, {
params: {
videoId: this.courseInfo.lessonAudioVideo.resourcesId
}
})
},
// 初始化播放器
createPlayer() {
let prop = {
id: "aliVideoPlayer", // 资源url播放
source: this.playerUrl, // vid+playauth播放
// vid: this.vid,
// playauth: this.playauth,
// encryptType: '1', // 播放加密视频
// qualitySort: "asc", // 指定排序方式,只有使用Vid + PlayAuth播放方式时支持。
// format: "m3u8", // 指定播放地址格式,只有使用vid的播放方式时支持可选值。
// definition: "FD,LD,SD,HD,OD,2K,4K", // 此值是vid对应流清晰度的一个子集,仅H5模式支持。
// defaultDefinition: 'SD', // 默认视频清晰度,此值是vid对应流的一个清晰度,仅H5模式支持。 mediaType: "video",
width: "100%",
height: "100%",
autoplay: true, // 自动播放
isLive: false, // 直播
rePlay: false, // 循环播放
playsinline: true, //H5是否内置播放
preload: true, //播放器自动加载
keyShortCuts: true, // 是否启用快捷键
language: "zh-cn", // 语言
cover: '', //播放器默认封面图片,需要autoplay为’false’时,才生效
controlBarVisibility: "hover", //控制面板的实现 ‘click’ 点击出现、‘hover’ 浮动出现、‘always’ 一直在
useH5Prism: true, //指定使用H5播放器
components: [
{ name: 'RateComponent', type: AliPlayerComponent.RateComponent },
{ name: 'MemoryPlayComponent', type: AliPlayerComponent.MemoryPlayComponent },
{
name: 'QualityComponent',
type: AliPlayerComponent.QualityComponent
}],
skinLayout: [
{ name: "bigPlayButton", align: "blabs", x: 30, y: 80 },
{ 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: 15, y: 12 },
// { name: "setting", align: "tr", x: 15, y: 12 },
{ name: "volume", align: "tr", x: 5, y: 10 }
]
}
]
} this.player = new Aliplayer(prop, function (player) {
console.log("The player is created");
player.on('sourceloaded', function (params) {
var paramData = params.paramData
var desc = paramData.desc
var definition = paramData.definition
// 获取清晰度组件并调用清晰度组件的 setCurrentQuality 设置清晰度
player.getComponent('QualityComponent').setCurrentQuality(desc, definition)
}) // 是否有设置过倍速
if (this.speed) {
player.setSpeed(this.speed)
}
}) // 播放
this.player.on('play', () => {
// console.log('开始播放')
}) // 播放ing
this.player.on('playing', () => {
// console.log('播放中ing') this.speed = this.player.tag.playbackRate // 学习记录上报
this.learningReport()
}) // 可以播放
this.player.on('canplay', () => {
if (this.seeked && this.courseInfo.duration && this.courseInfo.newestLessonId === this.courseInfo.lessonId) {
this.seeked = false
this.player.seek(this.courseInfo.duration)
}
}) // 暂停
this.player.on('pause', () => {
// console.log('播放暂停') // 停止上报
this.stopReportLearning()
}) // 播放出错
this.player.on('error', () => {
this.$message.error('播放出错')
}) // 播放完毕
this.player.on("ended", (e) => {
if (this.opener) {
this.opener = false
console.log('播放完了!!!!!')
this.stopReportLearning()
this.playDate = '' // 调用子组件方法,自动播放下一个
this.$refs.videoList.createdPlayList(this.courseInfo.lessonId)
}
})
}, // 接受到子组件课次变化,播放新的视频
async lessonChange(doing) { this.courseInfo = this.store.getCourseInfo // 未告知要播放时,只展示课次名字
if (doing !== 'play') {
this.lessonName = this.courseInfo.lessonName
return
} // 检测播放源是否相同(目前不进行检测,否则导致点击相同资源时->无法重播)
// if (this.playerUrl !== this.courseInfo.lessonAudioVideo.url) { // 更改视频源 // TODO: url
// this.playerUrl = this.courseInfo.lessonAudioVideo.url
// this.player.loadByUrl(this.playerUrl) // TODO: vod
const videoUrl = await this.getVid()
// this.playerUrl = videoInfo.Sd
// this.player.loadByUrl(this.playerUrl)
this.player.dispose()
this.playerUrl = JSON.stringify({ 'FD': videoUrl.Fd, 'SD': videoUrl.Sd })
this.createPlayer() // TODO: vid+playauth
// this.vid = videoInfo.VideoId
// this.playauth = videoInfo.PlayAuth
// this.player.replayByVidAndPlayAuth(this.vid, this.playauth) // } else {
// this.player.play()
// } this.lessonName = this.courseInfo.lessonName
this.seeked = true
this.opener = true
}, // 停止上报学习记录,清楚定时器
stopReportLearning() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
}, // 学习记录上报
learningReport() {
// 先清空
this.stopReportLearning() const courseInfo = this.courseInfo
const lessonAudioVideo = this.courseInfo.lessonAudioVideo if (this.playDate === '') {
const nowDate = new Date
this.playDate = nowDate.getTime()
// console.log(this.playDate)
} // 学次唯一值
const userInfo = this.userStore.getUserInfo
const key = `${userInfo.userId}_${courseInfo.orderId}_${courseInfo.projectId}_${courseInfo.courseId}_${courseInfo.lessonId}_${this.playDate}`;
const sessionKey = this.$md5(key) this.timer = setInterval(() => {
const curTime = parseInt(this.player.getCurrentTime())
this.$axios.$post('/hadoop/learning/learningRecordSend', {
sessionKey: sessionKey,
orderId: courseInfo.orderId,
projectId: courseInfo.projectId,
courseId: courseInfo.courseId,
courseCatalogId: courseInfo.lessonId,
resourceType: lessonAudioVideo.type,
resourceId: lessonAudioVideo.videoId,
duration: curTime
}).then(() => { }).catch((err) => {
if (err.code === 10009) this.player.pause()
});
}, 5000)
}
}
}
</script>
阿里播放器Aliplayer遇到的所有坑的更多相关文章
- 阿里播放器踩坑记录 进度条重构 video loadByUrl失效解决方案
如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 文档地址:https://player.alicdn.com/aliplayer/index. ...
- vue+element-ui中引入阿里播放器
1.在public文件下的index.html文件中插入以下代码: <link rel="stylesheet" href="https://g.alicdn.co ...
- 阿里云web播放器
原文地址:https://help.aliyun.com/document_detail/51991.html?spm=5176.doc61109.6.703.ZTCYoi 一.概念说明 1. pla ...
- 如何利用阿里视频云开源组件,快速自定义你的H5播放器?
摘要: Aliplayer希望提供一种方便.简单.灵活的机制,让客户能够扩展播放器的功能,并且Aliplayer提供一些组件的基本实现,用户可以基于这些开源的组件实现个性化功能,比如自定义UI和自己A ...
- 阿里云Prismplayer-Web播放器的使用
Prismplayer是一套在线视频播放技术方案,同时支持Flash和Html5两种播放技术,可对播放器进行功能配置和皮肤定制.其在线使用文档地址为:https://help.aliyun.com/d ...
- 前端视频插件Aliplayer播放器简单使用(基于地址播放)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- RTSP播放器开发填坑之道
好多开发者提到,在目前开源播放器如此泛滥的情况下,为什么还需要做自研框架的RTSP播放器,自研和开源播放器,到底好在哪些方面?以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延 ...
- RTMP播放器开发填坑之道
好多开发者提到,在目前开源播放器如此泛滥的情况下,为什么还需要做自研框架的RTMP播放器,自研和开源播放器,到底好在哪些方面?以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延 ...
- Web播放器
web视频播放器的使用及遇到的问题记录 TcPlayer播放器(腾讯Web超级播放器) https://cloud.tencent.com/document/product/881/20207 Ste ...
- iOS多播放器封装
今年在做直播业务的时候遇到一些问题,就是在一个套播放器UI中需要多种不同的播放器(AVPlayer.IJKPlayer.AliPlayer)支持,根据ABTest开关来切换具体使用哪种播放器,并且还要 ...
随机推荐
- ionic+vue+capacitor系列笔记--03项目使用Native插件
话不多说,直接上代码 下载依赖 npm install @capacitor/camera 添加权限配置代码到安卓文件夹里的 AndroidManifest.xml <uses-permissi ...
- ionic+vue+capacitor系列笔记--01项目初始化
Ionic 是什么? Ionic 是一款接近原生的 Html5 移动 App 开发框架,只需要你会 HTML.CSS 和 JavaScript 就可以开发移动 App应用,使用最基础的 Web 技术创 ...
- Ubuntu安装Anaconda并且配置国内镜像教程
前言 我们在学习 Python 的时候需要不同的 Python 版本,关系到电脑环境变量配置换来换去很是麻烦,所以这个时候我们需要一个虚拟的 Python 环境变量,我之前也装过 virtualenv ...
- 【单片机】nRF52832 实现停止蓝牙广播接口
前言 有一个项目使用了 nRF52832 芯片作为主控,其中有用到蓝牙功能.在对蓝牙接口进一步封装的时候,发现 SDK 居然没有停止广播的接口,咨询了代理 FAE,对方也没有找到关闭广播的接口.后来通 ...
- 【Django drf】视图层大总结 ViewSetMixin源码分析 路由系统 action装饰器
目录 九个视图子类 视图集 继承ModelViewSet类写五个接口 继承 ReadOnlyModelView编写2个只读接口 ViewSetMixin源码分析 查找as_view方法 setattr ...
- 洛谷 P3137 [USACO16FEB]Circular Barn S
题目链接 本蒟蒻的第一篇题解,写得不好请指出,敬请谅解 题意: 有\(n\)头奶牛,分布在一些房间,某些房间可能有多头牛,要让这些牛按顺时针移动,求使每一个房间刚好有一个奶牛的最小花费 花费计算:如果 ...
- 第九周总结-MySQL、前端
多表查询的两种方式 1.连表操作: 1.1: inner join:内连接,将两张表共同的部分连接在一起生成一张新表.凭借顺序是把后面的表拼在前面表的后面,如果颠倒位置结果不同. select * f ...
- 元数据库 information_schema.tables
转 https://www.cnblogs.com/ssslinppp/p/6178636.html 1.information_schema数据库 对于mysql和Infobright等数据库,i ...
- 6、Collections工具类
1.Collections工具类介绍 Collections 是一个操作 Set.List 和 Map 等集合的工具类 Collections 中提供了一系列静态的方法对集合元素进行排序.查询和修改等 ...
- P4_创建第一个小程序项目
设置外观和代理 创建小程序项目 点击"加号"按钮 填写项目信息 项目创建完成 在模拟器上查看项目效果 在真机上预览项目效果 主界面的 5 个组成部分