// ==UserScript== // @name b站vtuber直播同传评论转字幕 // @namespace http://tampermonkey.net/ // @version 0.2 // @author You // @match https://live.bilibili.com/* // @grant none // @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js // @require https://cdn.staticfile.org/vue/2.6.11/vue.min.js // @description 将vtuber直播时同传man的评论,以类似底部弹幕的形式展现在播放器窗口,免去在众多快速刷过的评论中找同传man的痛苦。 // @downloadURL none // ==/UserScript== (function () { // 字幕样式配置 const removeBracket = true window.attentionModul = {} window.attentionModul.commentApp = {} window.attentionModul.consoleApp = {} window.attentionModul.users = [] window.attentionModul.observe = {} window.attentionModul.dom = [] // 测试用组件 window.attentionModul.debug = {} window.attentionModul.debug.setComment = function (index, comment) { setComment(index, comment) } window.attentionModul.debug.addAttentionUser = addAttentionUser window.attentionModul.debug.showDOM = function () { return [document.getElementById('comment-container'), document.getElementById('console-container')] } window.attentionModul.config = JSON.parse(localStorage.getItem('config')|| '{"color":"","vertical":"2","fontSize":40}') // 添加关注用户 function addAttentionUser(uid) { console.log('add subscribe:', uid) $('textarea:eq(0)').click() if (window.attentionModul.users.indexOf(uid) < 0) { window.attentionModul.users.push(uid) window.attentionModul.commentApp.comments.push(null) } } // 移除关注用户 function removeAttentionUser() { } // 移除括号 function removeBreaket(comment) { let r = comment.match(/^[ 【]*(.*?)[ 】]*$/i)[1] return r } //将匹配评论添加到vue变量中对应的字幕DOM function setComment(index, comment) { console.log('comment', comment) window.attentionModul.commentApp.comments.splice(index, 1, comment) } //匹配评论发出者与关注用户 function chatFilter(nodeList) { for (let item of nodeList) { const uid = item.getAttribute('data-uid') const comment = item.getAttribute('data-danmaku') const index = window.attentionModul.users.indexOf(uid) if (index > -1) { if (removeBreaket) { setComment(index, removeBreaket(comment)) } else { setComment(index, comment) } } } } // DOM突变事件回调函数 function mutationListener(mutationList) { window.attentionModul.observe.message = mutationList if (window.attentionModul.observe.message[0].addedNodes.length > 0) { chatFilter(window.attentionModul.observe.message[0].addedNodes) } } function saveConfig() { const config = { "color":window.attentionModul.consoleApp.color, "vertical":window.attentionModul.consoleApp.vertical, "fontSize":window.attentionModul.consoleApp.fontSize } localStorage.setItem('config',JSON.stringify(config)) } // 注入控制台组件 ;(function () { const consoleStyle = ` .att-col{ display: flex; flex-flow: column nowrap; place-content: center start; } .att-row{ display: flex; flex-flow: row nowrap; place-content: center start; margin:3px 0px 3px 0px; } .att-top{ z-index: 999; } .att-input{ outline: none; } #console-container{ position: absolute; left: 50px; top: 300px; min-height: 48px; min-width: 48px; } .att-icon-container { position: absolute; left: 0px; top: 0px; height: 48px; width: 48px; background-color: #fb7299; border-radius: 4px; } .att-icon { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); height: 32px; width: 32px; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADFElEQVRYhe2XX2iPURjHP7+N0oYRWWObMZSUJjQKG/JnlCh/LkSaUG6URLlf8pNSciEX1AqzaEXKhdTMnVHmRogxtOZfG/m/r956Th3v791r7++nXPCt0znv8zznOd/3Oc95zvvyzyPlAiDpd7GYAywAioEioBd4BbQCd5MGMpVK/SoICAzQdku6p3i0S6qP8ZHRMhBhNN8c++iSdFVSk/UvQvo2SbP+BIGNIceNkhZKKgjZFUqqkXTOs/0maXUuBJZ4zh5KWjzIsC6T9NSbm5Y0NymBIknvzcEDSWOT7KukkhCJAGclTRwsgVM26Yuk8oSLu1Yp6WuIRI9tVSyBUm/CviwXd+2g+en3fP6QVB1HYK8ZvpGUnyOBYZJ6jUCDpFvmu9slskOex2GB9ZeAH5kUE+Ez0GKF7iOwxmTjgHSkI0mPjOX20NuMkTQlJJsRse/hhN1t/jrseZe3HSVRBD6ass5zEpyKZ5I+SJpnsrQl2RF7DuR9kp6bvZu71vy982TdLseitsCN/QwZBpQBhcAok00DhgJT7Xk0MBwoNXsHt40pz/dF62ujItBp7LaEQhkcn03ec7GkzXbmnSzQ14bm1XvFLGWybSZ7GkXgmimP5ngCXDtu/i57spUm+xS1BTetX5ck3WPg/LR5JvnW90cROG/9JGBDjotvASbY+IInL7e+K2OGhajFQtRlxy+b0Bd52d4U0rlbs3kgApV2bAIcypLADa/0loWIfTLdjoEIBO20GTUmXLhCUqtXbLaG9CddAkoaEUfghBmmvboefB1NHmDhCZL2S3odc5kt8nQH/LtgSEQCOdksoMESMig634ErQCfQZx+mlUCNFSpMvtNLaIcq698ChyPW/CUCZ5QcHXab+n7Ge+M15vGxk8VFoNcbtwPNViOCklwNzASWhuY8AV4C600/G1gO3AbOWLTcenl+HYiKQJC5eyRVxSRcUJ6vZxGp4HMtz49Akh+TKCwCVthPS4VdRj3AHeA+MB3YZBdWgA/AyGA592OSK4Ew8iM+ZgqAVUAd0AEcI+rP6D/+CoCf0HfCu9e1CkQAAAAASUVORK5CYII='); } #att-console{ color: #23ade5; background-color: white; width: 250px; min-height: 48px; padding: 14px 8px 14px 8px; border-radius: 8px; } .att-console-title{ margin:4px; } .att-input-range{ width: 200px; margin-right: 10px; outline: none; } .att-input-value{ width: 20px; text-align: center; border: 0px; border-bottom: 1px solid gray; outline: none; } ` const consoleContainer = $('
') const widgetIcon = $(' ') const consoleWidget = $('') const verticalWidget = $('