文章目录

  • 前序
    • 简介
    • 人群
    • git地址
  • 源码改造(各位客官请自行格式化代码)
    • 实现倍速切换的函数
      • 添加配置参数
      • 添加获取当前倍速的方法
      • 添加切换倍速的函数
    • 参照切换清晰度的代码对控制栏加入倍速播放的节点
      • 复制切换清晰度的代码,并修改点击函数
      • 加入倍速按钮
  • 使用说明
    • 参数说明
    • 增加方法&说明
    • 使用示例
  • 相关推荐

前序

简介

  • 主要介绍了基于tcplayer的源码改造,加入倍速播放功能
  • 不涉及tcplayer的使用以及框架如何调用,详情请看腾讯云点播文档
  • 源码解析中有些注释是笔者加的,如需定位,请不要复制注释
  • 以下示例的代码为重新混淆压缩过,可能与原来的tcplayer.js函数名不同,不可直接复制使用,请务必跟着笔者一步步执行

人群

  • 不想自己写播放器而使用tcplayer,但是又受限于播放器本身不带有倍速播放功能的开发人员
  • 不适合没有任何前端基础的小白,!!请谨慎观看!!

git地址

https://github.com/HaverLee1/hls-player

源码改造(各位客官请自行格式化代码)

实现倍速切换的函数

添加配置参数

在代码中定位videoSource,在第一个的位置,即初始化赋值的同层如下参数(带有注释的则是笔者加入的参数)

      function t(i, o) {n(this, t);var s = l(o);M = ["od", "hd", "sd"];var a = {owner: i,videoSource: s,src: s.curUrl,autoplay: o.autoplay,live: o.live,flash: o.flash,flashUrl: o.flashUrl,poster: o.poster,width: o.width,height: o.height,volume: o.volume,listener: o.listener,wording: o.wording,controls: o.controls,clarity: o.clarity,clarityLabel: o.clarityLabel,showLoading: "boolean" != typeof o.showLoading || o.showLoading,pausePosterEnabled: void 0 === o.pausePosterEnabled || o.pausePosterEnabled,fullscreenEnabled: void 0 === o.fuScrnEnabled || o.fuScrnEnabled,systemFullscreen: o.systemFullscreen || !1,hls: o.hls || "0.12.4",h5_flv: o.h5_flv,x5_player: o.x5_player !== !1,x5_type: o.x5_type,x5_fullscreen: o.x5_fullscreen,x5_orientation: o.x5_orientation,x5_playsinline: o.x5_playsinline,preload: o.preload || "auto",hlsConfig: o.hlsConfig,flvConfig: o.flvConfig,// curRate表示当前倍速curRate: o.curRate ? o.curRate : 1,// rates表示倍速数组rates: o.rates ? o.rates : [2, 1.75, 1.5, 1.25, 1.0, 0.75, 0.5]};return r(this, e.call(this, a))}

添加获取当前倍速的方法

定位"currentTime",可以看到如下代码:

      }, e.prototype.currentTime = function (e) {return this.video.currentTime(e)}

由腾讯视频的官方文档可以知道,currentTime方法是暴露给用户,用于获取/设置当前时间的方法,同理,加入获取当前倍速的方法currentRate:

      }, e.prototype.currentTime = function (e) {return this.video.currentTime(e)}, e.prototype.currentRate = function (e) {return this.video.options.curRate;}

添加切换倍速的函数

定位_switchClarity,找到放置该函数的位置,并加入_switchRate函数:

