Greasy Fork镜像 支持简体中文。

哔哩哔哩大会员视频替换

此脚本会替换掉原本的播放器,然后匹配相关资源并播放,支持部分港澳台。同时提供视频和弹幕下载。

  1. // ==UserScript==
  2. // @name 哔哩哔哩大会员视频替换
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.17
  5. // @description 此脚本会替换掉原本的播放器,然后匹配相关资源并播放,支持部分港澳台。同时提供视频和弹幕下载。
  6. // @author coldrainf
  7. // @grant unsafeWindow
  8. // @connect bilivideo.com
  9. // @include https://www.bilibili.com/bangumi/play/*
  10. // @include https://www.bilibili.com/video/BV*
  11. // @require https://gf.qytechs.cn/scripts/402897-bilibili-ass-danmaku-downloader-by-%E7%94%B0%E7%94%9F/code/bilibili%20ASS%20Danmaku%20Downloader%20by%20%E7%94%B0%E7%94%9F.js?version=802822
  12. // ==/UserScript==
  13. (function() {
  14. 'use strict';
  15. let dloading = false
  16. let bangumi = /bilibili.com\/bangumi\/play\//g.test(window.location.href)
  17. let parentId = bangumi ? 'toolbar_module' : 'arc_toolbar_report'
  18. //添加样式
  19. let style = document.createElement("style")
  20. style.innerHTML =(".coldrainf-get-dm{float:right;}.coldrainf-get-dm>div{display:inline-block;}.coldrainf-get-dm a{font-size:15px;color:#00a1d6;margin:0 12px;line-height:28px;}.coldrainf-get-dm a:hover{cursor:pointer;color:#f25d8e;}")
  21. document.head.appendChild(style)
  22. if(bangumi && unsafeWindow.__PGC_USERSTATE__.area_limit != 0) Object.defineProperty(unsafeWindow, '__PGC_USERSTATE__', {get: () => ({area_limit:0, gat: true})})
  23. //添加按钮
  24. let addElement = cid => {
  25. let name = document.title.match(/(.+?)_((.+?)_|哔哩哔哩 )/)[1]
  26. let title = bangumi ? unsafeWindow.__INITIAL_STATE__.mediaInfo.title : name
  27. let parent = document.getElementById(parentId)
  28. let old = document.querySelector('.coldrainf-get-dm')
  29. if(old) parent.removeChild(old)
  30. let ele = document.createElement("div")
  31. ele.className = 'coldrainf-get-dm'
  32. let dm = document.createElement("a")
  33. dm.href = "https://api.bilibili.com/x/v1/dm/list.so?oid=" + cid
  34. dm.textContent = "下载弹幕"
  35. dm.addEventListener('click',e => {
  36. fetch("https://api.bilibili.com/x/v1/dm/list.so?oid="+cid).then(res=>res.text()).then(text => {
  37. let danmaku = parseXML(text.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/g, ''));
  38. let ass = generateASS(setPosition(danmaku), {
  39. 'title': name,
  40. 'ori': name,
  41. })
  42. startDownload('\ufeff' + ass, name + '.ass');
  43. })
  44. if(e.preventDefault) e.preventDefault()
  45. else window.event.returnValue == false
  46. })
  47. let iframeTmp = document.querySelector('#coldrainf-iframe')
  48. if(iframeTmp) document.querySelector('.plp-l').removeChild(iframeTmp)
  49. let bfq = document.getElementById('player_module')
  50. if(bfq) bfq.style.display = 'block'
  51. let jump = document.createElement("a")
  52.  
  53. if(bangumi && (unsafeWindow.__INITIAL_STATE__.epPayMent.status != 0 || unsafeWindow.__PGC_USERSTATE__.gat)) {
  54.  
  55. let iframe = document.createElement("iframe")
  56. iframe.id = 'coldrainf-iframe'
  57. iframe.src = `https://dm.coldrain.top/?dm=${cid}&wd=${title.slice(0,13)}&ep=${unsafeWindow.__INITIAL_STATE__.epInfo.i + 1}`
  58. if(document.body.className.includes('player-mode-widescreen')) {
  59. iframe.style.position = 'absolute'
  60. iframe.style.top = '0'
  61. }
  62. iframe.height = 0
  63. iframe.width = '100%'
  64. iframe.setAttribute('frameborder','no')
  65. iframe.setAttribute('border','0')
  66. iframe.setAttribute('allowfullscreen','allowfullscreen')
  67. iframe.setAttribute('webkitallowfullscreen','webkitallowfullscreen')
  68. document.querySelector('.plp-l').insertBefore(iframe,bfq)
  69.  
  70. /*
  71. //自动替换,但有时需要和原片比对时间轴,所以不用
  72. if(unsafeWindow.player) unsafeWindow.player.pause()
  73. if(bfq.style.display != 'none') {
  74. iframe.height = bfq.clientHeight
  75. bfq.style.display = 'none'
  76. }
  77. */
  78.  
  79. //手动点击
  80. jump.textContent = "替换播放器"
  81. jump.onclick = e => {
  82. if(unsafeWindow.player) unsafeWindow.player.pause()
  83. if(bfq.style.display == 'none') return
  84. iframe.height = bfq.style.height
  85. window.onresize = () => {
  86. iframe.style.height = bfq.style.height
  87. }
  88. bfq.style.display = 'none'
  89. }
  90.  
  91. }
  92. let video = document.createElement("a")
  93. if(!bangumi || unsafeWindow.__INITIAL_STATE__.epPayMent.status == 0) {
  94. (async () => {
  95. video = document.createElement("div")
  96. let select = document.createElement("select"),
  97. aid = bangumi ? unsafeWindow.__INITIAL_STATE__.epInfo.aid : unsafeWindow.__INITIAL_STATE__.aid,
  98. api = `https://api.bilibili.com/x/player/playurl?cid=${cid}&avid=${aid}`,
  99. res0 = await fetch(api,{credentials: 'include'}),
  100. json = await res0.json()
  101. if(!json.data) return
  102. select.value = json.data.accept_quality[0]
  103. for(let i in json.data.accept_quality) {
  104. if((!bangumi || !unsafeWindow.__INITIAL_STATE__.loginInfo.isVip) && json.data.accept_quality[i] == '112') {
  105. select.value = json.data.accept_quality[1]
  106. continue
  107. }
  108. let option = document.createElement("option")
  109. option.value = json.data.accept_quality[i]
  110. option.textContent = json.data.accept_description[i]
  111. select.appendChild(option)
  112. }
  113.  
  114. video.appendChild(select)
  115. let dl = document.createElement("a")
  116. dl.textContent = "下载视频"
  117. dl.addEventListener('click', e => {
  118. if(e.preventDefault) e.preventDefault()
  119. else window.event.returnValue == false
  120. if(dloading) return
  121. dloading = true;
  122. (async () => {
  123. let res1 = await fetch(`${api}&qn=${select.value}`,{credentials: 'include'}),
  124. json1 = await res1.json(),
  125. url = json1.data.durl[0].url.replace('http','https')
  126.  
  127. let res = await fetch(url,{headers:{'Referer':'https://www.bilibili.com/'}}),
  128. loaded = 0, chunks = []
  129. const reader = res.body.getReader(), total = +res.headers.get('Content-Length');
  130. select.style.display = 'none'
  131. while(true) {
  132. const {done, value} = await reader.read()
  133. if(done) break
  134. chunks.push(value)
  135. loaded += value.length
  136. dl.textContent = `${(loaded/1024/1024).toFixed(2)}M/${(total/1024/1024).toFixed(2)}M`
  137. }
  138. select.style.display = 'inline'
  139. dl.textContent = "下载视频"
  140. dloading = false
  141. let hz = /\.flv\?/.test(url) ? '.flv' : '.mp4'
  142. startDownload(new Blob(chunks), name+hz)
  143. })()
  144. })
  145. video.appendChild(dl)
  146. })()
  147.  
  148. }else video.textContent = "无法下载视频"
  149. /*
  150. if(!bangumi) {
  151. video.textContent = "下载视频"
  152. video.target = '_blank'
  153. let api = 'https://www.xbeibeix.com/api/bilibiliapi.php?url=https://www.bilibili.com/&aid='+aid+'&cid='+cid
  154. GM_xmlhttpRequest({method: "get", url: api,onload(res){
  155. if(res.status != 200) return
  156. let json = JSON.parse(res.responseText)
  157. video.href = json.url
  158. },
  159. });
  160. }
  161. */
  162. ele.appendChild(video)
  163. ele.appendChild(dm)
  164. ele.appendChild(jump)
  165. parent.appendChild(ele)
  166. }
  167. //添加换p事件
  168. let href = window.location.href
  169. let changeEp = () => {
  170. let eles = bangumi ? document.querySelectorAll('.plp-r') : document.querySelectorAll('.list-box li')
  171. if(!eles) return
  172. eles.forEach(ele => {
  173. ele.addEventListener('click',e => {
  174. setTimeout(()=>{
  175. if(window.location.href == href) return
  176. href = window.location.href
  177. document.getElementById(parentId).removeChild(document.querySelector('.coldrainf-get-dm'))
  178. addElement(getCid())
  179. },200)
  180. })
  181. })
  182. }
  183. //获取cid
  184. let getCid = () => {
  185. if(bangumi) return unsafeWindow.__INITIAL_STATE__.epInfo.cid
  186. else return cid
  187. }
  188. let init = () => {
  189. addElement(getCid())
  190. changeEp()
  191. }
  192. let obs = bangumi ? document.querySelector('#toolbar_module') : document.querySelector('.ops')
  193. if(!obs) setTimeout(init,500)
  194. else{
  195. new MutationObserver(function (mutations, observer) {
  196. observer.disconnect();
  197. setTimeout(init,500)
  198. }).observe(obs, {childList: true, subtree: true});
  199. }
  200. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址