video play util

Universal video control, Control of the first video element of the page, advance and retract and multiply speed.

Versión del día 5/6/2023. Echa un vistazo a la versión más reciente.

  1. // ==UserScript==
  2. // @name video play util
  3. // @namespace https://gist.github.com/zqcccc/32eb827d35b8134f32f9dd3f70d9fb26
  4. // @version 0.0.4
  5. // @description Universal video control, Control of the first video element of the page, advance and retract and multiply speed.
  6. // @author zqcccc
  7. // @match https://www.disneyplus.com/*
  8. // @match https://www.bilibili.com/video/*
  9. // @match https://jable.tv/videos/*
  10. // @match https://dsxys.live/player/*
  11. // @match https://web.telegram.org/k/*
  12. // @match https://www.youtube.com/watch*
  13. // @match https://kaiwu.lagou.com/*
  14. // @match https://ddys.*/*
  15. // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com
  16. // @grant none
  17. // @license MIT
  18. // ==/UserScript==
  19.  
  20. ;(function () {
  21. 'use strict'
  22.  
  23. function getFirstVideo() {
  24. document.documentElement.background = '#fff'
  25. return document.querySelectorAll('video')[0] || window.$0 // chrome 自己指定
  26. }
  27.  
  28. function attachKeydownEvent() {
  29. function addEvent() {
  30. document.documentElement.addEventListener('keydown', keydownHandle)
  31. }
  32. function removeEvent() {
  33. document.documentElement.removeEventListener('keydown', keydownHandle)
  34. }
  35.  
  36. const keydownHandle = (e) => {
  37. const videoElement = getFirstVideo()
  38. if (!videoElement) removeEvent()
  39. switch (e.code) {
  40. case 'Period':
  41. videoElement.currentTime += 1
  42. break
  43. case 'Comma':
  44. videoElement.currentTime -= 2
  45. break
  46. case 'Equal':
  47. videoElement.playbackRate += 0.1
  48. break
  49. case 'Minus':
  50. videoElement.playbackRate -= 0.1
  51. break
  52. default:
  53. break
  54. }
  55. }
  56.  
  57. let hasAddEvent = false
  58. function check() {
  59. const videoElement = getFirstVideo()
  60. if (videoElement) {
  61. hasAddEvent = true
  62. emptyHandles()
  63. addEvent()
  64. }
  65. }
  66.  
  67. let intervalTimes = 0
  68. const timer = setInterval(() => {
  69. if (hasAddEvent || intervalTimes >= 120) {
  70. clearInterval(timer)
  71. } else {
  72. check()
  73. }
  74. intervalTimes++
  75. }, 1000)
  76. return removeEvent
  77. }
  78.  
  79. function observeVideo() {
  80. const v = getFirstVideo()
  81. if (v) {
  82. const ob = new MutationObserver((mutations, observer) => {
  83. mutations.forEach((mut) => {
  84. console.log(
  85. '%c mut: ',
  86. 'font-size:12px;background-color: #553E2E;color:#fff;',
  87. mut
  88. )
  89. if (mut.type === 'attributes' && mut.attributeName === 'src') {
  90. console.log('src changed')
  91. setTimeout(() => {
  92. emptyHandles()
  93. addRemove(attachKeydownEvent())
  94. }, 3000)
  95. }
  96. })
  97. })
  98. ob.observe(v, { attributes: true, attributeOldValue: true })
  99. return () => {
  100. ob.disconnect()
  101. }
  102. } else {
  103. console.log('no video element')
  104. }
  105. }
  106.  
  107. var waitRemoveHandles = []
  108. function emptyHandles() {
  109. for (let i = waitRemoveHandles.length - 1; i >= 0; i--) {
  110. waitRemoveHandles.pop()?.()
  111. }
  112. }
  113.  
  114. function insertPanel() {
  115. document.querySelector('#panel-control')?.remove()
  116.  
  117. const panel = document.createElement('div')
  118.  
  119. panel.style.cssText = `
  120. display: flex;
  121. flex-direction: column;
  122. align-items: center;
  123. justify-content: center;
  124. position: fixed;
  125. z-index: 100;
  126. width: 200px;
  127. height: 200px;
  128. background: rgba(0,0,0,0.4);
  129. color: #fff;
  130. `
  131. panel.style.left = '0'
  132. panel.style.top = '50vh'
  133. panel.draggable = 'true'
  134. panel.setAttribute('id', 'panel-control')
  135.  
  136. panel.innerHTML = `<style>
  137. #panel-control {
  138. opacity: 0.2
  139. }
  140. #panel-control:hover {
  141. opacity: 1
  142. }
  143. #panel-control button {
  144. background: rgba(0,0,0,0.5);
  145. border: none;
  146. color: #fff;
  147. }
  148. #refresh-panel {
  149. user-select: none;
  150. cursor: pointer;
  151. position: absolute;
  152. right: 10px;
  153. top: 10px;
  154. }
  155. </style>
  156. <div class="info"></div>
  157. <button class="get-info">info</button>
  158. <button class="add-speed">speed+0.1</button>
  159. <button class="minus-speed">speed-0.1</button>
  160. <button class="forward">+1s</button>
  161. <button class="backward">-2s</button>
  162. <button id="refresh-panel">↻</button>
  163. `
  164.  
  165. panel.querySelector('.get-info')?.addEventListener('click', () => {
  166. const video = getFirstVideo()
  167. if (video) {
  168. const infoDiv = panel.querySelector('.info')
  169. infoDiv.innerHTML = `rate:${Math.floor(video.playbackRate * 100) / 100}`
  170. }
  171. })
  172. panel.querySelector('.add-speed')?.addEventListener('click', () => {
  173. const video = getFirstVideo()
  174. video && (video.playbackRate += 0.1)
  175. })
  176. panel.querySelector('.minus-speed')?.addEventListener('click', () => {
  177. const video = getFirstVideo()
  178. video && (video.playbackRate -= 0.1)
  179. })
  180. panel.querySelector('.forward')?.addEventListener('click', () => {
  181. const video = getFirstVideo()
  182. video && (video.currentTime += 1)
  183. })
  184. panel.querySelector('.backward')?.addEventListener('click', () => {
  185. const video = getFirstVideo()
  186. video && (video.currentTime -= 2)
  187. })
  188. panel.querySelector('#refresh-panel')?.addEventListener('click', () => {
  189. init()
  190. })
  191.  
  192. let canDrag = false,
  193. lastX,
  194. lastY,
  195. panelLeft,
  196. panelTop
  197.  
  198. panel.addEventListener('dragstart', (e) => {
  199. canDrag = true
  200. lastX = e.pageX
  201. lastY = e.pageY
  202. const rect = panel.getBoundingClientRect()
  203. panelLeft = rect.left
  204. panelTop = rect.top
  205. })
  206. panel.addEventListener('drag', (e) => {
  207. if (canDrag) {
  208. const disX = e.pageX - lastX
  209. panel.style.left = panelLeft + disX + 'px'
  210. const disY = e.pageY - lastY
  211. panel.style.top = panelTop + disY + 'px'
  212. }
  213. })
  214. panel.addEventListener('dragend', () => (canDrag = false))
  215. panel.addEventListener('dragover', function (e) {
  216. e.preventDefault()
  217. })
  218.  
  219. document.documentElement.appendChild(panel)
  220. }
  221.  
  222. function addRemove(fn) {
  223. waitRemoveHandles.push(fn)
  224. }
  225.  
  226. function init() {
  227. emptyHandles()
  228. const cancel = observeVideo()
  229. addRemove(cancel)
  230. insertPanel()
  231. addRemove(attachKeydownEvent())
  232. }
  233.  
  234. init()
  235. })()