摘要:是一款轻量级易扩展的播放器,是为解决一些中小型的视频业务场景。同时各插件由于是面向的播放器接口,插件不知道插件的存在,因此能极大地降低各插件功能间的耦合。
larkplayer 是一款轻量级 & 易扩展的 html5 播放器,是为解决一些中小型的视频业务场景。这些业务不一定需要大而全的解决方案,并且他们往往有自己的定制化需求。
背景为什么要编写 larkplayer?(注意,这里面有一些我的个人观点)
目前 html5 web player 社区已经比较成熟,videojs 和 jwplayer 等都是优秀的解决方案。然而,社区的两极分化也比较严重:
排名靠前的播放器基本都是一种『大而全』的状态:功能丰富&定制化,体积动辄几百K。对于一些相对简单的业务,还是有点太重了,尤其是在移动端,在做扩展时也可能由于一些已有的功能而碍手碍脚
一些小一点的播放器,往往只是解决了自己特定的业务场景的问题,缺乏扩展性
一些播放器存在对某些大型库(比如 jQuery、AngularJS 等)的依赖,通用性与可移植性不是很好
因此,对于一些中小型的视频业务场景,其实并没有一个舒服的播放器方案可供选择。
思考如何解决上诉问题?
业务上:
轻量,尽量不提供"多余"的功能,代码体积小
易扩展,能轻易地支持如广告、皮肤、统计等各种定制化需求
代码上:
解决兼容性问题,把琐碎的细节留在内部,对外接口统一
插件化机制,解耦各功能,提供方便扩展的接口与方式
原生 javascript 编写,减少对类库的依赖,便于在各种环境下使用与移植
设计larkplayer 的灵感来自 videojs,采用插件化的设计:播放器本身只是一个精巧的核心,包含一些必备的机制和 API,其余功能由插件提供。
你可以自由选择和编写自己的插件,做到按需取用,渐进增强。在 ugilfy + gzip 后,larkplayer 代码体积约 12KB.
Html5 模块负责抹平兼容性问题,对外提供统一的 API
Event 模块提供事件机制,支持原生事件及自定义事件
Plugin 模块用于提供插件机制,为各类插件提供基类,约定其接口及运行方式
Util 中包含一些常用的工具方法,比如对 DOM 的一些便捷操作函数
Player 模块聚合以上模块,用以实例化播放器以及对外提供接口
2. API 3. 事件机制事件作为播放器内部核心的沟通机制,为内部的状态流转以及后续的扩展提供底层支持。
目前自定义事件系统的实现方式主要有 2 种:
DOM Event:HTML 原生 API,能够监听 DOM 相关事件,支持自定义事件,具有捕获、冒泡机制,需要一些兼容性处理
EventEmitter:JS 实现的事件机制,核心是一套『订阅发布模式』,允许自定义事件,拥有更加灵活的 API,无法监听 DOM 相关事件,基本无兼容性问题
由于 DOM Event 能够监听 DOM 相关事件,同时冒泡机制对后续 UI 插件的控制有一定的帮助,因此选用其作为自定义事件系统实现的基础。
通过 DOM Event 实现以下几类主要功能:
事件监听
事件注销
支持自定义事件类型
支持手动触发事件(通过 JS 触发而不是用户交互触发)
DOM Event 流程可通过下图概览:
插件是一种常用的『依赖反转』的方式,使得播放器不必依赖外部或下层组件,而是所有外部插件都依赖播放器本身。
同时各插件由于是面向的播放器接口,插件 A 不知道 插件 B 的存在,因此能极大地降低各插件(功能)间的耦合。
如何设计插件的类型和接口便关系到后续长期的发展,经过业务经验的总结以及对其他解决方案的参考,总结出以下 3 类插件类型:
UI 插件,DOM 相关,往往是要添加某些样式或交互,如皮肤、弹幕等
MSE 插件,播放技术相关,基于 Media Source Extension,可扩展播放器对其他视频类型的支持,如 m3u8、flv 等
其他插件,可以看做是一种保留类型,上述两种类型无法满足时,落到此类型,后续某类新的插件高频出现时,可再次抽离出新的类型
这几类插件如何运行呢?这里简单介绍下,具体可以参见设计文档或源码。
1.UI 插件
Component 类作为基类,提供事件、DOM 操作工具函数支持,可获取到播放器引用
组件化的方式开发,通过构建工具与代码配合,支持 JSX 语法
可在播放器初始化时传递参数,以及从播放器上获取插件实例
2.MSE 插件
MSEHandler 类作为基类,提供事件支持,可获取播放器引用,给予修改播放器 play 等方法的权限
可在播放器初始化时传递参数,以及从播放器上获取插件实例
3.其他插件
Plugin 类作为基类,提供事件支持,可获取播放器引用
可在播放器初始化时传递参数,以及从播放器上获取插件实例
实践我们已经在多个业务中使用 larkplayer,并开发了十几个插件用于解决各种业务需求,支持了千万级/天的视频播放。
larkplayer 及其插件均支持以 script、npm 以及各种模块化的方式引用,你可以怎么舒服怎么来。
larkplayer 使用方式十分简单,将以下代码粘贴到任意编辑器中,用浏览器打开即可运行,更详细的使用文档可以参考这里。
larkplayer quick start
larkplayer 本身已经包含一些基础而核心的功能和机制,比如
功能上,支持 pause()、play()、requestFullscreen()、exitFullscreen()、currentTime(second)(跳转到某一时刻) 等
事件上,可以监听 play、pause、end、error、timeupdate、loadstart、fullscreen 等
更多的功能和事件可以查看 API。
使用插件另外有一些常用但可能不是必须的功能,比如自定义样式、m3u8 文件播放、断点续播等,我们已经提供了一些插件:
larkplayer-ui 提供了一套适应 PC 与 WAP 的皮肤
larkplayer-hls 提供播放 m3u8 文件的功能
larkplayer-vr 提供全景视频播放功能
larkplayer-auto-resume 提供自动续播功能
larkplayer-play-muted 提供静音播放时的 UI
插件的使用也十分简单,只需在 larkplayer 之后引入插件即可。
下面的代码为播放器添加了自定义的样式以及断点续播功能,将其粘贴到任意编辑器,用浏览器打开即可运行。
larkplayer plugin exmaple
larkplayer-ui 插件 能够自适应 PC 与 WAP 展现以下两种样式:
WAP 端样式
PC 端样式
值得一提的是,larkplayer-ui 是一种典型的 UI 类插件,这类插件支持 JSX 语法,书写起来非常方便。比如 WAP 端的样式,在代码中最终就像这样:
controls-mobile.js
import classnames from "classnames"; import {Component, util} from "larkplayer"; import ControlBar from "./control-bar"; import ProgressBarSimple from "./progress-bar-simple"; import Loading from "../component/loading"; import PlayButton from "../component/play-button"; import NotSupport from "../component/not-support"; import Error from "../component/error"; export default class ControlsMobile extends Component { createEl() { return (); } }
如果你有兴趣,也可以自己查看源码。
管理插件larkplayer 的这种设计,使得他可能存在大量的插件,每次调用播放器后面都跟着大量的插件引用会导致重复的代码。这里给出一种解决方案:
1.新建 common/player.js 文件,将 larkplayer 和公用的插件封装在里面,业务上调用 common/player.js 即可
/** * @file 视频播放器,包含 larkplayer 及所有公用插件 */ import larkplayer from "larkplayer"; import "larkplayer-ui"; import "larkplayer-hls"; import "larkplaer-auto-resume"; ... export default larkplayer;
2.对于只在特定场景使用的插件,由于引用次数较少,在对应的场景引用即可
/** * @file VR 视频播放 */ import player from "common/player.js"; import "larkplayer-vr"; const myPlayer = player("video-el"); ...编写插件
以下是 3 类插件的编写示例:
UI 插件编写
MSE 插件编写
普通插件编写
其他 测试采用 karma + jasmine 完成单测编码编写&运行
BrowserStack 提供真机环境用于测试回归
一些示例、思想说明的文档手动编写
API 一类的文档由 nodejs 插件 jsdoc 从代码注释生成
构建采用 grunt 构建,完成模块化、打包、压缩、代码转换等工作。
总览以下是目前整个项目的结构组成
最后,如果你已经看到了这里,不妨到 github 上点个 star 吧,谢谢 :)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/97852.html
摘要:是一款轻量级易扩展的播放器,是为解决一些中小型的视频业务场景。同时各插件由于是面向的播放器接口,插件不知道插件的存在,因此能极大地降低各插件功能间的耦合。 larkplayer 是一款轻量级 & 易扩展的 html5 播放器,是为解决一些中小型的视频业务场景。这些业务不一定需要大而全的解决方案,并且他们往往有自己的定制化需求。 背景 为什么要编写 larkplayer?(注意,这里面有...
摘要:可读性,提高代码的可读性,便于多人的修改维护,提高开发效率。主流浏览器都兼容的新标签,对于及以下版本不认识的新元素,可以使用创建一个没用的元素来解决,例如,也可以使用来解决兼容性问题,详情可参考 概览 showImg(https://segmentfault.com/img/bV5JXT?w=1880&h=1050); 文档章节 导航 表示和主要内容不相关的区域 表示一个独...
摘要:转载来源包管理器管理着库,并提供读取和打包它们的工具。能构建更好应用的客户端包管理器。一个整合和的最佳思想,使开发者能快速方便地组织和编写前端代码的下一代包管理器。很棒的组件集合。隐秘地使用和用户数据。 转载来源:https://github.com/jobbole/aw... 包管理器管理着 javascript 库,并提供读取和打包它们的工具。•npm – npm 是 javasc...
阅读 2846·2021-10-21 09:38
阅读 2752·2021-10-11 10:59
阅读 3025·2021-09-27 13:36
阅读 1652·2021-08-23 09:43
阅读 792·2019-08-29 14:14
阅读 3036·2019-08-29 12:13
阅读 3204·2019-08-29 12:13
阅读 310·2019-08-26 12:24