// ==UserScript== // @name Bilibili - 自动切换直播画质至最高画质 // @namespace https://bilibili.com/ // @version 0.5 // @description 自动切换Bilibili直播画质至最高画质 | V0.5 修复无法在未登录的情况下切换画质的问题 // @license GPL-3.0 // @author DD1969 // @match https://live.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant GM_xmlhttpRequest // @grant unsafeWindow // @noframes // @downloadURL none // ==/UserScript== (async function() { 'use strict'; // jump to actual room if live streaming is nested setInterval(() => { const nestedPage = document.querySelector('iframe[src*=blanc]'); if (nestedPage) unsafeWindow.location.href = nestedPage.src; }, 200); // set target quality to 1080p const targetQualityNumber = "10000"; // hide the loading gif const styleElement = document.createElement('style'); styleElement.textContent = `.web-player-loading { opacity: 0; }`; document.head.appendChild(styleElement); // wait until cookie and livePlayer loaded await new Promise(resolve => { const timer = setInterval(() => { if (document.cookie && unsafeWindow.livePlayer && unsafeWindow.livePlayer.getPlayerInfo && unsafeWindow.livePlayer.switchQuality) { clearInterval(timer); resolve(); } }, 200); }); // get room ID const roomID = await fetch(`https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=${location.pathname.split('/').pop()}`) .then(res => res.json()) .then(json => json.data.room_info.room_id); // get data from API const roomPlayInfo = await new Promise(resolve => { GM_xmlhttpRequest({ method: 'GET', url: `https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id=${roomID}&protocol=0,1&format=0,1,2&codec=0,1,2&qn=${targetQualityNumber}&platform=web&ptype=8&dolby=5&panorama=1`, headers: { 'Cookie': '\n' }, responseType: 'json', onload: res => resolve(res.response) }); }); // get target codec const targetCodec = roomPlayInfo .data .playurl_info .playurl .stream .find(stream => stream.protocol_name === 'http_hls') .format .find(format => format.format_name === 'fmp4') .codec .find(codec => codec.codec_name === 'avc'); // override 'find' method of Array to change the processing codec config const originFind = Array.prototype.find; Array.prototype.find = function(func) { if (this.some(item => item.codec_name === 'avc')) { return originFind.call([targetCodec], func); } return originFind.call(this, func); } // override 'split' method of String to change the processing cookie string const originSplit = String.prototype.split; String.prototype.split = function (spliter) { let str = this; if (spliter === ';' && str.length > 0) str += '; DedeUserID=123456'; return originSplit.call(str, spliter); } // switch quality const { quality } = unsafeWindow.livePlayer.getPlayerInfo(); if (quality !== targetQualityNumber) { unsafeWindow.livePlayer.switchQuality(targetQualityNumber); setTimeout(() => unsafeWindow.livePlayer.reload(), 2000); } })();