return s(t, e), t.prototype._switchClarity = function (e) {e = e || "od";var t = this.currentTime(), i = this.options.videoSource, o = c(i.urls, e), n = this.playing();this.load(o.url), i.curUrl = o.url, i.curDef = o.definition, i.curFormat = o.format;var r = A.bind(this, function () {parseInt(this.duration() - t) > 0 && !this.options.live && this.currentTime(t), n && this.play(!0), m.unsub(w.MetaLoaded, "*", r, this)});m.sub(w.MetaLoaded, "*", r, this);// 切换清晰度后依旧保持原有的倍速document.querySelector("video").playbackRate = this.options.curRate;}, t.prototype._switchRate = function (e) {// 自定义的切换倍速的函数e = e || 1;this.options.curRate = e;document.querySelector("video").playbackRate = e;}, t.prototype.switchClarity = function (e) {this.claritySwitcher ? this.claritySwitcher.setClarity(e) : this._switchClarity(e)}, t.prototype.handleMsg = function (t) {e.prototype.handleMsg.call(this, t)}, t

参照切换清晰度的代码对控制栏加入倍速播放的节点

复制切换清晰度的代码,并修改点击函数

考虑到倍速播放的样式与切换清晰度类似(其实就是一样啦),可以定位到切换清晰度的代码,进行复制黏贴.
在chrome中打开开发者工具,定位到视频下方的控制栏中清晰度,可以找到对应的节点vcp-clarityswitcher.

在代码中搜索"vcp-clarityswitcher",会搜索到一些样式和实际添加节点的代码,如下:

        return a(t, e), t.prototype.render = function (t) {this.show = !1, this.createEl("div", {"class": "vcp-clarityswitcher"}), this.current = p.createEl("a", {"class": "vcp-vertical-switcher-current"}), this.container = p.createEl("div", {"class": "vcp-vertical-switcher-container"}), this.items = [], this.currentItem = "";var i = this.options.videoSource;this.current.innerHTML = f[i.curDef], this.el.appendChild(this.current);for (var o = 0; o < i.definitions.length; o++) {var n = p.createEl("a", {"class": "vcp-vertical-switcher-item"});n.innerHTML = f[i.definitions[o]], i.definitions[o] == i.curDef && (p.addClass(n, "current"), this.currentItem = n), n.setAttribute("data-def", i.definitions[o]), this.items.push(n), this.container.appendChild(n)}return this.el.appendChild(this.container), e.prototype.render.call(this, t)}

复制整个function,如下是整个function:

, function (e, t, i) {"use strict";function o(e) {if (e && e.__esModule) return e;var t = {};if (null != e) for (var i in e) Object.prototype.hasOwnProperty.call(e, i) && (t[i] = e[i]);return t["default"] = e, t}function n(e) {return e && e.__esModule ? e : {"default": e}}function r(e, t) {if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function")}function s(e, t) {if (!e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return !t || "object" != typeof t && "function" != typeof t ? e : t}function a(e, t) {if ("function" != typeof t && null !== t) throw new TypeError("Super expression must either be null or a function, not " + typeof t);e.prototype = Object.create(t && t.prototype, {constructor: {value: e,enumerable: !1,writable: !0,configurable: !0}}), t && (Object.setPrototypeOf ? Object.setPrototypeOf(e, t) : e.__proto__ = t)}t.__esModule = !0;var l = i(24), c = n(l), u = i(2), p = o(u), h = i(3), d = o(h), f = {od: "超清", hd: "高清", sd: "标清"},y = function (e) {function t(i) {r(this, t);var o = s(this, e.call(this, i, "ClaritySwitcher"));return f = d.extend({}, i.options.clarityLabel, f), i.claritySwitcher = o, o}return a(t, e), t.prototype.render = function (t) {this.show = !1, this.createEl("div", {"class": "vcp-clarityswitcher"}), this.current = p.createEl("a", {"class": "vcp-vertical-switcher-current"}), this.container = p.createEl("div", {"class": "vcp-vertical-switcher-container"}), this.items = [], this.currentItem = "";var i = this.options.videoSource;this.current.innerHTML = f[i.curDef], this.el.appendChild(this.current);for (var o = 0; o < i.definitions.length; o++) {var n = p.createEl("a", {"class": "vcp-vertical-switcher-item"});n.innerHTML = f[i.definitions[o]], i.definitions[o] == i.curDef && (p.addClass(n, "current"), this.currentItem = n), n.setAttribute("data-def", i.definitions[o]), this.items.push(n), this.container.appendChild(n)}return this.el.appendChild(this.container), e.prototype.render.call(this, t)}, t.prototype.setup = function () {this.on("click", this.onClick), this.on("mouseenter", this.onMouseEnter), this.on("mouseleave", this.onMouseLeave)}, t.prototype.onClick = function (e) {var t = e.target.getAttribute("data-def");t ? (this.current.innerHTML = f[t], p.removeClass(this.currentItem, "current"), p.addClass(e.target, "current"), this.currentItem = e.target, this.player._switchClarity(t)) : !this.show}, t.prototype.onMouseLeave = function () {this.container.style.display = "none", this.show = !1}, t.prototype.onMouseEnter = function () {this.container.style.display = "block", this.show = !0}, t.prototype.setClarity = function (e) {e && (this.current.innerHTML = f[e], p.removeClass(document.querySelector(".vcp-vertical-switcher-item.current"), "current"), p.addClass(document.querySelector('.vcp-vertical-switcher-item[data-def="' + e + '"]'), "current"), this.currentItem = document.querySelector('.vcp-vertical-switcher-item[data-def="' + e + '"]'), this.player._switchClarity(e))}, t}(c["default"]);t["default"] = y}

黏贴到同层级的最下方,代码拉到最下方,在下图鼠标光标所在位置黏贴:

再改动绑定的数据

// 删除了原有的f这个数组var l = i(24), c = n(l), u = i(2), p = o(u), h = i(3), d = o(h),y = function (e) {function t(i) {return r(this, t), s(this, e.call(this, i, "ClaritySwitcher"))}return a(t, e), t.prototype.render = function (t) {this.show = !1, this.createEl("div", {"class": "vcp-clarityswitcher"}), this.current = p.createEl("a", {"class": "vcp-vertical-switcher-current"}), this.container = p.createEl("div", {"class": "vcp-vertical-switcher-container"}), this.items = [], this.currentItem = "";// curRate为配置中的当前倍速 rates为倍速数组var i = this.options.curRate, f = this.options.rates;this.current.innerHTML = f[i], this.el.appendChild(this.current);for (var o = 0; o < f.length; o++) {var n = p.createEl("a", {"class": "vcp-vertical-switcher-item"});n.innerHTML = f[o], f[o] == i && (p.addClass(n, "current"), this.currentItem = n), n.setAttribute("data-def", o), this.items.push(n), this.container.appendChild(n)}return this.el.appendChild(this.container), e.prototype.render.call(this, t)}, t.prototype.setup = function () {// 在初始化时加入修改倍速函数_switchRate,切换到当前倍速this.player._switchRate(this.options.curRate), this.on("click", this.onClick), this.on("mouseenter", this.onMouseEnter), this.on("mouseleave", this.onMouseLeave)}, t.prototype.onClick = function (e) {var t = e.target.getAttribute("data-def"),f = this.options.rates;// 修改点击函数,将_switchClarity改为自定义的_switchRatet ? (this.current.innerHTML = f[t], p.removeClass(this.currentItem, "current"), p.addClass(e.target, "current"), this.currentItem = e.target, this.player._switchRate(f[t])) : !this.show}, t.prototype.onMouseLeave = function () {this.container.style.display = "none", this.show = !1}, t.prototype.onMouseEnter = function () {this.container.style.display = "block", this.show = !0}// 去除了无效的setClarity函数,也可不去,对功能无影响,只是代码洁癖, t}

加入倍速按钮

在chrome中打开开发者工具,定位到视频下方的控制栏,可以找到对应的节点"vcp-controls-panel".

在代码中搜索"vcp-controls-panel",会搜索到一些样式和实际添加节点的代码,如下:

    t.__esModule = !0;var l = i(24), c = n(l), u = i(28), p = n(u), h = i(29), d = n(h), f = i(30), y = i(31), A = n(y), v = i(32),m = n(v), g = i(33), w = n(g), b = i(34), M = n(b), I = i(4), S = i(2), E = o(S), _ = i(3), T = o(_), D = i(1),L = o(D), O = function (e) {function t(i) {return r(this, t), s(this, e.call(this, i, "Panel"))}return a(t, e), t.prototype.render = function (t) {return this.createEl("div", {"class": "vcp-controls-panel"}), this.el.appendChild(E.createEl("div", {"class": "vcp-panel-bg"})), this.playToggle = new p["default"](this.player), this.playToggle.render(this.el), this.timelabel = new m["default"](this.player), this.timelabel.render(this.el), this.timeline = new A["default"](this.player), this.timeline.render(this.el), this.options.fullscreenEnabled === !0 && (this.fullscreen = new d["default"](this.player), this.fullscreen.render(this.el)), L.IS_MOBILE || (this.volume = new w["default"](this.player), this.volume.render(this.el)), this.options.videoSource && this.options.videoSource.definitions.length > 1 && !L.IS_MOBILE && (this.claritySwitcher = new M["default"](this.player), this.claritySwitcher.render(this.el)), e.prototype.render.call(this, t)}

将其改为:

    t.__esModule = !0;// i为对应的esmodule,M["default"]表示n[i(34)]个,即分辨率是第34个function,相应的,我们将倍速的放在最后,就是第40个var l = i(24), c = n(l), u = i(28), p = n(u), h = i(29), d = n(h), f = i(30), y = i(31), A = n(y), v = i(32),m = n(v), g = i(33), w = n(g), b = i(34), M = n(b), I = i(4), S = i(2), E = o(S), _ = i(3), T = o(_), D = i(1),L = o(D), rate = i(40), Rate = n(rate), O = function (e) {function t(i) {return r(this, t), s(this, e.call(this, i, "Panel"))}return a(t, e), t.prototype.render = function (t) {// 加入倍速节点,由于现有的手机浏览器都支持倍速,所以去掉了手机端判断return this.createEl("div", {"class": "vcp-controls-panel"}), this.el.appendChild(E.createEl("div", {"class": "vcp-panel-bg"})), this.playToggle = new p["default"](this.player), this.playToggle.render(this.el), this.timelabel = new m["default"](this.player), this.timelabel.render(this.el), this.timeline = new A["default"](this.player), this.timeline.render(this.el), this.options.fullscreenEnabled === !0 && (this.fullscreen = new d["default"](this.player), this.fullscreen.render(this.el)), L.IS_MOBILE || (this.volume = new w["default"](this.player), this.volume.render(this.el)), this.options.videoSource && this.options.videoSource.definitions.length > 1 && (this.claritySwitcher = new M["default"](this.player), this.claritySwitcher.render(this.el)) && (this.rateSwitcher = new Rate["default"](this.player), this.rateSwitcher.render(this.el)), e.prototype.render.call(this, t)}

使用说明

使用时请先压缩js文件

参数说明

在原有播放器支持的参数下添加了两个参数

参数 类型 默认值 参数说明
rates Array [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5] 倍速数组
curRate Number 1 默认倍速

增加方法&说明

方法 参数 返回值 说明 示例
currentRate() {int} 获取当前的倍速 player.currentRate()

使用示例

var player = new TcPlayer('id_test_video', {"m3u8": "http://2157.liveplay.myqcloud.com/2157_358535a.m3u8", //请替换成实际可用的播放地址"autoplay" : true,      //iOS 下 safari 浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的"poster" : "http://www.test.com/myimage.jpg","width" :  '480',//视频的显示宽度,请尽量使用视频分辨率宽度"height" : '320'//视频的显示高度,请尽量使用视频分辨率高度"rates": [2, 1.5, 1, 0.5],"curRate": '1'
});

相关推荐

  • tcplayer源码改造第一弹 -> 自定义hls加密播放器
  • tcplayer源码改造第二弹 -> 加入倍速播放
  • tcplayer源码改造第三弹 -> 防盗录
  • tcplayer 源码改造第四弹 -> 字幕(srt)
  • tcplayer源码改造第五弹 -> 兼容sarafi/遨游

tcplayer 源码改造第二弹 - 加入倍速播放相关推荐

  1. tcplayer 源码改造第三弹 - 防盗录

    文章目录 前序 简介 人群 git地址 源码改造tcplayer.js(各位客官请自行格式化代码) 修改思路 添加配置参数 添加防盗录的节点 添加防盗录的节点样式 使用说明 参数说明 使用示例 相关推 ...

  2. hdfs源码分析第二弹

    以写文件为例,串联整个流程的源码: FSDataOutputStream out = fs.create(outFile); 1. DistributedFileSystem 继承并实现了FileSy ...

  3. 2021苹果CMS安卓萝卜视频原生影视APP源码支持投屏选集倍速弹幕版(前端二开美化版)

    苹果CMS原生萝卜影视4.2源码APP前端源码(炫彩白) 介绍:萝卜视频为全原生(并不是所谓的跨平台半原生请知晓)安卓:JAVA,后端用的是二次开发的苹果CMS,支持局域网投屏,视频软解硬解,播放器自 ...

  4. Springboot源码分析第一弹 - 自动装配实现

    Springboot就不用多了吧,解放Java开发双手的神器. 最显著的特点就是,去配置化,自动装配,自动配置.让开发人员只需要注重业务的开发 今天就来了解一下自动装配的源码是怎么实现的 预先准备 直 ...

  5. 深入理解Tomcat和Jetty源码之第二篇servlet规范和servlet容器

    深入理解Tomcat和Jetty源码之第二篇servlet规范和servlet容器 思维导图总览 这篇推送主要讲servlet的规范和什么是servlet容器? 1.先来讲讲servlet规范: 2. ...

  6. 2020-10-19。小白自学:飞机大战源码改造。(新手入门,学习总结。从零开始,步步为营。不同版本,独立运行。完整代码,感谢原著。)

    #简介: #小白自学:飞机大战源码改造.(新手入门,学习总结.) #从零开始:完全重写代码框架.(步步为营,完整代码.) #简单就好:删除各种自定函数.(讨厌函数跳转,喜欢层次分明.) #文本归一:方 ...

  7. Apollo+ES源码改造,构建民生银行的ELK日志平台配置管理中心【转载】

    Apollo+ES源码改造,构建民生银行的ELK日志平台配置管理中心 原创 高效开发运维 架构头条 2019-02-28 作者 | 中国民生银行大数据基础平台运维组团队 编辑 | 张婵 随着 IT 业 ...

  8. Apollo+ES源码改造,构建民生银行的ELK日志平台配置管理中心

    作者 | 中国民生银行大数据基础平台运维组团队 编辑 | 张婵 随着 IT 业务系统的迅速发展,中国民生银行需要考虑实现一套完整并适用于民生银行的日志文件智能分析与处理的解决方案.本文详细介绍了中国民 ...

  9. ffplay使用ffmpeg滤镜实现倍速播放

    第一章 自定义播放器接口 第二章 倍速播放(本章) ______第一节 sonic实现倍速播放 ______第二节 soundtouch实现倍速播放 ______第三节 ffmpeg滤镜实现倍速播放( ...

最新文章

  1. The RAII Programming Idiom
  2. 你知道CSS实现水平垂直居中的第10种方式吗?
  3. C++前缀++/–比后缀++/–的效率高
  4. location.search
  5. 2.PHP利用PDO连接方式连接mysql数据库
  6. 关于Vmware ESX 4.1添加第二个Servier Console 却无法添加网关的解决方法
  7. php软件开发--yii2框架搭建及gitlib同步线上网站
  8. java中的getinstance_Java中的KeyPairGenerator getInstance()方法
  9. 混沌工程(Chaos Engineering) 到底是什么?
  10. 使用 cookie的一些缺陷和隐患
  11. Microsoft Visual SourceSafe 2005 服务端安装配置过程以及出现的问题,以及解决方法!...
  12. Uva_156 Ananagrams ( map 的应用 )
  13. vsftpd命令详解
  14. 解决用电脑连接宽带给手机开热点的问题
  15. Python学习笔记字典之检查字典中是否存在键或值
  16. vue range 双向滚动 取中间值
  17. 电赛小车常用硬件解析(蓝牙遥控,循迹)
  18. Mysql添加用户设置权限
  19. Muduo日志系统介绍
  20. 未明学院:量化训练营,帮我拿下新加坡国立大学定量金融offer!

热门文章

  1. linux 虚拟地址空间在哪,Linux虚拟地址空间
  2. 微信开发者工具更新版本后,模拟器显示与真机不一致
  3. galeracluster高可用集群异常恢复
  4. 二叉树 度数和阶数的定义与区别
  5. Delphi调用腾讯云最新签名方法v3 TC3-HMAC-SHA256发送短信
  6. 超详细的Thymeleaf语法入门教程
  7. SPWM的单极性和双极性
  8. 2022年最新《谷粒学院开发教程》:4 - 课程管理
  9. swift 【block】
  10. 如何在iPhone或iPad上使用Google进行Safari搜索