Add volume overdrive

This commit is contained in:
the1812 2020-07-04 16:17:20 +08:00
parent 1f3bfb458d
commit 1bc1407df5
10 changed files with 180 additions and 12 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -198,8 +198,8 @@
"settings-tooltip.min.css": "0C138D5CF16B9068E73D173D229B2B458C15F50272DA73D6A580921C5A848845",
"settings-tooltip.min.js": "E9ABA72B3C29CA850342109E57B055B193F3356DD59876B202E8E908AE6247C9",
"settings-tooltip.zh-CN.min.js": "C237FB86DE05C28C1EB8A11EAE85D4F79D942937C6DD8BD2D4D900FCC99B930B",
"show-cover-before-play.min.css": "E963B5E47F0FF5F283CE2C2621DF7AD13A97C619386F2807021E57544233B08F",
"show-cover-before-play.min.js": "7CB9F6D6F4F0C6DF2D5D251306314D055C53FF9992C4DDB6E5A6A2B2F22A641A",
"show-cover-before-play.min.css": "E4050D66F8014029270CB5A4DEFDE2F847B095BA9ED4274BFED3E131B737B06D",
"show-cover-before-play.min.js": "1460F247A0DCE097C0F7B4977D6D060D4644862D9F2AE774F3F6F1E41469D12A",
"show-dead-video-title.min.js": "8D591930421EBA43A1BDF50DC8B645C1BD1A17E109FB1CFBCD6B78E6C74E1D68",
"simple-home.vue.min.js": "1F5CF46DEE65549A30C5F0790578EED0C6B3AD6C5F20D9B88CD745C4B7664ABB",
"simple-home-bangumi-category.vue.min.js": "87DCA2C8295CAD66C9FA01D65437EC2F9DD5E7F4A565B4384ABAB1746A6787EE",
@ -242,6 +242,7 @@
"video-list.vue.min.js": "90C4CCAB3C9C3FB0CFE39C9A9482C3A964EE7FAC17F7FBF682CCC2FEFB6632F2",
"video-story.min.js": "F9D4D2D80997DF5F11BF0CFA4D389B77BDBF1566EA6002E47174B68B440F3C0D",
"view-cover.min.js": "895AA8A393D5EBA787ABCAE12EAF4D47E5A68E6B998E4FE839F81FB491F92ED5",
"volume-overdrive.min.js": "442428F9918086D86AD90966071E37298F4C726883232F627C6B6E15AAB4F6D0",
"watchlater.min.js": "940646B8DEAC0B2C47BACD360A259DFCF9F67F78E4B9D38ACE9E8D7322E88016",
"watchlater-api.min.js": "0A341429EFB4489594C6670A1FEEF99E7EC2564FF18BCE3A679E98101BA0F2F4",
"watchlater-expire-warnings.min.js": "99282802EF8EB87F199BDE88240E1F196CD85C77516E8D5466EB6F1939B908DD"

Binary file not shown.

1
min/volume-overdrive.min.js vendored Normal file
View File

@ -0,0 +1 @@
(()=>{return(e,t)=>{const n=new Map;const i=e=>{console.log("create new context");const t=new AudioContext;const i=t.createMediaElementSource(e);const o=t.createGain();i.connect(o);o.connect(t.destination);n.set(e,o.gain);return o.gain};const o=e=>{if(n.has(e)){const t=n.get(e);t.value=1}};const r=(e,t)=>{if(n.has(e)){const i=n.get(e);let o=i.value+t;if(o<0){o=0}i.value=o;return o}else{const n=i(e);const o=n.value+t;n.value=o;return o}};const s=async()=>{const e=["https://www.bilibili.com/bangumi/","https://www.bilibili.com/video/","https://www.bilibili.com/watchlater/","https://www.bilibili.com/medialist/play/"];if(e.every(e=>!document.URL.startsWith(e))){return}let i;const o=e=>{let n=dq(".volume-overdrive-tip");if(!n){const e=dq(".bilibili-player-video-wrap");if(!e){return}e.insertAdjacentHTML("afterbegin",`\n<div class="volume-overdrive-tip-container">\n<i class="mdi mdi-volume-high"></i>\n<div class="volume-overdrive-tip"></div>\n</div>\n`);t.applyStyleFromText(`\n .volume-overdrive-tip-container {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n padding: 8px 16px;\n background-color: #000A;\n color: white;\n pointer-events: none;\n opacity: 0;\n z-index: 100;\n display: flex;\n align-items: center;\n font-size: 14pt;\n border-radius: 4px;\n transition: .2s ease-out;\n }\n .volume-overdrive-tip-container.show {\n opacity: 1;\n }\n .volume-overdrive-tip-container i {\n line-height: 1;\n margin-right: 8px;\n font-size: 18pt;\n }\n`,"volumeOverdriveStyle");n=dq(".volume-overdrive-tip")}const o=dq("video");n.innerHTML=`音量${Math.round(o.volume*100)}% x 增幅${Math.round(e*100)}% = ${Math.round(o.volume*e*100)}%`;if(i){clearTimeout(i)}dq(".volume-overdrive-tip-container").classList.add("show");i=setTimeout(()=>{dq(".volume-overdrive-tip-container").classList.remove("show")},2e3)};Observer.videoChange(async()=>{n.clear();document.body.addEventListener("keydown",e=>{const t=!e.shiftKey&&e.ctrlKey&&!e.altKey&&!e.metaKey;if(t&&(e.key==="ArrowDown"||e.key==="ArrowUp")){const t=dq("video");if(!t){return}const n=e.key==="ArrowDown"?-.1:.1;const i=r(t,n);o(i);e.preventDefault();e.stopImmediatePropagation()}},{capture:true})})};s();return{export:{setVolume:r}}}})();

