// ==UserScript== // @name 哔哩哔哩画中画弹幕 // @namespace qwq0 // @version 0.7 // @description 哔哩哔哩画中画支持显示弹幕 // @author QwQ~ // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/medialist/play/* // @match https://www.bilibili.com/bangumi/play/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @downloadURL none // ==/UserScript== setTimeout(function() { 'use strict'; var videoHolder = document.getElementsByClassName("bilibili-player-video")[0] || document.getElementsByClassName("bpx-player-video-wrap")[0]; var video = videoHolder.children[0]; var width = video.videoWidth; var height = video.videoHeight; var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); var canvasWidth = canvas.width = Math.floor(width / 2); var canvasHeight = canvas.height = Math.floor(height / 2); var nVideo = document.createElement("video"); var danmuList = []; var danmuLine = []; var danmuCount = 0; var danmuHolder = document.getElementsByClassName("bilibili-player-video-danmaku")[0] || document.getElementsByClassName("bpx-player-row-dm-wrap")[0]; function addDanmu(text, color) { danmuCount++; var lineNum = 0; for(var i=0;i < 8 && danmuLine[lineNum] + 3 >= danmuCount;i++) { lineNum = Math.floor(Math.random() * 11); } danmuLine[lineNum] = danmuCount; danmuList.push({text: text, color: (color ? color : "rgb(255, 255, 255)"), x: canvasWidth, y: lineNum * 36 }); } var danmuObserver = new MutationObserver(e=>{ e.forEach(o=>{ // console.log("danmu(all)", o); if(o.type == "childList") { o.addedNodes.forEach(ele =>{ if(ele.innerText) { let text = ele.innerText; addDanmu(text, ele.style.color); console.log("danmu(it)", ele.style.color, text); } else if(ele.textContent) { let text = ele.textContent; addDanmu(text, o.target.style.color); console.log("danmu(ct)", o.target.color, text); } }); } }); }); danmuObserver.observe(danmuHolder, { childList: true, subtree: true }); setInterval(()=>{ var nowDanmuHolder = document.getElementsByClassName("bilibili-player-video-danmaku")[0] || document.getElementsByClassName("bpx-player-row-dm-wrap")[0]; if(nowDanmuHolder != danmuHolder) { danmuHolder = nowDanmuHolder; danmuObserver.disconnect(); width = video.videoWidth; height = video.videoHeight; canvasWidth = canvas.width = Math.floor(width / 2); canvasHeight = canvas.height = Math.floor(height / 2); nVideo.srcObject = canvas.captureStream(50); setTimeout(() => nVideo.play(), 3500); danmuObserver.observe(danmuHolder, { childList: true, subtree: true }); } }, 3000); var lastTime = 0; function draw(nowTime) { var timeInterval = nowTime - lastTime; lastTime = nowTime; context.globalAlpha = 1; context.drawImage(video, 0, 0, width, height, 0, 0, width/2, height/2); context.font = '36px SimHei,"Microsoft JhengHei",Arial,Helvetica,sans-serif'; context.textBaseline = "top"; context.fillStyle = "rgb(255, 255, 255)"; context.shadowColor = "rgb(0, 0, 0)"; context.globalAlpha = 0.8; danmuList.forEach((o, i)=>{ context.fillStyle = o.color; context.shadowBlur = 5; context.fillText(o.text, o.x, o.y); o.x -= timeInterval * 0.2; if(o.x < -1000) { danmuList.splice(i, 1); } }); requestAnimationFrame(draw); } requestAnimationFrame(draw); console.log("[哔哩哔哩画中画弹幕]", "已加载") console.log("[哔哩哔哩画中画弹幕]", "视频分辨率", width, height); console.log("[哔哩哔哩画中画弹幕]", "视频分辨率", canvasWidth, canvasHeight); nVideo.srcObject = canvas.captureStream(60); video.addEventListener("enterpictureinpicture",() =>{ nVideo.requestPictureInPicture(); nVideo.play(); }); }, 3500);