videojs 实现自定义组件(视频画质/清晰度切换) React

前言

最近使用videojs作为视频处理第三方库,用来对接m3u8视频类型。这里总结一下自定义组件遇到的问题及实现,目前看了许多文章也不全,官方文档写的也不是很详细,自己摸索了一段时间陆陆续续完成了,这是实现后的效果.

image.png

样式啥的自己检查后覆盖就行了,没啥说的,重点看看画质切换这个组件如何实现的。最开始我是采用函数组件直接嵌入进去,后面发现是报错的,原因是hook使用范围有误,找了半天也不知道是什么原因。后面采用继承Videojs内的menu组件来实现。

代码实现

option配置如下

 const options: any = {controls: true,preload: 'auto',language: 'zh-CN',width: 854,height: 480,playbackRates: [0.5, 0.75, 1, 1.5, 2], // 倍速数组controlBar: {children: {PlayToggle: true,CurrentTimeDisplay: true,DurationDisplay: true,ProgressControl: true,Quality: true,PlaybackRateMenuButton: true,volumePanel: {inline: false,},PictureInPictureToggle: true,FullscreenToggle: true,},},}

video组件

import { ForwardedRef, forwardRef, useEffect, useImperativeHandle, useRef } from 'react'
import videojs from 'video.js'
import Quality from './quality'import './index.less'interface videoComProps {videoOptions: anyonReady: (player: any) => voidsrc?: string
}const VideoWrapper = (props: videoComProps, ref: ForwardedRef<any>) => {const { videoOptions, onReady, src } = propsconst videoRef = useRef<any>(null)const playerRef = useRef<any>(null)function toggleTv(obj: any) {const player = playerRef?.currentif (!player) returnplayer.src(obj.src)player.load(obj.load)player.play()}useEffect(() => {if (!playerRef?.current && videoRef.current) {// 注册组件  一定要在使用之前注册哦videojs.registerComponent('Quality', Quality as any)// 初始化videoconst player = (playerRef.current = videojs(videoRef.current, videoOptions, () => {onReady(player)}))}}, [videoRef])useEffect(() => {const player = playerRef.currentreturn () => {// 组件销毁的时候,销毁视频播放器的实例if (player && !player.isDisposed()) {player.dispose()playerRef.current = null}}}, [playerRef])// ref抛出变量useImperativeHandle(ref, () => ({toggleTv,}))return (<div className="video-wrapper"><videoref={videoRef}className="video-js vjs-big-play-centered"><source src={src} />{/* <span>视频走丢了,请稍后再试</span> */}</video></div>)
}export default forwardRef(VideoWrapper)

自定义组件

// 切换视频清晰度代码
import videoJs from 'video.js'
import { createRoot } from 'react-dom/client'// 初始化清晰度按钮
const TextTrackMenuItem: any = videoJs.getComponent('TextTrackMenuItem')
const TrackButton: any = videoJs.getComponent('TrackButton')
const videoQuality = '超清,高清,自动'class QualityTrackItem extends TextTrackMenuItem {constructor(player: any, options: any) {super(player, options)this.mount = this.mount.bind(this)player.ready(() => {this.mount()})this.on('dispose', () => {this.root.unmount()})if (options.index === 2) {this.addClass('vjs-selected')}}// 切换高清播放源,this 指向被点击QualityTrackItem实例handleClick(event: any) {// 先将所有选项的选中状态设为未选中this.parentComponent_.children_.forEach((c: any) => {c.selected(false)})// 选中当前this.selected(true)// 选中后修改按钮文本const btn = document.querySelector('.vjs-menu-button .vjs-icon-placeholder')if (!btn) returnbtn.innerHTML = this.track.label// 其他逻辑 通知修改视频源地址进行切换console.log('切换视频源')}mount() {this.root = createRoot(this.el()).render(<div>{this.track.label}</div>)}
}
// 扩展基类,实现菜单按钮
class QualityTrackButton extends TrackButton {constructor(player: any, options: any) {super(player, options)this.controlText('画质选择')this.children()[0].el().firstElementChild.innerText = '自动'this.addClass('vjs-quality')}createItems() {const qualityKeyArray = videoQuality.split(',')if (qualityKeyArray.length > 0) {const result: any = []qualityKeyArray.forEach((key, index: number) => {result.push(new QualityTrackItem(this.player_, {track: {label: key,value: key,},selectable: true,index,}))})return result} else {return []}}
}export default QualityTrackButton

END

希望能帮到正在开发的伙伴们

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/104136.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis分页与特殊字符处理

文章目录 一、分页1.1 分页插件PageHelper1.2 使用1.2.1 导入pom依赖1.2.2 Mybatis.cfg.xml配置拦截器1.2.3. 配置 Mapper.xml1.2.4 测试 二、特殊字符处理2.1 使用CDATA区段2.2 使用实体引用 一、分页 1.1 分页插件PageHelper PageHelper 是 Mybatis 的一个插件。官网 Page…

ios小组件报错:Please adopt containerBackground API

iOS 17 小组件报错:Please adopt containerBackground API 使用下面的方法解决了: 代码: extension View {func widgetBackground(_ backgroundView: some View) -> some View {if #available(iOSApplicationExtension 17.0, *) {return containerBackground(for: .wi…

【云原生】Docker私有仓库 RegistryHabor

目录 1.Docker私有仓库&#xff08;Registry&#xff09; 1.1 Registry的介绍 1.2 Registry的部署 步骤一&#xff1a;拉取相关的镜像 步骤二&#xff1a;进行 Registry的相关yml文件配置&#xff08;docker-compose&#xff09; 步骤三&#xff1a;镜像的推送 2. Regist…

k8s 安装 istio(二)

3.3 部署服务网格调用链检测工具 Jaeger 部署 Jaeger 服务 kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/jaeger.yaml 创建 jaeger-vs.yaml 文件 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata…

java 高级面试题整理(薄弱技术)

session 和cookie的区别和联系 session1.什么是session Session是另一种记录客户状态的机制&#xff0c;不同的是Cookie保存在客户端浏览器中&#xff0c;而Session保存在服务器上。客户端浏览器访问服务器的时候&#xff0c;服务器把客户端信息以某种形式记录在服务器上。这就…

常用的数据可视化工具有哪些?要操作简单的

随着数据量的剧增&#xff0c;对分析效率和数据信息传递都带来了不小的挑战&#xff0c;于是数据可视化工具应运而生&#xff0c;通过直观形象的图表来展现、传递数据信息&#xff0c;提高数据分析报表的易读性。那么&#xff0c;常用的操作简单数据可视化工具有哪些&#xff1…

Dockerfile推送私有仓库的两个案例

一&#xff0c;编写Dockerfile制作Web应用系统nginx镜像&#xff0c;生成镜像nginx:v1.1&#xff0c;并推送其到私有仓库。 具体要求如下&#xff1a; &#xff08;1&#xff09;基于centos基础镜像&#xff1b; &#xff08;2&#xff09;指定作者信息&#xff1b; &#xff…

数据结构:二叉树及相关操作

文章目录 前言一、树的概念及结构1.什么是树2. 树的相关概念3.树的表示 二、二叉树概念及结构1.二叉树概念2.特殊的二叉树3.二叉树的性质4.二叉树的存储结构 三、平衡二叉树实现1.创建树和树的前中后遍历1.前中后遍历2.创建树且打印前中后遍历 2.转换为平衡二叉树和相关操作1.转…

Anaconda安装教程以及深度学习环境搭建

目录 前言 下载Anaconda 虚拟环境的搭建 在pycharm中配置现有的conda环境 CUDA简介 下载安装pytorch包 前言 最近换新笔记本了&#xff0c;要重新安装软件&#xff0c;以前本来是想要写这个教程的&#xff0c;但当时由于截图不全还要懒得再下载重装&#xff0c;就放弃了&…

高效多用的群集-Haproxy搭建Web集群

Haproxy搭建 Web 群集 一、Haproxy前言 HAProxy是一个使用c语言编写的自由及开放源代码软件&#xff0c;其提供高可用性、负载均衡&#xff0c;以及基于TcP和HrrP的应用程序代理。HAProxy特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或七层处理。…

jmeter模拟多用户并发

一、100个真实的用户 1、一个账号模拟100虚拟用户同时登录和100账号同时登录 区别 &#xff08;1&#xff09;1个账号100个人用&#xff0c;同时登录&#xff1b; &#xff08;2&#xff09;100个人100个账号&#xff0c;同时登录。 相同 &#xff08;1&#xff09;两个都…

【ES6】—数组的扩展

一、类数组/ 伪数组 1. 类/伪数组: 并不是真正意义的数组&#xff0c;有长度的属性&#xff0c;但无法使用Array原型上的方法 let divs document.getElementsByTagName(div) console.log(divs) // HTMLCollection []let divs2 document.getElementsByClassName("xxx&q…

【业务功能篇73】分布式ID解决方案

业界实现方案 1. 基于UUID2. 基于DB数据库多种模式(自增主键、segment)3. 基于Redis4. 基于ZK、ETCD5. 基于SnowFlake6. 美团Leaf(DB-Segment、zkSnowFlake)7. 百度uid-generator() 1.基于UUID生成唯一ID UUID:UUID长度128bit&#xff0c;32个16进制字符&#xff0c;占用存储空…

Kdab QML (part9)自由缩放时钟

文章目录 Kdab QML (part9)自由缩放时钟代码详细解释运行截图 Kdab QML (part9)自由缩放时钟 代码 import QtQuick 2.15 import QtQuick.Window 2.15Window {id: rootwidth: 500height: 500visible: truecolor: "lightgrey"title: qsTr("Hello World")It…

springboot2+redis 订阅发布,解决接收消息累计线程到内存溢出,使用自定义线程池接收消息

pom 添加redis <!-- redis 缓存操作 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 发布消息 import lombok.extern.slf4j.Slf4j; import o…

【一】ubuntu20.04上搭建containerd版( 1.2.4 以上)k8s及kuboard V3

k8s 部署全程在超级用户下进行 sudo su本文请根据大纲顺序阅读&#xff01; 一、配置基础环境&#xff08;在全部节点执行&#xff09; 1、安装docker 使用apt安装containerd 新版k8s已经弃用docker转为containerd&#xff0c;如果要将docker改为containerd详见&#xff1a…

21.1 CSS 文字样式

1. 字体倾斜 font-style属性: 为文本设置字体样式.常用取值: normal: 正常显示文本. 快捷键: fstab. italic: 显示斜体文本. 快捷键: fsntab.<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>fo…

MySQL高级篇——MySQL架构篇3(用户与权限管理)

目录 1 用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其它用户密码1.7 MySQL8密码管理(了解) 2 权限管理2.1 权限列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限 3 权限表3.1 user表3.2 db表3.3 tables_priv表和…

实现外网访问本地服务

最近开发需要其他项目组的人访问我本地服务测试,但又不在同一个地方,不能使用内网访问,所以需要外网访问本地服务功能. 条件: 1.需要一台具备公网IP的服务器 我用的服务器是windows,电脑也是Windows系统 2.下载frp 软件,只需要下载一份就可以了,分别放到服务器上和本地目录既…

Python - 面向对象的属性,类方法,静态方法,实例方法的区别及用法详解

一. 前言 在Python的面向对象编程中&#xff0c;类属性和实例属性是两个不同的概念&#xff0c;它们在作用域和使用方式上有所区别。在Python中的面向对象编程中有三种方法&#xff1a;实例方法、类方法和静态方法&#xff0c;它们之间的差异主要体现在参数传递和调用方式上。…