View File

@ -922,5 +922,11 @@ Resource.manifest = {
showCoverBeforePlay: '播放前显示封面',
},
},
volumeOverdrive: {
path: 'volume-overdrive.min.js',
displayNames: {
volumeOverdrive: '音量增幅',
},
},
}
export const resourceManifest = Resource.manifest

View File

@ -240,6 +240,7 @@ export const settings = {
watchLaterRedirectNavbar: true,
watchLaterRedirectPage: true,
showCoverBeforePlay: false,
volumeOverdrive: false,
cache: {},
}
const fixedSettings = {

View File

@ -0,0 +1,127 @@
const gainMap = new Map<HTMLVideoElement, AudioParam>()
export const getGain = (video: HTMLVideoElement) => {
console.log('create new context')
const context = new AudioContext()
const source = context.createMediaElementSource(video)
const gainNode = context.createGain()
source.connect(gainNode)
gainNode.connect(context.destination)
gainMap.set(video, gainNode.gain)
return gainNode.gain
}
export const resetGain = (video: HTMLVideoElement) => {
if (gainMap.has(video)) {
const gain = gainMap.get(video)!
gain.value = 1
}
}
export const setVolume = (video: HTMLVideoElement, volumeChange: number): number => {
if (gainMap.has(video)) {
const gain = gainMap.get(video)!
let volume = gain.value + volumeChange
if (volume < 0) {
volume = 0
}
gain.value = volume
return volume
} else {
const gain = getGain(video)
const volume = gain.value + volumeChange
gain.value = volume
return volume
}
}
const entry = async () => {
const supportedUrls = [
'https://www.bilibili.com/bangumi/',
'https://www.bilibili.com/video/',
'https://www.bilibili.com/watchlater/',
'https://www.bilibili.com/medialist/play/',
]
if (supportedUrls.every(url => !document.URL.startsWith(url))) {
return
}
/** 音量增幅提示框用的`setTimeout`句柄 */
let showVolumeTipOldTimeout: number
/**
*
* @param volume
*/
const showVolumeTip = (volume: number) => {
let tip = dq('.volume-overdrive-tip') as HTMLDivElement
if (!tip) {
const player = dq('.bilibili-player-video-wrap')
if (!player) {
return
}
player.insertAdjacentHTML('afterbegin', /*html*/`
<div class="volume-overdrive-tip-container">
<i class="mdi mdi-volume-high"></i>
<div class="volume-overdrive-tip"></div>
</div>
`)
resources.applyStyleFromText(`
.volume-overdrive-tip-container {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 8px 16px;
background-color: #000A;
color: white;
pointer-events: none;
opacity: 0;
z-index: 100;
display: flex;
align-items: center;
font-size: 14pt;
border-radius: 4px;
transition: .2s ease-out;
}
.volume-overdrive-tip-container.show {
opacity: 1;
}
.volume-overdrive-tip-container i {
line-height: 1;
margin-right: 8px;
font-size: 18pt;
}
`, 'volumeOverdriveStyle')
tip = dq('.volume-overdrive-tip') as HTMLDivElement
}
const video = dq('video') as HTMLVideoElement
tip.innerHTML = `音量${Math.round(video.volume * 100)}% x 增幅${Math.round(volume * 100)}% = ${Math.round(video.volume * volume * 100)}%`
if (showVolumeTipOldTimeout) {
clearTimeout(showVolumeTipOldTimeout)
}
(dq('.volume-overdrive-tip-container') as HTMLDivElement).classList.add('show')
showVolumeTipOldTimeout = setTimeout(() => {
(dq('.volume-overdrive-tip-container') as HTMLDivElement).classList.remove('show')
}, 2000)
}
Observer.videoChange(async () => {
gainMap.clear()
document.body.addEventListener('keydown', e => {
const ctrlKey = !e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey
if (ctrlKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
const video = dq('video') as HTMLVideoElement
if (!video) {
return
}
const volumeChange = e.key === 'ArrowDown' ? -0.1 : 0.1
const volume = setVolume(video, volumeChange)
showVolumeTip(volume)
e.preventDefault()
e.stopImmediatePropagation()
}
}, { capture: true })
})
}
entry()
export default {
export: {
setVolume,
}
}