// ==UserScript== // @name NEXT-哔哩哔哩(bilibili.com)播放页调整 // @license GPL-3.0 License // @namespace https://greasyfork.org/zh-CN/scripts/415804-bilibili%E6%92%AD%E6%94%BE%E9%A1%B5%E8%B0%83%E6%95%B4-%E8%87%AA%E7%94%A8 // @version 0.13 // @description 1.自动定位到播放器(进入播放页,可自动定位到播放器,可设置偏移量及是否在点击主播放器时定位);2.可设置是否自动选择最高画质;3.可设置播放器默认模式; // @author QIAN // @match *://*.bilibili.com/video/* // @match *://*.bilibili.com/bangumi/play/* // @match *://*.bilibili.com/list/watchlater* // @run-at document-start // @require https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js // @require https://unpkg.com/sweetalert2@11.7.2/dist/sweetalert2.min.js // @resource swalStyle https://unpkg.com/sweetalert2@11.7.2/dist/sweetalert2.min.css // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_getResourceText // @grant GM.info // @supportURL https://github.com/QIUZAIYOU/Bilibili-VideoPage-Adjustment // @homepageURL https://github.com/QIUZAIYOU/Bilibili-VideoPage-Adjustment // @icon https://www.bilibili.com/favicon.ico?v=1 // @downloadURL none // ==/UserScript== $(() => { 'use strict' let { currentUrl, theMainFunctionRunningTimes, thePrepFunctionRunningTimes, autoSelectScreenModeTimes, autoCancelMuteTimes, webfullUnlockTimes, insertGoToCommentsButtonTimes, autoSelectVideoHightestQualityTimes, } = { currentUrl: window.location.href, theMainFunctionRunningTimes: 0, thePrepFunctionRunningTimes: 0, autoSelectScreenModeTimes: 0, autoCancelMuteTimes: 0, webfullUnlockTimes: 0, insertGoToCommentsButtonTimes: 0, autoSelectVideoHightestQualityTimes: 0, } const { getValue, setValue, sleep, addStyle, historyListener, checkBrowserHistory, throttle, getClientHeight, checkElementExistence, isLogin, logger, checkPageReadyState } = { getValue(name) { return GM_getValue(name) }, setValue(name, value) { GM_setValue(name, value) }, sleep(time) { return new Promise(resolve => setTimeout(resolve, time)) }, addStyle(id, tag, css) { tag = tag || 'style' const doc = document const styleDom = doc.getElementById(id) if (styleDom) return const style = doc.createElement(tag) style.rel = 'stylesheet' style.id = id tag === 'style' ? (style.innerHTML = css) : (style.href = css) document.head.appendChild(style) }, historyListener() { class Dep { constructor(name) { this.id = new Date() this.subs = [] } defined() { Dep.watch.add(this) } notify() { this.subs.forEach((e, i) => { if (typeof e.update === 'function') { try { e.update.apply(e) } catch (err) { console.warr(err) } } }) } } Dep.watch = null class Watch { constructor(name, fn) { this.name = name this.id = new Date() this.callBack = fn } add(dep) { dep.subs.push(this) } update() { var cb = this.callBack cb(this.name) } } var addHistoryMethod = (function() { var historyDep = new Dep() return function(name) { if (name === 'historychange') { return function(name, fn) { var event = new Watch(name, fn) Dep.watch = event historyDep.defined() Dep.watch = null } } else if (name === 'pushState' || name === 'replaceState') { var method = history[name] return function() { method.apply(history, arguments) historyDep.notify() // logger.info("访问历史|变化") } } } })() window.addHistoryListener = addHistoryMethod('historychange') history.pushState = addHistoryMethod('pushState') history.replaceState = addHistoryMethod('replaceState') window.addHistoryListener('history', function() { const throttleAutoLocation = throttle(m.autoLocation, 500) throttleAutoLocation() }) }, checkBrowserHistory() { window.addEventListener('popstate', () => { m.autoLocation() }) }, throttle(func, delay) { let wait = false return (...args) => { if (wait) { return } func(...args) wait = true setTimeout(() => { wait = false }, delay) } }, getClientHeight() { const bodyHeight = document.body.clientHeight || 0 const docHeight = document.documentElement.clientHeight || 0 return bodyHeight < docHeight ? bodyHeight : docHeight }, // 检查指定HTML元素是否存在 checkElementExistence(selector, maxAttempts, interval) { return new Promise(resolve => { let attempts = 0 const intervalId = setInterval(() => { attempts++ const element = $(selector) if (element.length) { clearInterval(intervalId) resolve(true) } else if (attempts === maxAttempts) { clearInterval(intervalId) resolve(false) } }, interval) }) }, isLogin() { return Boolean(document.cookie.replace(new RegExp(String.raw`(?:(?:^|.*;\s*)bili_jct\s*=\s*([^;]*).*$)|^.*$`), '$1') || null) }, logger: { info(content) { console.info('%c播放页调整', 'color:white;background:#006aff;padding:2px;border-radius:2px', content) }, warn(content) { console.warn('%c播放页调整', 'color:white;background:#ff6d00;padding:2px;border-radius:2px', content) }, error(content) { console.error('%c播放页调整', 'color:white;background:#f33;padding:2px;border-radius:2px', content) }, }, checkPageReadyState(state) { return new Promise((resolve) => { const timer = setInterval(() => { if (document.readyState === state) { clearInterval(timer); resolve(true); } }, 100); }); } } const { is_vip, player_type, offset_top, auto_locate, auto_locate_video, auto_locate_bangumi, click_player_auto_locate, player_offset_top, current_screen_mode, selected_screen_mode, auto_select_video_highest_quality, contain_quality_4k, contain_quality_8k, webfull_unlock, } = { is_vip: getValue('is_vip'), player_type: getValue('player_type'), offset_top: Math.trunc(getValue('offset_top')), auto_locate: getValue('auto_locate'), auto_locate_video: getValue('auto_locate_video'), auto_locate_bangumi: getValue('auto_locate_bangumi'), click_player_auto_locate: getValue('click_player_auto_locate'), player_offset_top: Math.trunc(getValue('player_offset_top')), current_screen_mode: getValue('current_screen_mode'), selected_screen_mode: getValue('selected_screen_mode'), auto_select_video_highest_quality: getValue('auto_select_video_highest_quality'), contain_quality_4k: getValue('contain_quality_4k'), contain_quality_8k: getValue('contain_quality_8k'), webfull_unlock: getValue('webfull_unlock'), } const m = { // 初始化设置参数 initValue() { const value = [{ name: 'is_vip', value: false, }, { name: 'player_type', value: 'video', }, { name: 'offset_top', value: 7, }, { name: 'player_offset_top', value: 160, }, { name: 'auto_locate', value: true, }, { name: 'auto_locate_video', value: true, }, { name: 'auto_locate_bangumi', value: true, }, { name: 'click_player_auto_locate', value: true, }, { name: 'current_screen_mode', value: 'normal', }, { name: 'selected_screen_mode', value: 'wide', }, { name: 'auto_select_video_highest_quality', value: true, }, { name: 'contain_quality_4k', value: false, }, { name: 'contain_quality_8k', value: false, }, { name: 'webfull_unlock', value: false, }, ] value.forEach(v => { if (getValue(v.name) === undefined) { setValue(v.name, v.value) } }) }, // 检查视频资源是否加载完毕并处于可播放状态 async checkVideoCanPlayThrough() { const BwpVideoPlayerExists = await checkElementExistence('bwp-video', 10, 10) if (BwpVideoPlayerExists) { return new Promise(resolve => { resolve(true) }) } return new Promise(resolve => { const checkTimeout = setTimeout(() => { // logger.error('视频资源|脚本检测失败|重载页面') // location.reload(true) resolve(false) }, 7000) $('#bilibili-player video').on('canplaythrough', () => { // logger.info("视频资源加载|成功") let attempts = 10 const timer = setInterval(() => { const isHidden = $('#bilibili-player .bpx-player-container').attr('data-ctrl-hidden') if (isHidden === 'false') { clearInterval(timer) clearTimeout(checkTimeout) // logger.info(`视频可播放`) // logger.info(`控制条|出现(hidden:${isHidden})`) resolve(true) } else if (attempts <= 0) { clearInterval(timer) clearTimeout(checkTimeout) // logger.error("控制条|检查失败") resolve(false) } // logger.info("控制条|检查中") attempts-- }, 100) }) }) }, // 获取当前视频类型(video/bangumi) getCurrentPlayerType() { const isVideo = currentUrl.includes('www.bilibili.com/video') || currentUrl.includes('www.bilibili.com/list/watchlater') const isBangumi = currentUrl.includes('www.bilibili.com/bangumi') setValue('player_type', isVideo ? 'video' : isBangumi && 'bangumi') }, // 获取当前屏幕模式(normal/wide/web/full) async getCurrentScreenMode() { const exists = await checkElementExistence('#bilibili-player .bpx-player-container', 10, 100) if (exists) { const screenMode = $('#bilibili-player .bpx-player-container').attr('data-screen') return Promise.resolve(screenMode) } else return Promise.resolve(false) }, // 监听屏幕模式变化(normal/wide/web/full) watchScreenModeChange() { const screenModObserver = new MutationObserver(mutations => { const playerDataScreen = $('#bilibili-player .bpx-player-container').attr('data-screen') setValue('current_screen_mode', playerDataScreen) }) screenModObserver.observe($('#bilibili-player .bpx-player-container')[0], { attributes: true, attributeFilter: ['data-screen'], }) }, // 判断自动切换屏幕模式是否切换成功 async checkScreenModeSuccess(expect_mode) { const current_screen_mode = await this.getCurrentScreenMode() const player_data_screen = $('#bilibili-player .bpx-player-container').attr('data-screen') const equal = new Set([ expect_mode, selected_screen_mode, current_screen_mode, player_data_screen, ]).size === 1 return Promise.resolve(equal) }, // 自动选择屏幕模式 autoSelectScreenMode() { autoSelectScreenModeTimes++ if (autoSelectScreenModeTimes === 1) { const $wideEnterBtn = player_type === 'video' ? $('.bpx-player-ctrl-wide-enter') : $('.squirtle-widescreen-inactive') const $webEnterBtn = player_type === 'video' ? $('.bpx-player-ctrl-web-enter') : $('.squirtle-pagefullscreen-inactive') const selectModeBtn = selected_screen_mode === 'wide' ? $wideEnterBtn : $webEnterBtn const expect_mode = selected_screen_mode === 'wide' ? 'wide' : 'web' let attempts = 3 selectModeBtn.click() const checkScreenMode = async (expect_mode) => { const success = await this.checkScreenModeSuccess(expect_mode) if (success) { clearInterval(checkScreenModeInterval) setValue('current_screen_mode', selected_screen_mode) return { done: true, mode: selected_screen_mode, } } else { selectModeBtn.click() logger.warn('自动选择屏幕模式失败正在重试') attempts-- if (attempts === 0) location.reload(true) } } let checkScreenModeInterval = setInterval(checkScreenMode, 100, expect_mode) return new Promise(resolve => { checkScreenMode(expect_mode).then(result => { resolve(result) }) }) } }, // 网页全屏解锁 fixedWebfullUnlockStyle() { webfullUnlockTimes++ if (webfullUnlockTimes === 1) { const clientHeight = getClientHeight() $('body.webscreen-fix').css({ 'padding-top': clientHeight, position: 'unset', }) $('#bilibili-player.mode-webscreen').css({ height: clientHeight, position: 'absolute', }) $('#app').prepend($('#bilibili-player.mode-webscreen')) $('#playerWrap').css('display', 'none') logger.info('网页全屏解锁成功') setValue('current_screen_mode', 'web') this.insertGoToCommentsButton() // 退出网页全屏 $('.bpx-player-ctrl-btn-icon.bpx-player-ctrl-web-leave').click(function() { $('body').css({ 'padding-top': 0, position: 'auto', }) $('#playerWrap').css('display', 'block') const playerWrapHeight = $('#playerWrap').height() $('#bilibili-player').css({ height: playerWrapHeight, position: 'unset', }) $('#playerWrap').append($('#bilibili-player.mode-webscreen')) setValue('selected_screen_mode', 'wide') this.autoLocation() setValue('selected_screen_mode', 'web') $('.float-nav-exp .mini').css('display', '') }) // 再次进入网页全屏 $('.bpx-player-ctrl-btn-icon.bpx-player-ctrl-web-enter').click(function() { $('body').css({ 'padding-top': clientHeight, position: 'unset', }) $('#bilibili-player').css({ height: clientHeight, position: 'absolute', }) $('#app').prepend($('#bilibili-player')) $('#playerWrap').css('display', 'none') $('.float-nav-exp .mini').css('display', 'none') $('#danmukuBox').css('margin-top', '20px') $('html,body').scrollTop(0) }) } }, // 插入跳转评论按钮 insertGoToCommentsButton() { insertGoToCommentsButtonTimes++ if (player_type === 'video' && webfull_unlock && insertGoToCommentsButtonTimes === 1) { const goToCommentsBtnHtml = `
` $('.bpx-player-control-bottom-right').append(goToCommentsBtnHtml) $('#goToComments').on('click', function(event) { event.stopPropagation() $('body,html').scrollTop($('#comment').offset().top - 10) logger.info('到达评论区') }) } }, // 添加返回播放器按钮 async insertBackToPlayerButton() { const playerDataScreen = await this.getCurrentScreenMode() if (player_type === 'video') { const locateButtonHtml = `
\n
` const floatNav = $('.fixed-sidenav-storage .back-to-top-wrap') const locateButton = $('.storable-items .fixed-sidenav-storage-item.locate') // $('.fixed-sidenav-storage').css('bottom', '274px') const dataV = floatNav[0].attributes[1].name const locateButtonHtmlDataV = locateButtonHtml.replace(`title="定位至播放器"`, `title="定位至播放器" ${dataV}`) floatNav.prepend(locateButtonHtmlDataV) locateButton.not(':first-child').remove() floatNav.on('click', '.locate', function() { $('html,body').scrollTop(playerDataScreen !== 'web' ? player_offset_top - offset_top : 0) }) } if (player_type === 'bangumi') { const locateButtonHtml = `
\n
` const floatNav = $('.nav-tools') const locateButton = $('.nav-tools .tool-item.locate') floatNav.prepend(locateButtonHtml) locateButton.not(':first-child').remove() floatNav.on('click', '.locate', function() { $('html,body').scrollTop(playerDataScreen !== 'web' ? player_offset_top - offset_top : 0) }) } }, // 自动定位至播放器 autoLocation() { const $player = $('#bilibili-player') const player_offset_top = Math.trunc($player.offset().top) setValue('player_offset_top', player_offset_top) return new Promise(resolve => { const isAutoLocate = auto_locate && ((!auto_locate_video && !auto_locate_bangumi) || (auto_locate_video && player_type === 'video') || (auto_locate_bangumi && player_type === 'bangumi')) if (!isAutoLocate || selected_screen_mode === 'web') { resolve(false) return } const scrollToPlayer = () => { $('html,body').scrollTop(player_offset_top - offset_top) } scrollToPlayer() const applyAutoLocationInterval = setInterval(() => { scrollToPlayer() logger.warn(`自动定位失败,继续尝试 ----------------- 当前文档顶部偏移量:${$(document).scrollTop()} 期望文档顶部偏移量:${player_offset_top - offset_top} 播放器顶部偏移量:${player_offset_top} 设置偏移量:${offset_top}`) }, 200) const checkAutoLocationStatus = setInterval(() => { const document_scroll_top = $(document).scrollTop() const success = document_scroll_top === player_offset_top - offset_top if (success) { clearInterval(checkAutoLocationStatus) clearInterval(applyAutoLocationInterval) // logger.info("自动定位成功"); resolve(true) } }, 100) }) }, // 点击播放器自动定位至播放器 async clickPlayerAutoLocation() { const playerDataScreen = await this.getCurrentScreenMode(); if (click_player_auto_locate) { $('#bilibili-player').on('click', handleClick); function handleClick(event) { event.stopPropagation(); if ($(this).attr('status') === 'adjustment-mini') { logger.info('点击迷你播放器'); } else { const scrollTop = playerDataScreen !== 'web' ? player_offset_top - offset_top : 0; $('html,body').scrollTop(scrollTop); } } } }, // 点击时间锚点自动返回播放器 jumpVideoTime() { const video = $('#bilibili-player video')[0] const clickTarget = player_type === 'video' ? '#comment' : '#comment_module' const $clickTarget = $(clickTarget) $clickTarget.unbind('click').on('click', '.video-time,.video-seek', function(event) { event.stopPropagation() const targetTime = $(this).attr(player_type === 'video' ? 'data-video-time' : 'data-time') video.currentTime = targetTime video.play() $('html,body').scrollTop(selected_screen_mode === 'web' ? 0 : player_offset_top - offset_top) }) }, // 自动取消静音 autoCancelMute() { autoCancelMuteTimes++ const cancelMuteButtn = player_type === 'video' ? $('.bpx-player-ctrl-muted-icon') : $('.squirtle-volume-wrap .squirtle-volume .squirtle-volume-icon') const cancelMuteButtnDisplay = cancelMuteButtn.css('display') const cancelMuteButtnClass = cancelMuteButtn.attr('class') if (autoCancelMuteTimes === 1) { if (player_type === 'video' && cancelMuteButtnDisplay === 'block') { cancelMuteButtn.click() logger.info('已自动取消静音') } if (player_type === 'bangumi' && cancelMuteButtnClass.includes('squirtle-volume-mute-state')) { cancelMuteButtn.click() logger.info('已自动取消静音') } } }, // 自动选择最高画质 autoSelectVideoHightestQuality() { autoSelectVideoHightestQualityTimes++; if (!auto_select_video_highest_quality) return; if (autoSelectVideoHightestQualityTimes === 1) { let qualityValue, message; switch (player_type) { case 'video': if (is_vip) { if (!contain_quality_4k && !contain_quality_8k) { qualityValue = $('.bpx-player-ctrl-quality > ul > li').filter(function() { const qualityText = $(this).children('span.bpx-player-ctrl-quality-text').text(); return (!qualityText.includes('4K') && !qualityText.includes('8K')) }); message = '最高画质|VIP|不包含4K及8K|切换成功'; } else if (contain_quality_4k && contain_quality_8k) { qualityValue = $('.bpx-player-ctrl-quality > ul > li').filter(function() { return $(this).children('span.bpx-player-ctrl-quality-text').text().includes('8K') }); message = '最高画质|VIP|8K|切换成功'; } else if (contain_quality_4k && !contain_quality_8k) { qualityValue = $('.bpx-player-ctrl-quality > ul > li').filter(function() { return $(this).children('span.bpx-player-ctrl-quality-text').text().includes('4K') }); message = '最高画质|VIP|4K|切换成功'; } else if (!contain_quality_4k && contain_quality_8k) { qualityValue = $('.bpx-player-ctrl-quality > ul > li').filter(function() { return $(this).children('span.bpx-player-ctrl-quality-text').text().includes('8K') }); message = '最高画质|VIP|8K|切换成功'; } qualityValue.eq(0).click(); } else { const selectVipItemLength = $('.bpx-player-ctrl-quality > ul > li').children('.bpx-player-ctrl-quality-badge-bigvip').length; $('.bpx-player-ctrl-quality > ul > li').eq(selectVipItemLength).click(); message = '最高画质|非VIP|切换成功'; } break; case 'bangumi': if (is_vip) { if (contain_quality_4k) { $('.squirtle-quality-wrap >.squirtle-video-quality > ul > li').eq(0).click(); message = '最高画质|VIP|包含4K|切换成功'; } else { qualityValue = $('.squirtle-quality-wrap > .squirtle-video-quality > ul > li').filter(function() { const qualityText = $(this).children('.squirtle-quality-text-c').children('.squirtle-quality-text').text(); return (!qualityText.includes('4K') && !qualityText.includes('8K')) }); qualityValue.eq(0).click() message = '最高画质|VIP|不包含4K|切换成功'; } } else { const selectVipItemLength = $('.squirtle-quality-wrap >.squirtle-video-quality > ul > li').children('.squirtle-bigvip').length; $('.squirtle-quality-wrap >.squirtle-video-quality > ul > li').eq(selectVipItemLength).click(); message = '最高画质|非VIP|切换成功'; } break; default: break; } logger.info(message); } }, // 添加样式文件 addPluginStyle() { const style = ` #playerAdjustment { height: 500px; overflow: auto; overscroll-behavior: contain; padding-right: 10px; } .swal2-popup { width: 34em !important; padding: 1.25em !important; } .swal2-html-container { margin: 0 !important; padding: 16px 5px 0 !important; width: 100% !important; box-sizing: border-box !important; } .swal2-footer { flex-direction: column !important; } .swal2-close { top: 5px !important; right: 3px !important; } .swal2-actions { margin: 7px auto 0 !important; } .swal2-styled.swal2-confirm { background-color: #23ade5 !important; } .swal2-icon.swal2-info.swal2-icon-show { display: none !important; } .player-adjustment-container, .swal2-container { z-index: 999999999 !important; } .player-adjustment-popup { font-size: 14px !important; } .player-adjustment-setting-label { display: flex !important; align-items: center !important; justify-content: space-between !important; padding-top: 10px !important; } .player-adjustment-setting-checkbox { width: 16px !important; height: 16px !important; } .player-adjustment-setting-tips { width: 100% !important; display: flex !important; align-items: center !important; padding: 5px !important; margin-top: 10px !important; background: #f5f5f5 !important; box-sizing: border-box !important; font-size: 14px !important; color: #666 !important; border-radius: 2px !important; text-align: left !important; } .player-adjustment-setting-tips svg { margin-right: 5px !important; } label.player-adjustment-setting-label input { border: 1px solid #cecece !important; background: #fff !important; } label.player-adjustment-setting-label input[type=checkbox], label.player-adjustment-setting-label input[type=radio] { width: 16px !important; height: 16px !important; } label.player-adjustment-setting-label input:checked { border-color: #1986b3 !important; background: #23ade5 !important; } .auto-quality-sub-options, .auto-locate-sub-options { display: flex; align-items: center; padding-left: 15px; } .auto-quality-sub-options label.player-adjustment-setting-label.fourK, .auto-locate-sub-options label.player-adjustment-setting-label.video { margin-right: 10px; } .auto-quality-sub-options .player-adjustment-setting-label input[type="checkbox"] { margin-left: 5px !important; } .player-adjustment-setting-label.screen-mod input { margin-right: 5px !important; } #biliMainHeader { height:64px!important; } #viewbox_report { height:106px!important; padding-top:24px!important; } #v_upinfo { height:80px!important; } .members-info-v1 { padding-top:0!important; } .members-info-v1 .wide-members-header { height:0!important; } .members-info-v1 .wide-members-container .up-card .info-tag { display:none!important; } .fixed-sidenav-storage-item.locate { width:40px!important; height:40px!important; } ` const addStyleToHead = () => { addStyle('swal-pub-style', 'style', GM_getResourceText('swalStyle')) addStyle('player-adjustment-style', 'style', style) } if (document.head) { addStyleToHead() } else { const headObserver = new MutationObserver(() => { if (document.head) { headObserver.disconnect() addStyleToHead() } }) headObserver.observe(document.documentElement, { childList: true, subtree: true, }) } }, // 注册脚本设置控件 registerMenuCommand() { GM_registerMenuCommand('设置', () => { const html = `
-> 请如实勾选,否则影响自动选择清晰度
-> 只有勾选自动定位至播放器,才会执行自动定位的功能;勾选自动定位至播放器后,video 和 bangumi 两者全选或全不选,默认在这两种类型视频播放页都执行;否则勾选哪种类型,就只在这种类型的播放页才执行。 -> 播放器距离浏览器窗口默认距离为 ${Math.trunc( $('#bilibili-player').offset().top )};请填写小于 ${Math.trunc( $('#bilibili-player').offset().top )} 的正整数或 0;当值为 0 时,播放器上沿将紧贴浏览器窗口上沿、值为 ${Math.trunc( $('#bilibili-player').offset().top )} 时,将保持B站默认。
播放器默认模式
-> 若遇到不能自动选择播放器模式可尝试点击重置 ->*实验性功能(不稳,可能会有这样或那样的问题):勾选后网页全屏模式下可以滑动滚动条查看下方评论等内容,2秒延迟后解锁(番剧播放页不支持)
->新增迷你播放器显示,不过比较简陋,只支持暂停/播放操作,有条件的建议还是直接使用浏览器自带的小窗播放功能。
-> 网络条件好时可以启用此项,勾哪项选哪项,都勾选8k,否则选择4k及8k外最高画质。
` Swal.fire({ title: '播放页调整设置', html: html, icon: 'info', showCloseButton: true, showDenyButton: true, confirmButtonText: '保存', denyButtonText: '重置', footer: '
如果发现脚本不能用,可能是播放页更新了,请耐心等待适配。

夜间哔哩 - 检查更新
', }).then(res => { res.isConfirmed && location.reload(true) if (res.isConfirmed) { location.reload(true) } else if (res.isDenied) { setValue('current_screen_mode', 'normal') location.reload(true) } }) $('#Is-Vip').change(e => { setValue('is_vip', e.target.checked) $('.fourK,.eightK').css('display', e.target.checked ? 'flex!important' : 'none!important') }) $('#Auto-Locate').change(e => { setValue('auto_locate', e.target.checked) }) $('#Auto-Locate-Video').change(e => { setValue('auto_locate_video', e.target.checked) }) $('#Auto-Locate-Bangumi').change(e => { setValue('auto_locate_bangumi', e.target.checked) }) $('#Top-Offset').change(e => { setValue('offset_top', e.target.value * 1) }) $('#Click-Player-Auto-Location').change(e => { setValue('click_player_auto_locate', e.target.checked) }) $('#Auto-Quality').change(e => { setValue('auto_select_video_highest_quality', e.target.checked) }) $('#Quality-4K').change(e => { setValue('contain_quality_4k', e.target.checked) }) $('#Quality-8K').change(e => { setValue('contain_quality_8k', e.target.checked) }) $('input[name="Screen-Mod"]').click(function() { setValue('selected_screen_mode', $(this).val()) }) $('#Webfull-Unlock').change(e => { setValue('webfull_unlock', e.target.checked) }) }) }, // 冻结视频标题及UP主信息样式 freezeHeaderAndVideoTitleStyles() { $('#biliMainHeader').attr('style', 'height:64px!important') $('#viewbox_report').attr('style', 'height:106px!important;padding-top:24px!important') $('#v_upinfo').attr('style', 'height:80px!important') $('.members-info-v1').attr('style', 'padding-top:0!important') $('.members-info-v1 .wide-members-header').attr('style', 'height:0!important') $('.members-info-v1 .wide-members-container .up-card .info-tag').attr('style', 'display:none!important') }, // 判断当前窗口是否在最上方 isTopWindow() { return window.self === window.top }, // 前期准备函数 thePrepFunction() { thePrepFunctionRunningTimes++ if (thePrepFunctionRunningTimes === 1) { isLogin() checkBrowserHistory() historyListener() this.initValue() this.addPluginStyle() this.isTopWindow() && this.registerMenuCommand() this.getCurrentPlayerType() this.getCurrentScreenMode() } }, // 主函数 async theMainFunction() { try { theMainFunctionRunningTimes++ if (theMainFunctionRunningTimes === 1) { const videoPlayerExists = await checkElementExistence('#bilibili-player video', 5, 100) || await checkElementExistence('bwp-video', 5, 100) if (videoPlayerExists) { logger.info(`播放器|存在`) $('body').css('overflow', 'hidden') const isPlayable = await this.checkVideoCanPlayThrough() const pageComplete = await checkPageReadyState('complete') if (isPlayable || (!isPlayable && pageComplete)) { logger.info(`视频资源|可以播放`) // console.time('播放页调整:切换模式耗时') this.watchScreenModeChange() await sleep(100) const selectedScreenMode = await this.autoSelectScreenMode() // console.timeEnd('播放页调整:切换模式耗时') if (selectedScreenMode.done) { logger.info(`屏幕模式|${selectedScreenMode['mode'].toUpperCase()}|切换成功`) this.autoCancelMute() // console.time('播放页调整:选择画质耗时') this.autoSelectVideoHightestQuality() // console.timeEnd('播放页调整:选择画质耗时') this.clickPlayerAutoLocation() if (webfull_unlock && selectedScreenMode.mode === 'web') { this.fixedWebfullUnlockStyle() } // console.time('播放页调整:自动定位耗时') this.freezeHeaderAndVideoTitleStyles() const autoLocationDone = await this.autoLocation() // console.timeEnd('播放页调整:自动定位耗时') if (auto_locate && autoLocationDone) { $('body').css('overflow', '') logger.info(`自动定位|成功`) this.insertBackToPlayerButton() this.jumpVideoTime() } if (!auto_locate || (auto_locate && auto_locate_bangumi && !auto_locate_video && player_type === 'video') || (auto_locate && auto_locate_video && !auto_locate_bangumi && player_type === 'bangumi')) { $('body').css('overflow', '') logger.info(`自动定位|未开启`) } if (player_type === 'video') { const loaded = await checkElementExistence('#comment > .comment > .bili-comment', 10, 100) await sleep(100) if (loaded) { logger.info(`页面加载|完毕`) } else { location.reload(true) } } } else { logger.error(`屏幕模式|${selectedScreenMode.mode}|切换失败`) location.reload(true) } } else { logger.error(`视频资源|加载失败`) location.reload(true) } } else { logger.error(`播放器|不存在`) location.reload(true) } } } catch (error) { logger.error(error) location.reload(true) } }, } if (isLogin()) { m.thePrepFunction() m.theMainFunction() } else logger.warn('请登录|本脚本只能在登录状态下使用') })