夏影の博客

[知识分享]在浏览器中调整百度网盘播放速度的尝试

2020年5月15日发布在 知识分享

最近女友使用百度云盘观看学习视频时, 觉得讲师语速太慢, 想调快速度, 然而调速是会员功能. 为了这么一个简单的功能而购买高昂的会员服务, 显然不值得(当然也可以把视频下载下来再用本地播放器倍速, 但又不够方便), 故我做了一番尝试, 最终通过技术手段达成了女友的功能要求. 本文仅做技术研究, 无它, 若有侵犯任何人的权益, 请通过关于页面中的联系方式联系我处理.

当代浏览器已经禁用了 Flash, 故在浏览器中播放视频只能使用 video 标签(若有安装浏览器插件, 则有例外情况, 在此不做讨论), 而调整速度使用 playbackRate API 即可, 原理上来说很简单.

第一次尝试

右键点击播放器, 使用浏览器的审查功能, 快速定位到了 video, 在开发工具的 Console 中执行代码 $0.playbackRate = 2, 视频播放速度加倍, 一切看似OK.

然而进一步完善时, 发现情况没这么简单. 在 Console 中执行代码 document.querySelector('video') 返回为null, 而非一个DOM节点. 通过查找 video 标签所在的父级标签, 发现了如下图所示的 #shadow-root(closed) 标记. 原来视频标签在 Shadow DOM 中, 被隔离开了, 使用JS API还是可以正常访问 Shadow DOM 中内容的. shadowRoot

但意外情况又发生了, 访问Shadow DOM宿主元素的 shadowRoot 时, 又返回的了 null. 这时才留意到 #shadow-root(closed) 标记中的 (closed), 查阅资料后发现: closed 为 ShadowRoot 的 mode, 有 openclosed 两个值: open 表示 ShadowRoot 可以被JS访问, closed 则相反. 于是还需要进一步尝试.

第二次尝试

基于以上情况, 我便考虑如何将 closed 改为 open. ShadowRoot 的 mode 属性为只读属性, 无法直接修改, 于是猜测应当可以通过劫持原生API来实现. 再次阅资料后, 应证了我的猜想. 可以通过劫持 attachShadow 实现, 于是写下了如下代码进行劫持, 并借助浏览器插件 Tampermonkey 完善了一个用户脚本.

const originalAttachShadow = Element.prototype.attachShadow
Element.prototype.attachShadow = function (args) {
    args.mode = 'open'
    return originalAttachShadow.call(this, args)
}

写完用户脚本反复测试时又发现了新状况: 有时候倍速生效, 有时候又不生效 ):- . 进一步猜测是和网络加载速度有关系, 因为执行脚本用户脚本的时视频资源可能还在加载初始化中. 还要继续尝试.

第三次也是最后一次尝试

尝试中, 意外发现若将 Element.prototype.attachShadow = null, 网页不会使用Shadow DOM来创建视频标签了(即视频库做了特性检测, 有fallback方案), 此时可简单快速访问到 video 标签, 于是果断放弃了上述尝试, 最后也无缝完善了本功能.

这里还有两个小点要提一下:

后记

在女友的建议下, 我还给播放器增加了倍速控制按钮, 和网页自带的播放器浑然天成. 也发现了网上有其他更简便的解决方案(均未亲自测验):

  1. 使用最新版火狐浏览器, 在火狐浏览器中右击视频, 即可调整播放速度, 此为浏览器自带功能, 使用方便
  2. 直接在浏览器中执行代码调用播放器使用的视频库 videojs 的API控制速度, 但对不懂代码的人来说, 使用不便且无法随意切换播放速度

我的思路从原生API出发, 更通用(有时候也会更繁琐), 不受浏览器(需要浏览器支持用户脚本, 现代浏览器均已支持)和使用的JS库限制.

标签 浏览器软件
ஓ๑∗๑ஓ