Greasy Fork

Greasy Fork is available in English.

哔哩哔哩画中画弹幕

哔哩哔哩画中画支持显示弹幕

当前为 2022-07-10 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         哔哩哔哩画中画弹幕
// @namespace    qwq0
// @version      0.6
// @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
// ==/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 = width / 2;
    var canvasHeight = canvas.height = 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 = width / 2;
            canvasHeight = canvas.height = 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(50);
    video.addEventListener("enterpictureinpicture",() =>{
        nVideo.requestPictureInPicture();
        nVideo.play();
    });
}, 3500);