画质切换
当你的视频是 .m3u8
这种流媒体格式,可以使用 hls.js 直接在客户端进行清晰度的切换,而对于 .mp4
这种容器格式,我们就要准备多个清晰度的视频源,以供用户切换。
提示
一般用户上传一个高清的视频到视频网站的服务端后,可以使用比如 FFmpeg 这种工具来重新编解码生成不同清晰度、码率的视频。
比如我现在准备的视频有以下三种清晰度的视频:
test-video_1080p.mp4
test-video_720p.mp4
test-video_480p.mp4
然后通过自定义一个控制器项来实现:
js
import Player from 'qier-player'
const quantity = {
el: document.createElement('div'),
init(player) {
const quantities = [
{
id: '1080p',
label: '1080p 高清',
checked: true,
dom: null
},
{
id: '720p',
label: '720p 清晰',
checked: false,
dom: null
},
{
id: '480p',
label: '480p 流畅',
checked: false,
dom: null
},
]
this.btn = document.createElement('div')
this.btn.textContent = quantities[0].label
this.el.appendChild(this.btn)
// 填充以防光标离开控制项弹框就丢失
this.stuffing = document.createElement('div')
this.stuffing.classList.add('qier-player_controller_quantity_stuffing')
this.el.appendChild(this.stuffing)
this.popover = new Popover(this.el)
this.el.addEventListener('mouseenter', () => {
this.stuffing.style.display = 'block'
this.popover.show()
// 这段代码是通知其他弹框应该立即消失
player.emit(EVENT.POPOVER_SHOW_CHANGE);
})
this.el.addEventListener('mouseleave', () => {
this.stuffing.style.display = 'none'
this.popover.hide()
})
this.el.classList.add('qier-player_controller_quantity')
const quantityWrapper = document.createElement('div')
quantities.forEach((item) => {
const quantityItem = document.createElement('div')
quantityItem.classList.add('qier-player_controller_quantity_item')
quantityItem.setAttribute('data-id', item.id)
quantityItem.innerText = item.label
item.dom = quantityItem
quantityWrapper.appendChild(quantityItem)
quantityItem.addEventListener('click', (e) => {
e.stopPropagation()
if (e.target) {
const targetDom = e.target as HTMLElement
const id = targetDom.getAttribute('data-id')
const checkedItem = quantities.find(item => item.id === id)
if (!checkedItem.checked) {
quantities.forEach(item => {
item.checked = false
item.dom.classList.remove('qier-player_controller_quantity_item--active')
})
checkedItem.checked = true
item.dom.classList.add('qier-player_controller_quantity_item--active')
this.btn.textContent = item.label
// 提示:这里使用 video 标签更改 src 的方式不友好,还有 bug,后续会修复,提供一个更新的方法
player.video.src = `/test-video_${item.id}.mp4`
}
}
})
})
this.popover.panelEl.appendChild(quantityWrapper);
}
}
const player = new Player({
controller: {
progress: ['progress'],
eles: ['play', 'time', 'spacer', quantity, 'volume', 'settings', 'web-fullscreen', 'fullscreen'],
},
})
player.mount(document.body)
样式代码:
css
.qier-player_controller_quantity) {
position: relative;
height: 100%;
padding: 6px;
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
font-size: 14px;
}
.qier-player_controller_quantity_item {
display: flex;
align-items: center;
justify-content: center;
padding: 5px 8px;
width: 128px;
position: relative;
}
.qier-player_controller_quantity_item:hover {
color: var(--theme-color);
background: rgba(255, 255, 255, 0.2);
}
.qier-player_controller_quantity_item--active {
color: var(--theme-color);
}
.qier-player_controller_quantity_item--active::before {
margin-right: 16px;
margin-bottom: 4px;
margin-left: 10px;
opacity: 1;
content: '';
display: inline-block;
width: 5px;
height: 12px;
border-right: 1px solid var(--theme-color);
border-bottom: 1px solid var(--theme-color);
transform: rotate(45deg);
position: absolute;
left: 4px;
}
.qier-player_controller_quantity_stuffing {
position: absolute;
bottom: 100%;
left: 0;
display: none;
width: 100%;
padding: 20px 0;
}