Greasy Fork

Greasy Fork is available in English.

解锁b站vip视频+弹幕移植

功能很少有缺陷,先看粗体字再决定是否要安装。解除B站大会员观影限制,理论支持番剧和放映厅,不支持的视频请反馈留地址让我修复,或自行在代码搜索‘大会员’并添加识别div与语句。

当前为 2021-07-04 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         解锁b站vip视频+弹幕移植
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACS0lEQVRYR8WXz2oTURTGv3MnpqhNKy1UWmxRTGdaiLSQRKkKIoK4FVrRPoHu7BMYn0B3+gQquuiuiC6kaFVsAhGEZkKqG/+Vrtp0YWsyR27KlEwz0xnnT3LgwjB37vl+97tzz9whdDiow/pwBCjofN0AJohwKQgkMxYF8Dmt0bxdnhaAQoWTXMczENJBhFvGMgqk4GY6SZXmPgvAmy/cnYijGqrwvmTVHSQup2jLvG0ByJf5EYDbUQIAeJxR6U4LQHGV1VodesTijfQxBdrkaSrL6z0Hlst8i4An7QBgYDar0lMrgM45ItxrCwDjflajnC+AtR8Gvn8zGpz9xwVOjor/Zma/ANt/GIsLNWxt8p7o4IiAmlLQP+C9pvkG+FoyUPxYs52xhFDPKIh3uRviG2ClWIdsTpHoJYymFNdliQzABBsaEZg4p+DwUftliRxAggwOC0xdidma1RaAI92Ea9OHOgcwPqlANruI1AElhsa2dBKXQJEBnDglGlvxWN/BNcE3gKyCS69b64AUlMISwEv4BpDJ3778i/Xfu5XQtFtaLq+9RiCA6gZj/dcuQN8Audod6kvodYZuz9k7UOK7JPDAbXAY/WxgLjtGDy2f408VPi8MLIUh4JbDELhwNknvLQDyQNoTh87AkFuCIP0E/NzcgWYeTC0bdrkNp6Lm9bc4YM4qr/NzEGaCzNJxLONFRqMbzf22JSu/wlcphhwzpsIAIcIHriGXGadX+/MdWDPflTjRxcH+kLYJhYtj5Piz4/0gF4YVNjk6DvAPDb0aMEr8/nEAAAAASUVORK5CYII=    
// @version      1.11.7
// @description  功能很少有缺陷,先看粗体字再决定是否要安装。解除B站大会员观影限制,理论支持番剧和放映厅,不支持的视频请反馈留地址让我修复,或自行在代码搜索‘大会员’并添加识别div与语句。
// @author       p7
// @require      https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js
// @match        https://www.bilibili.com/bangumi/*
// @match        https://vip.parwix.com:4433/*
// @match        https://z1.m1907.cn/*
// @match        https://api.yueliangjx.com/*
// @match        https://showxi.xyz/*
// @match        https://okjx.cc/*
// @run-at       document-end
// @grant        GM_openInTab
// @grant        GM.openInTab
// @grant        GM_getValue
// @grant        GM.getValue
// @grant        GM_setValue
// @grant        GM.setValue
// @grant        GM_addStyle
// @namespace    http://greasyfork.icu/users/789132
// ==/UserScript==
(function () {
  /*1.11.6 mod区域*/
  let originalInterfaceList = [{
    "name": "Parwix",
    "category": "1",
    "url": "https://vip.parwix.com:4433/player/?url="
  },
  {
    "name": "m1907",
    "category": "1",
    "url": "https://z1.m1907.cn/?jx="
  },
  {
    "name": "月亮[不稳]",
    "category": "1",
    "url": "https://api.yueliangjx.com/?url="
  },
  {
    "name": "showxi[多线]",
    "category": "1",
    "url": "https://showxi.xyz/mov/s/?sv=3&url="
  },
  {
    "name": "OK[多线]",
    "category": "1",
    "url": "https://okjx.cc/?url="
  },
  ];

  let repeatp = 0 //去重概率[0-100]
  /*mod区域结束*/

  var player
  var playerRect
  var minpool = [];
  var domPool = [];
  var domtopdownPool = [];
  var listobj
  //1.11.6修复弹幕重复问题
  let minpoolout = [];
  let lastvideotime = 0;
  //1.11.7全屏问题
  //let lastplaywidth = 0;

  var distance = 25
  var fontSize = 25;
  var buiSwitch = true;
  console.log(1, window.location.href)

  function xmlToJson(xml) {

    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) { // element
      // do attributes
      if (xml.attributes.length > 0) {
        obj["@attributes"] = {};
        for (var j = 0; j < xml.attributes.length; j++) {
          var attribute = xml.attributes.item(j);
          obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
        }
      }
    } else if (xml.nodeType == 3) { // text
      obj = xml.nodeValue;
    }

    // do children
    if (xml.hasChildNodes()) {
      for (var i = 0; i < xml.childNodes.length; i++) {
        var item = xml.childNodes.item(i);
        var nodeName = item.nodeName;
        if (typeof (obj[nodeName]) == "undefined") {
          obj[nodeName] = xmlToJson(item);
        } else {
          if (typeof (obj[nodeName].push) == "undefined") {
            var old = obj[nodeName];
            obj[nodeName] = [];
            obj[nodeName].push(old);
          }
          obj[nodeName].push(xmlToJson(item));
        }
      }
    }
    return obj;
  };
  //1.11.7 稳定发送
  function postdownmessage(obj) {
    for (var posta = 0; posta <= 3; posta++) {
      try { window.frames[posta].postMessage(obj, '*'); } catch { }
      for (var postb = 0; postb <= 3; postb++) {
        try { window.frames[posta].frames[postb].postMessage(obj, '*'); } catch { }
        for (var postc = 0; postc <= 3; postc++) {
          try { window.frames[posta].frames[postb].frames[postc].postMessage(obj, '*'); } catch { }
        }
      }
    }
  }
  function getBV() {
    let bv = $("a.av-link[target='_blank']")[0]
    if (bv) {
      //console.log(bv.innerText);
      $.getJSON("https://api.bilibili.com/x/player/pagelist?bvid=" + bv.innerText,
        function (result) {

          var xmlhtml = `https://api.bilibili.com/x/v1/dm/list.so?oid=${result.data[0].cid}`
          //ajax解析xml文件
          console.log(xmlhtml);
          $.ajax({
            url: xmlhtml,
            dataType: "xml",
            success: function (xml) {
              //console.log('xmllist', xmlToJson(xml));
              let listjson = xmlToJson(xml)
              //console.log($('.bilibili-player-video-info-danmaku-number'), listjson.i.d.length)
              $('.bilibili-player-video-info-danmaku-number').text(listjson.i.d.length)
              //console.log(window.frames.length, listjson.i.d.length);
              postdownmessage({
                obj: listjson,
                str: 'xmllist'
              }) 
            }

          })
        })

    } else {
      setTimeout(function () {
        getBV()
      },
        500)
    }
  }

  function receiveInfoFromAnotherDomain() {
    //首先让window添加一个事件监听函数,表明它可以监听窗口对象的message事件 
    //它受到事件时,会先判断是否来自指定的Domain(不是所有Domain丢过来的事件它都处理的) 
    window.addEventListener("message",
      function (ev) {
        switch (window.location.host) {
          case 'www.bilibili.com':
            if (ev.origin != 'https://www.bilibili.com' && ev.origin != 'https://message.bilibili.com') {
              console.log(ev.origin, ' message to', window.location.href, ev.data);
              if (ev.data.str == 'hasplayer') {
                getBV()
              }
            }
            break
          default:
            window.top.postMessage({
              fromweb: window.location.href,
              obj: ev.data,
              str: '来自iframe:',
              from: ev.origin
            },
              '*');
            switch (ev.data.str) {
              case 'xmllist':
                listobj = ev.data.obj;
                break;
              case 'checktrue':
                buiSwitch = true;
                break;
              case 'checkfalse':
                buiSwitch = false;
                break;
            }

        }
      })
    window.top.postMessage({
      fromweb: window.location.href,
      obj: 'iframe监听初始化',
      str: '来自iframe:',
    },
      '*');
  }

  function detecH5Player(findplayertime) {

    player = document.querySelector('video');
    if (player) {
      //console.log(window.location.href+'发现h5')
      receiveInfoFromAnotherDomain();
      window.top.postMessage({
        str: 'hasplayer',
        fromweb: window.location.href
      },
        '*');
      playerRect = player.getBoundingClientRect();
      initcss();

      player.addEventListener('pause',
        function () { //暂停开始执行的函数
          $('.left').each(function (index, element) {
            element.style.willChange = 'auto'
            let domRect = element.getBoundingClientRect();
            let domLeft = domRect.left - playerRect.left;
            $(element).css('transform', `translateX(${domLeft}px)`);
            //element.style.left = `${domLeft}px`
            $(element).css('transition', `transform 0s linear`);

          })
        });
      //1.11.7
      document.addEventListener("fullscreenchange", function (e) {
        refreshDom()//player.clientWidth-lastplaywidth
      })
      //lastplaywidth = player.clientWidth
      player.addEventListener('playing',
        function () { //暂停开始执行的函数
          playtime = (new Date()).getTime()
          $('.left').each(function (index, element) {
            let domRect = element.getBoundingClientRect()
            let domLeft = domRect.left - playerRect.left
            let oldS = element.clientWidth + player.clientWidth
            let newS = element.clientWidth + domLeft
            let oldT = 0.0074 * (element.clientWidth + player.clientWidth)
            let newT = newS / oldS * oldT
            //console.log(element.clientWidth+','+player.clientWidth+','+oldS+','+newS+','+oldT+','+newT)
            $(element).css('transition', `transform ${newT}s linear`);
            $(element).addClass('left');

            element.style.willChange = 'transform'
            element.style.transform = `translateX(${-element.clientWidth - newS}px)`;

          })
        });
      player.addEventListener('timeupdate',
        function () {
          //1.11.6 修复弹幕重复、前进后退清屏、后退重载弹幕
          let lastlen = parseInt(lastvideotime / 60)
          let startlen = parseInt(player.currentTime / 60)
          if (lastvideotime > player.currentTime) {
            for (var c = startlen; c <= lastlen; c++) {
              if (minpoolout[c].length != 0) {
                minpool[c] = minpool[c].concat(minpoolout[c])
                minpoolout[c].length = 0
              }
            }
            refreshDomscreen()
          } else if (lastvideotime + 2 < player.currentTime) {
            refreshDomscreen()
          }
          lastvideotime = player.currentTime
          if (minpool.length == 0 && listobj) {
            minpool = new Array(parseInt(player.duration / 60));
            let minlen = minpool.length
            for (var a = 0; a <= minlen; a++) {
              minpool[a] = []
            }
            minpoolout = new Array(minlen);
            for (var b = 0; b <= minlen; b++) {
              minpoolout[b] = []
            }
            let len = listobj.i.d.length
            //window.top.postMessage({obj:'listobj.i.d.length:'+listobj.i.d.length,str:'来自iframe:',from:window.location.href},'*');
            for (var j = 0; j < len; j++) {
              let strp = listobj.i.d[j]['@attributes'].p
              let arrp = strp.split(',');
              let arrpJson = {
                "time": arrp[0],
                "type": arrp[1],
                "size": arrp[2],
                "rgb": arrp[3],
                "pool": arrp[5],
                "text": listobj.i.d[j]['#text']
              };
              if (repeatp == 100 || repeatp > Math.floor(Math.random() * 100)) {
                let len2 = minpool[parseInt(arrp[0] / 60)].length
                let needpush = true
                for (var i = 0; i < len2; i++) {
                  if (minpool[parseInt(arrp[0] / 60)][i].text == arrpJson.text) {
                    needpush = false;
                    break;
                  }
                }
                if (needpush == true) {
                  minpool[parseInt(arrp[0] / 60)].push(arrpJson);
                }
              } else {
                minpool[parseInt(arrp[0] / 60)].push(arrpJson);
              }
              /*window.top.postMessage({
                obj: 'minpool push:' + minpool[parseInt(arrp[0] / 60)][minpool[parseInt(arrp[0] / 60)].length - 1],
                str: '来自iframe:',
                from: window.location.href
              }, '*');*/
            }
          }
          //window.top.postMessage({obj:'currentTime:'+player.currentTime+'  '+minpool.length+'  '+domPool.length,str:'来自iframe:',from:window.location.href},'*');  
          $('.topdown').each(function (index, element) {
            if (element.innerText != '') {
              let nowtime = (new Date()).getTime();
              let lasttime = parseInt(nowtime) - parseInt($(element).prop("name"))
              //console.log('lasttime:'+lasttime+' '+typeof lasttime);
              if (lasttime >= 4500) {
                //console.log('lasttime2:'+lasttime+' '+typeof lasttime);
                element.innerText = ''
                element.name = ''
              }
            }
          });
          //window.top.postMessage({obj:buiSwitch.prop("checked"),str:'来自iframe:',from:window.location.href},'*'); 
          if (minpool.length != 0 && domPool.length != 0 && buiSwitch == true) {
            let channel;
            let nowlen = parseInt(player.currentTime / 60);
            //console.log('currentTime:'+player.currentTime); 
            //window.top.postMessage({obj:'currentTime:'+player.currentTime+'  '+minpool[nowlen].length,str:'来自iframe:',from:window.location.href},'*');  
            if (!$(player).paused) {
              for (var j = minpool[nowlen].length - 1; j > -1; j--) {
                //console.log('pool:'+minpool[nowlen][j].pool) 
                //window.top.postMessage({obj:minpool[nowlen][j],str:'来自iframe:',from:window.location.href},'*');  
                if (minpool[nowlen][j].time >= player.currentTime && minpool[nowlen][j].time <= player.currentTime + 0.5 && minpool[nowlen][j].type == '1') {
                  channel = getChannel()
                  //console.log('channel:'+channel)
                  if (channel != -1) {
                    let arrpJson = minpool[nowlen][j]
                    //console.log(minpool[nowlen][j].time+','+player.currentTime+'  biu~ [' + minpool[nowlen][j].text + ']');                  
                    let dom = domPool[channel].shift() //把数组的第一个元素从其中删除
                    domPool[channel].push(dom); //向数组的末尾添加一个或多个元素                    
                    shootDanmu(dom, arrpJson, channel);
                    minpoolout[nowlen].push(minpool[nowlen][j])
                    minpool[nowlen].splice(j, 1);
                  }
                } else if (minpool[nowlen][j].time >= player.currentTime && minpool[nowlen][j].time <= player.currentTime + 0.5 && minpool[nowlen][j].type != '1') {
                  channel = gettopdownChannel(minpool[nowlen][j].type);
                  console.log('gettopdownChannel:' + channel);
                  if (channel != -1) {
                    let arrpJson = minpool[nowlen][j]
                    //console.log(minpool[nowlen][j].time+','+player.currentTime+'  biu~ [' + danmu + ']');
                    let dom = domtopdownPool[channel];
                    shoottopdownDanmu(dom, arrpJson, channel);
                    minpoolout[nowlen].push(minpool[nowlen][j])
                    minpool[nowlen].splice(j, 1);
                  }
                }
              }
            }
          } else if (buiSwitch == false) {
            refreshDomscreen();
          }
        })
    } else {
      // 轮询检测
      setTimeout(function () {
        //console.log(window.location.href + '开始检测h5', findplayertime, new Date().getTime() - findplayertime);
        if (new Date().getTime() - findplayertime <= 5000) {
          detecH5Player(findplayertime)
        }
      },
        500)
    }
  }

  function refreshDomscreen() {
    //1.11.6 清除在场弹幕
    $('.left').each(function (index, element) {
      $(element).css('transition', `transform 0s linear`);
      $(element).addClass('right');
      element.style.left = 0
      element.style.willChange = 'transform'
      element.style.transition = null;
      element.style.willChange = 'auto'
      element.style.transform = `translateX(${player.clientWidth}px)`
      //element.style.left = `${player.clientWidth}px`
      element.innerText = ''
      element.className = 'right';

    })
    for (let i = 0; i < CHANNEL_COUNT; i++) {
      domtopdownPool[i].innerText = ''
    }

    $('.right').each(function (index, element) {
      element.style.left = 0
      element.style.transform = `translateX(${player.clientWidth}px)`
    })
    $('.left').each(function (index, element) {
      element.removeEventListener('transitionend', recoverLiftdom(element));
      element.addEventListener('transitionend', recoverLiftdom(element));
    })
  }
  var MAX_DM_COUNT = 10
  var CHANNEL_COUNT = 0

  function initcss() {
    let css = `.right {
			position: absolute;
			visibility: hidden;
			white - space: nowrap;
			/*left: 700px;
      transform: translateX(700px);*/
		}.left {
			position: absolute;
			white - space: nowrap;
			user - select: none;
			/* transition: transform 7s linear; 时间相同 越长的弹幕滑动距离越长 所以越快~ */
		}.topdown {
			position: absolute;
			white - space: nowrap;
			user - select: none;

		}`
    GM_addStyle(css);
    refreshDom();
  }

  function refreshDom() {
    window.top.postMessage({
      obj: 'refreshDom',
      str: '来自iframe:',
      from: window.location.href
    }, '*');
    if (Math.floor(player.clientHeight / fontSize) - CHANNEL_COUNT > 0) {
      // 先new一些span 重复利用这些DOM
      for (let j = Math.floor(player.clientHeight / fontSize); j > CHANNEL_COUNT; j--) {
        let doms = [];
        for (let i = 0; i < MAX_DM_COUNT; i++) {
          // 要全部放进player
          let dom = document.createElement('div');
          //alert(fontSize)
          dom.style.fontSize = fontSize + 'px';
          dom.style.color = 'rgb(255,255,255)';
          dom.style.fontFamily = 'SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif'
          dom.style.fontWeight = 'bold'
          dom.style.opacity = '1' //不透明度
          dom.style.textShadow = 'rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px';
          //dom.style.transform = `translateX(${player.clientWidth}px)`
          dom.style.left = `${player.clientWidth}px`
          dom.style.willChange = 'auto'
          // 初始化dom的位置 通过设置className
          dom.className = 'right';
          // DOM的通道是固定的 所以设置好top就不需要再改变了
          dom.style.top = (-j + Math.floor(player.clientHeight / fontSize) + 1) * fontSize + 'px';
          player.parentNode.appendChild(dom);

          // 放入改通道的DOM池
          doms.push(dom);
          // 每次到transition结束的时候 就是弹幕划出屏幕了 将DOM位置重置 再放回DOM池
          dom.addEventListener('transitionend', recoverLiftdom(dom));
        }
        domPool.push(doms);

        let dom2 = document.createElement('div');
        dom2.style.fontSize = fontSize + 'px';
        dom2.style.color = 'rgb(255,255,255)';
        dom2.style.fontFamily = 'SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif'
        dom2.style.fontWeight = 'bold'
        dom2.style.opacity = '1' //不透明度
        dom2.style.textShadow = 'rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px';
        dom2.style.willChange = 'auto'
        dom2.style.top = (-j + Math.floor(player.clientHeight / fontSize) + 1) * fontSize + 'px';
        dom2.style.left = `${(player.clientWidth - dom2.clientWidth) / 2}px`;
        dom2.className = 'topdown';

        player.parentNode.appendChild(dom2);
        domtopdownPool.push(dom2);
      }

    } else {
      //1.11.7 删除多余dom
      for (let j2 = Math.floor(player.clientHeight / fontSize); j2 < CHANNEL_COUNT; j2++) {
        for (let i2 = 0; i2 < MAX_DM_COUNT; i2++) {
          let thisdom = domPool[j2][i2]
          thisdom.parentNode.removeChild(thisdom)
        }
        domPool[j2].length = 0
        domPool.splice(j2, 1);
        //refreshDomscreen()
        domtopdownPool[j2].parentNode.removeChild(domtopdownPool[j2])
        domtopdownPool.splice(j2, 1);
      }
    }
    CHANNEL_COUNT = Math.floor(player.clientHeight / fontSize);
    /*//1.11.7 修改弹幕默认位置
    $('.right').each(function (index, element) {
      element.style.transform = `translateX(${player.clientWidth}px)`
    })
    $('.left').each(function (index, element) {
      element.removeEventListener('transitionend',recoverLiftdom(element));
      element.addEventListener('transitionend',recoverLiftdom(element));
    })
    $('.topdown').each(function (index, element) {
      element.style.left = `${(player.clientWidth - element.clientWidth) / 2}px`;
    })*/
    refreshDomscreen()
    let refreshDom_time = parseInt(player.currentTime / 60)
    if (minpool.length != 0) {
      minpool[refreshDom_time] = minpool[refreshDom_time].concat(minpoolout[refreshDom_time])
      minpoolout[refreshDom_time].length = 0
    }

  }

  function recoverLiftdom(dom) {
    dom.style.transition = null;
    dom.style.willChange = 'auto'
    //dom.style.transform = `translateX(${player.clientWidth}px)`
    dom.style.left = `${player.clientWidth}px`
    dom.innerText = ''
    dom.className = 'right';
  }
  /**
   * 获取一个可以发射弹幕的通道 没有则返回-1
   */

  function getChannel() {
    for (let i = 0; i < CHANNEL_COUNT; i++) {
      let lastNumPos = domPool[i].length - 1
      let lastDom = domPool[i][lastNumPos];
      //console.log('lastDom:'+lastDom)
      if (lastDom) {
        if (lastDom.className == 'right') {
          //console.log('捷径')
          return i
        }
        let lastDomPos = lastDom.getBoundingClientRect();
        //console.log('lastDomPos.right:'+lastDomPos.right+'playerRect.right:'+playerRect.right)
        // 轨道中最后一个元素要求已经全部进入展示区域
        if (lastDomPos.right > playerRect.right) {
          continue
        }

        let occupyS = lastDomPos.right - playerRect.left
        //console.log('playerRect.left:'+occupyS+'player.clientWidth:'+player.clientWidth)
        // 追及问题
        if (player.clientWidth - occupyS < distance) {
          continue
        }
        for (let j = 0; j < domPool[i].length; j++) {
          if (domPool[i][j].className == 'right') {
            return i
          }
        }

      }
    }
    return -1;
  }

  function gettopdownChannel(type) {
    for (let i = 0; i < CHANNEL_COUNT; i++) {
      if (type == 4) {
        let lastNumPos = domtopdownPool.length - i - 1
        let downDom = domtopdownPool[lastNumPos];
        if (downDom.innerText == '') {
          return i
        }
      } else if (type == 5) {
        let lastNumPos2 = i
        let topDom = domtopdownPool[lastNumPos2];
        if (topDom.innerText == '') {
          return i
        }
      }
    }
    return -1;
  }

  /**
   * 根据DOM和弹幕信息 发射弹幕
   */
  function shootDanmu(dom, arrpJson, channel) {
    dom.innerText = arrpJson.text;
    console.log(' biu1~ [' + arrpJson.text + ']');

    let num16 = parseInt(arrpJson.rgb).toString(16);
    dom.style.color = '#' + (Array(6).join(0) + num16).slice(-6);
    dom.style.fontSize = arrpJson.size + 'px';
    // 如果为每个弹幕设置 transition 可以保证每个弹幕的速度相同 这里没有保证速度相同
    dom.style.transition = `transform ${0.0074 * (dom.clientWidth + player.clientWidth)}s linear`;

    // 设置弹幕的位置信息 性能优化 left -> transform
    dom.style.transform = `translateX(${-dom.clientWidth - player.clientWidth}px)`;
    dom.style.willChange = 'transform';
    dom.className = 'left';
  }

  function shoottopdownDanmu(dom, arrpJson, channel) { //1.11.5 格式化居然把这function丢失了
    dom.innerText = arrpJson.text;
    dom.name = new Date().getTime();
    console.log(' biu2~ [' + arrpJson.text + ']');
    let num16 = parseInt(arrpJson.rgb).toString(16);
    dom.style.fontSize = arrpJson.size + 'px';
    dom.style.color = '#' + (Array(6).join(0) + num16).slice(-6);

    //dom.style.transform = `translateX(${(player.clientWidth - dom.clientWidth) / 2}px)`;
    dom.style.left = `${(player.clientWidth - dom.clientWidth) / 2}px`;
  }

  var $ = $ || window.$;

  /**
   * 共有方法
   */
  function commonFunction() {
    this.GMgetValue = function (name, value) { //得到存在本地的数据
      if (typeof GM_getValue === "function") {
        return GM_getValue(name, value);
      } else {
        return GM.getValue(name, value);
      }
    };
    this.GMsetValue = function (name, value) { //设置存在本地的数据
      if (typeof GM_setValue === "function") {
        return GM_setValue(name, value);
      } else {
        return GM.setValue(name, value);
      }
    };
    this.GMaddStyle = function (css) { //插入css
      var myStyle = document.createElement('style');
      myStyle.textContent = css;
      var doc = document.head || document.documentElement;
      doc.appendChild(myStyle);
    };
    this.GMopenInTab = function (url, open_in_background) { //新标签页打开网址
      if (typeof GM_openInTab === "function") {
        GM_openInTab(url, open_in_background);
      } else {
        GM.openInTab(url, open_in_background);
      }
    };
    this.addScript = function (url) { //添加脚本
      var s = document.createElement('script');
      s.setAttribute('src', url);
      document.body.appendChild(s);
    };
  }

  //全局统一变量
  const commonFunctionObject = new commonFunction();

  /**
   * 超级解析助手
   * @param {Object} originalInterfaceList
   * @param {Object} playerNodes
   */
  function superVideoHelper() {
    this.originalInterfaceList = originalInterfaceList;
    this.node = "#player_module";
    this.elementId = Math.ceil(Math.random() * 100000000);

    this.innerParse = function (url) { //内嵌解析
      $("#iframe-player").attr("src", url);
    };
    this.addHtmlElements = function () {
      var vipVideoImageBase64 = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC9klEQVRoQ+2ZPWgVQRDH/7/CWqOIYOFHFbRSjJhGMGDpByoIago70cqvUtQgdipWFqawMWghGIidhcHKQAJqEURBRfED1CCCjc3IPu4em31775J7d3m8cAtX3O7szP7nPzszx6EeH/T4+VUD6DaDTQbMbE+3D7MY+8Ckkw8BPFuMki7KDtUAuuh9Z3oZMtBljxY2X9eBwq4raWPNQEmOLKxm+TBgZqsknQ1dAVzNco+ZhWsm6ZakHZLC1mQyrZ5OX2RvzMxnSa8lzQJ/YwLzGDCze5JOeoI/gbVtAMxJ6vPW7wKnkr4qbEuaxccDcGWBsfNV0mjMmSGAg5LGA6XbgFehITPbLel5MN84ZAUAUjMPgWO+zZY7YGbvJW0OvRoB8EjSEW9+BhhIvOvCp0wGfPPbgZfpRAzATUnn56GEmJyLd39cBNxeF99FADTa42BskuQef4wDh9oB2CXpRbDpMPA4nTOz05LuBDLrgW+dAACGIkxfkHTDm/8DrMwEkBxgOskkqdwEcMAD4GLf3YF0PACOe+uFGMgA4Bj4EAAbAGbcXLQOmNklSdeCTRuBT2bWL+lNsLYfeFIRgH2SJgJ7GwCXYjMBrJb0K9jUiHEzG5F02VubA9b4skXvQMiAmW2VdFSSn24/As0kk1mJzeyppL3ewaaBnWY2K2mLNz8S5ueCAMLwz3q/DZxreweSe3BC0v1Ai7tkYXrsB96WwMBCAfQBv3MBJCD+SVrhaXaZ54z3PgUMhpYrZKCF7bbNnJk5BhwT6fghyW8thoGxigE4my6tXwemQlt5AGI1oamDSIFLmCuURiW5BOGPL8C7drGV206b2XdJ6yJKxoDhmPKCIeS61ZZClncxFgLAtcyxrnEwRmknDFQFIFYTWnJ/CVmoGgYSj7Z81OR86Lg7sOgPmnY6s0IpN4TyYrDb6zWAmoEOPVCHUIcO7Hh7/YemYxcWU7AMf3BkNGDF/FP9rkwGqjddkoWWv5Ql6V1yNXUdWHKXBwZ7noH/dP+HQNqheToAAAAASUVORK5CYII=`;
      var category_1_html = "";
      this.originalInterfaceList.forEach((item, index) => {
        if (item.category === "1") {
          category_1_html += "<li title='" + item.name + "' data-index='" + index + "'>" + item.name + "</li>";
        }
      });

      //获得自定义位置
      var left = 0;
      var top = 100;
      var Position = commonFunctionObject.GMgetValue("Position_" + window.location.host);
      if (!!Position) {
        left = Position.left;
        top = Position.top;
      }
      var cssMould = `#vip_movie_box` + this.elementId + ` {cursor:pointer; position:fixed; top:` + top + `px; left:` + left + `px; width:0px; z-index:2147483647; font-size:16px; text-align:left;}
							#vip_movie_box` + this.elementId + ` .item_text {}
							#vip_movie_box` + this.elementId + ` .item_text .img_box{width:26px; height:35px;line-height:35px;text-align:center;background-color:#E5212E;}
							#vip_movie_box` + this.elementId + ` .item_text .img_box >img {width:20px; display:inline-block; vertical-align:middle;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_action {display:none; position:absolute; left:26px; top:0; text-align:center; background-color:#272930; border:1px solid gray;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_action li{border-radius:2px; font-size:12px; color:#DCDCDC; text-align:center; width:60px; line-height:21px; float:left; border:1px solid gray; padding:0 4px; margin:4px 2px;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;-o-text-overflow:ellipsis;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_action li:hover{color:#E5212E; border:1px solid #E5212E;}
							
							#vip_movie_box` + this.elementId + ` li.selected{color:#E5212E; border:1px solid #E5212E;}
							
							
							#vip_movie_box` + this.elementId + ` .selected_text {margin-top:5px;}
							#vip_movie_box` + this.elementId + ` .selected_text .img_box{width:26px; height:35px;line-height:35px;text-align:center;background-color:#E5212E;}
							#vip_movie_box` + this.elementId + ` .selected_text .img_box >img {width:20px; height:20px;display:inline-block; vertical-align:middle;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_selected {display:none;position:absolute; left:26px; top:0; text-align:center; background-color:#F5F6CE; border:1px solid gray;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_selected ul{overflow-y: auto;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_selected li{border-radius:2px; font-size:12px; color:#393AE6; text-align:center; width:95px; line-height:27px; float:left; border:1px dashed gray; padding:0 4px; margin:4px 2px;display:block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}
							#vip_movie_box` + this.elementId + ` .vip_mod_box_selected li:hover{color:#E5212E; border:1px solid #E5212E;}
														
							#vip_movie_box` + this.elementId + ` .default-scrollbar-55678::-webkit-scrollbar{width:5px; height:1px;}
							#vip_movie_box` + this.elementId + ` .default-scrollbar-55678::-webkit-scrollbar-thumb{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#A8A8A8;}
							#vip_movie_box` + this.elementId + ` .default-scrollbar-55678::-webkit-scrollbar-track{box-shadow:inset 0 0 5px rgba(0, 0, 0, 0.2); background:#F1F1F1;}
							`;
      commonFunctionObject.GMaddStyle(cssMould);

      var htmlMould = `<div id='vip_movie_box` + this.elementId + `'>
			<div class='item_text'>
				<div class="img_box" id="img_box_6667897iio"><img src='` + vipVideoImageBase64 + `' title='点击跳转到综合解析页面,线路随意选!'/></div>
					<div class='vip_mod_box_action' >
						<div style='display:flex;'>
							<div style='padding:10px 0px; width:380px; max-height:400px; overflow-y:auto;'  class="default-scrollbar-55678">
								<div style='font-size:16px; text-align:center; color:#E5212E; padding:5px 0px;'><b>线路</b></div>
								<ul>` + category_1_html + `<div style='clear:both;'></div></ul>
							</div>
						</div>
					</div>	
				</div>
			</div>`;
      $("body").append(htmlMould);
    };
    this.mouseEvent = function () {
      $(".item_text").on("mouseover", () => {
        $(".vip_mod_box_action").show();
      });
      $(".item_text").on("mouseout", () => {
        $(".vip_mod_box_action").hide();
      });
      $(".vip_mod_box_action li").each((liIndex, item) => {
        item.addEventListener("click", () => {
          //1.11.5同一操作
          var index = parseInt($(item).attr("data-index"));
          commonFunctionObject.GMsetValue("index", index);
          this.videoreplace();
        });
      });
    };

    this.operatOther = function () {
      switch (window.location.host) {
        case 'www.bilibili.com':
          receiveInfoFromAnotherDomain();
          this.addHtmlElements();
          //console.log("检测是否为vip视频");
          let findviptime = new Date().getTime();
          let waitlimit = setInterval(() => {
            let viptextArr = [$(".bpx-player-toast-confirm").text(), $(".twp-title").text(), $(".video-float-hint-btn.hint-red").text(), $('.new-twp-btn.right.vip.blue').children('.current').text()];
            let vipmatchArr = ['成为大会员', '付费观看', '成为大会员抢先看', '开通大会员观看'];
            //let arr2=['成为大会员', '开通大会员观看','正在观看预览,大会员免费看全片', '正在观看预览,付费观看完整版']
            let intersection = viptextArr.filter(item => new Set(vipmatchArr).has(item))
            //console.log(arr1,arr2,intersection);
            if (intersection.length != 0) {
              console.log("是vip视频");
              this.videoreplace();
              clearInterval(waitlimit);
            }
            if (new Date().getTime() - findviptime >= 5000) {
              clearInterval(waitlimit)
            }
          },
            250);
          break
        default:
          try {
            detecH5Player(new Date().getTime())
          } catch (err) {
            console.log('h5:' + err)
          }
          break
      }
    }

    this.videoreplace = function () {
      let safediv = window.document.querySelector("#player_placeholder")
      //1.11.6 修复m1907存在滚动条(才发现是滚动条) 修复基础不扎实且手贱导致的全屏问题
      let videoPlayer = $("<div id='iframe-play-div' style='width:100%;height:92%;z-index:1000;'><iframe id='iframe-player' allowfullscreen='true' frameborder='0' width='100%' height='100%' scrolling='no'></iframe></div>");
      let index = commonFunctionObject.GMgetValue("index");
      $(".vip_mod_box_action li").removeClass("selected");
      $(".vip_mod_box_action li").eq(index).addClass("selected");
      if (index == null) {
        index = 0
      }
      let url2 = this.originalInterfaceList[index].url + window.location.href;
      console.log(index, url2);
      if (document.getElementById("iframe-player") == null) {
        //1.11.5 尝试修复多重视频声音 www.cnblogs.com/dzyany/p/14187782.html
        let playerb = document.querySelector('video');
        if (playerb) {
          playerb.pause();
          playerb.removeAttribute('src');
          playerb.currentSrc = '';
          playerb.innerHTML = '';
        }

        let playera = $(this.node);
        //console.log(playera)
        playera.empty();
        playera.append(videoPlayer);

        //1.11.5添加底部区域
        this.bottomArea()

      }
      this.innerParse(url2);
      //1.11.5 修复移除vip提示bug
      let removetime = new Date().getTime();
      let waitlimit = setInterval(() => {
        $(".player-limit-mask").remove();
        $(".player-limit-mask pay").remove();
        $(".twp-container").remove();
        $(".twp-mask.twp-float").remove();
        if (new Date().getTime() - removetime >= 5000) {
          clearInterval(waitlimit)
        }
      },
        250);
    }
    this.bottomArea = function () {
      let playera = $(this.node);
      //1.11.5添加bottomArea
      let bottomcss = `/*底部背景阴影*/
			.bilibili-player-video-bottom-area
			{
			width:100%;
			height: 46px;	
			background-color:#fff;
			-webkit-box-shadow: 0 0 8px #e5e9ef;
			box-shadow: 0 0 8px #e5e9ef;
			-ms-flex-negative: 0;
			flex-shrink: 0;
			position: relative;
			display: -webkit-box;
			display: -ms-flexbox;
			display: flex;
			-webkit-box-align: center;
			-ms-flex-align: center;
			align-items: center;
			}
			/*弹幕字体*/
			.bilibili-player-video-info-danmaku-number {
				height: 14px;
				line-height: 14px;
				font-size: 14px;
				font-weight: 600;
			}
			/*视频信息文本格式*/
			.bilibili-player-video-info {
				display: -webkit-box;
				display: -ms-flexbox;
				display: flex;
				-webkit-box-flex: 0;
				-ms-flex: none;
				flex: none;
				-ms-flex-negative: 1;
				flex-shrink: 1;
				font-size: 12px;
				height: 16px;
				line-height: 14px;
				color: #505050;
				-webkit-box-pack: start;
				-ms-flex-pack: start;
				justify-content: flex-start;
				-webkit-box-align: center;
				-ms-flex-align: center;
				align-items: center;
				margin-right: 12px;
				width: 208px;
				white-space: nowrap;
				-webkit-box-align: end;
				-ms-flex-align: end;
				align-items: flex-end;
				overflow: hidden;
				padding: 0 12px 0 20px;
			}
			/*弹幕按钮本体*/
			.bui-switch .bui-switch-input {
				position: absolute;
				width: 30px;
				height: 20px;
				border-radius: 10px;
				opacity: 0;
				margin: 0;
				cursor: pointer;
				z-index: 1;
			}
			/*弹幕按钮主体*/
			.bui-switch .bui-switch-body {
				display: inline-block; 
				width: 30px;
				height: 20px;
				outline: none; 
				border-radius: 10px;
				-webkit-box-sizing: border-box; 
				box-sizing: border-box; 
				background: #757575;
				margin-right: 11px;
			}
			.bui-switch .bui-switch-input:checked+.bui-switch-label .bui-switch-body {
					background: #00a1d6;
				}
			/*弹幕按钮dot*/
			.bui-switch .bui-switch-dot {
				top: 2px;
				left: 2px;
				border-radius: 100%;
				width: 16px;
				height: 16px;
				background-color: #fff;
				color: #757575;
				fill: #757575;
				line-height: 16px;
				text-align: center;
				-webkit-box-shadow: 0 3px 1px 0 rgba(0,0,0,.05), 0 2px 2px 0 rgba(0,0,0,.1), 0 3px 3px 0 rgba(0,0,0,.05);
				box-shadow: 0 3px 1px 0 rgba(0,0,0,.05), 0 2px 2px 0 rgba(0,0,0,.1), 0 3px 3px 0 rgba(0,0,0,.05);
				display: -webkit-box;
				display: -ms-flexbox;
				display: flex;
				-webkit-box-align: center;
				-ms-flex-align: center;
				align-items: center;
				-webkit-box-pack: center;
				-ms-flex-pack: center;
				justify-content: center;
			}
			.bui-switch .bui-switch-body, .bui-switch .bui-switch-dot {
				position: relative;
				-webkit-transition: all .3s;
				-o-transition: all .3s;
				transition: all .3s;
				-webkit-transform: translateZ(0);
				transform: translateZ(0);
			}
			.bui-switch .bui-switch-input:checked+.bui-switch-label .bui-switch-body .bui-switch-dot {
				left: 100%;
				margin-left: -18px;
				color: #00a1d6;
				fill: #00a1d6;
			}
			/*弹幕按钮图片*/
			.bui-switch .bui-switch-dot span {
				display: inline-block;
				width: 10px;
				height: 10px;
				font-size: 0;
			}
			/*设置主体*/
			.bilibili-player-video-danmaku-setting .bp-svgicon span {
				display: inline-block;
				width: 24px;
				font-size: 0;
				position: absolute;
				cursor: pointer;
				z-index: 1;
				margin: middle;
				top: 13px;
				margin-right: 11px;
			}
			.bilibili-player-video-danmaku-setting:hover .bp-svgicon span {
				color: #00a1d6;
				fill: #00a1d6;
			}`
      GM_addStyle(bottomcss);
      let bottomdiv = `
			<div class="bilibili-player-video-bottom-area">	
 <div class="bilibili-player-video-info">
  <div class="bilibili-player-video-info-danmaku player-tooltips-trigger"> 						
   <span class="bilibili-player-video-info-danmaku-number"></span>
   <span class="bilibili-player-video-info-danmaku-text">条弹幕存在此弹幕池</span>
  </div>
 </div>
 <div class="bui-switch" aria-label="弹幕显示隐藏">
  <input class="bui-switch-input" type="checkbox" checked="">
  <label class="bui-switch-label">
   <span class="bui-switch-name"></span>
   <span class="bui-switch-body">
    <span class="bui-switch-dot">
     <span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><path d="M1.311 3.759l-.153 1.438h2.186c0 1.832-.066 3.056-.175 3.674-.131.618-.688.959-1.683 1.023-.284 0-.568-.021-.874-.043L.317 8.818c.284.032.59.053.896.053.546 0 .852-.17.929-.511.077-.341.12-1.076.12-2.204H0l.306-3.344h1.847V1.427H.098V.479h3.18v3.28H1.311zM4 1.747h1.311A8.095 8.095 0 004.492.426L5.53.085c.306.426.579.873.809 1.363l-.689.299h1.508c.306-.544.569-1.129.809-1.747l1.082.373c-.219.511-.47.969-.743 1.374h1.268V6.23H7.322v.82H10v1.044H7.322V10H6.208V8.094H3.607V7.05h2.601v-.82H4V1.747zm4.568 3.557v-.831H7.322v.831h1.246zm-2.36 0v-.831H5.016v.831h1.192zM5.016 3.557h1.191v-.873H5.016v.873zm2.306-.873v.873h1.246v-.873H7.322z"></path></svg></span>
    </span>
   </span>
  </label>
 </div>
  <div class="bilibili-player-video-danmaku-setting">
	<span class="bp-svgicon">
	 <span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path d="M16.5 8c1.289 0 2.49.375 3.5 1.022V6a2 2 0 00-2-2H4a2 2 0 00-2 2v10a2 2 0 002 2h7.022A6.5 6.5 0 0116.5 8zM7 13H5a1 1 0 010-2h2a1 1 0 010 2zm2-4H5a1 1 0 010-2h4a1 1 0 010 2z"></path><path d="M20.587 13.696l-.787-.131a3.503 3.503 0 00-.593-1.051l.301-.804a.46.46 0 00-.21-.56l-1.005-.581a.52.52 0 00-.656.113l-.499.607a3.53 3.53 0 00-1.276 0l-.499-.607a.52.52 0 00-.656-.113l-1.005.581a.46.46 0 00-.21.56l.301.804c-.254.31-.456.665-.593 1.051l-.787.131a.48.48 0 00-.413.465v1.209a.48.48 0 00.413.465l.811.135c.144.382.353.733.614 1.038l-.292.78a.46.46 0 00.21.56l1.005.581a.52.52 0 00.656-.113l.515-.626a3.549 3.549 0 001.136 0l.515.626a.52.52 0 00.656.113l1.005-.581a.46.46 0 00.21-.56l-.292-.78c.261-.305.47-.656.614-1.038l.811-.135A.48.48 0 0021 15.37v-1.209a.48.48 0 00-.413-.465zM16.5 16.057a1.29 1.29 0 11.002-2.582 1.29 1.29 0 01-.002 2.582z"></path></svg></span>
    </span>
	<div class="bilibili-player-video-danmaku-setting-wrap" style="display: none;">
	</div>	
 </div>
</div>
`;
      playera.append(bottomdiv);

      //1.11.5修复移除关键div导致脚本失效
      let playerPlaceholder = document.createElement('div');
      playerPlaceholder.id = 'player_placeholder';
      playera.append(playerPlaceholder);
      //console.log($(".bui-switch-input").prop("checked"),document.querySelector("#player_module > div.bilibili-player-video-bottom-area > div.bui-switch > input").checked)

      //1.11.5 弹幕开关
      let buiSwitchbtn = $(".bui-switch-input");
      buiSwitchbtn.click(function () {
        //let buiSwitchbtn = $(".bui-switch-input").prop("checked");
        //console.log(buiSwitchbtn);
        if ($(".bui-switch-input").prop("checked")) {
          postdownmessage({
            str: 'checktrue'
          }) 
        } else {
          postdownmessage({
            str: 'checkfalse'
          }) 
        }

      });
    }

    this.start = function () {
      this.operatOther();
      this.mouseEvent();
    }
  };

  (new superVideoHelper()).start();
})()