Youtube长按倍速脚本

Youtube长按倍速,广告也能倍速/快进跳过。

目前為 2023-08-02 提交的版本,檢視 最新版本

// ==UserScript==
// @license     AGPL License
// @name        Youtube长按倍速脚本
// @name:en     Youtube long press to speed up
// @namespace   Violentmonkey Scripts
// @match       https://www.youtube.com/*
// @run-at      document-start
// @noframes
// @grant       none
// @version     1.6
// @author      n1nja88888
// @description Youtube长按倍速,广告也能倍速/快进跳过。
// @description:en Youtube long press to speed up, also works for ads.
// ==/UserScript==
'use strict'
console.log('n1nja88888 creates this world!')
const _onload = window.onload
window.onload = ()=>{
    if(!!_onload){
        _onload()
    }
    main()
}
 
(function() {
    document._addEventListener = document.addEventListener
 
    // document中就是keydown控制快进这些
    document.addEventListener = function(type,listener,useCapture=false) {
        if(type === 'keydown'){
            // 重写所有添加的listener
            listener = keydownOmit(listener, new Set(['ArrowLeft', 'ArrowRight', ' ']))
            this._addEventListener(type,listener,useCapture)
        }else{
            this._addEventListener(type,listener,useCapture)
        }
    }
 
    // 操作同上,对ELement的事件监听器也重写一遍
    Element.prototype._addEventListener = Element.prototype.addEventListener
    Element.prototype.addEventListener = function(type,listener,useCapture=false) {
        if(type === 'keypress'){
            listener = keydownOmit(listener, new Set(['ArrowLeft', 'ArrowRight', ' ']))
            this._addEventListener(type,listener,useCapture)
        }
        else if(type === 'keydown'){
            listener = keydownOmit(listener, new Set(['ArrowLeft', 'ArrowRight', ' ']))
            this._addEventListener(type,listener,useCapture)
        }
        // declare listener
        else
            this._addEventListener(type,listener,useCapture)
    }
})()
// 判断是否是组合键
function isCombKey(e){
    return e.ctrlKey || e.shiftkey || e.altKey || e.metaKey
}
// 判断传入元素是否为当前页面活动元素
function isActive(eleSet){
    if(!!eleSet[0]){
        for(let i = 0; i < eleSet.length; i++){
            if(document.activeElement === eleSet[i]){
                return true
            }
        }
    }else{
        return document.activeElement === eleSet
    }
    return false
}
//改变keydown事件监听器函数 忽略指定key
function keydownOmit(listener, omits){
    return (...args) => {
        if(!omits.has(args[0].key)){
            listener(...args)
        }
    }
}
//获得有src属性的video
function getVideo(list){
    for (const video of list) {
        if(!!video.getAttribute('src')){
            return video
        }
    }
 
    return null
}
function main(){
    // 倍速定时器
    let timer = null
    //用于记录是否重复按下
    let isPressed = false
    //初始速度,松开按键后是恢复到初始速度
    let initSpeed = -1
 
 
    document._addEventListener('keydown', (e)=>{
        if(isCombKey(e)){
            return
        }
 
        const video = getVideo(document.querySelectorAll('video'))
        if(!video){
            return
        }
 
        // 当前不是在输入框
        if(isActive(document.querySelectorAll('input')) || isActive(document.querySelectorAll('textarea')) || isActive(document.querySelectorAll('#contenteditable-root'))){
            return
        }
        e.preventDefault()
        switch(e.key){
            case 'ArrowLeft':
                video.currentTime -= 5
                break
            case 'ArrowRight':
                if(!timer){
                    isPressed = true
                    timer = setTimeout(()=>{
                            if(isPressed){
                                video.play()
                                initSpeed = video.playbackRate
                                video.playbackRate = 3
                            }
                        },0.15e3)
                }
                break
            // 空格暂停
            case ' ':
                if(video.paused){
                    video.play()
                }else{
                    video.pause()
                }
                break
            // 短视频评论
            case 'c':
            case 'C':
                const comment = document.querySelector('#comments-button button')
                if(!!comment){
                    comment.click()
                }
                break
        }
    })
    document._addEventListener('keyup',(e)=>{
        e.preventDefault()
        const video = getVideo(document.querySelectorAll('video'))
        if(!!video && e.key === 'ArrowRight' && !isActive(document.querySelectorAll('input')) && !isActive(document.querySelectorAll('textarea')) && !isActive(document.querySelectorAll('#contenteditable-root'))){
            e.preventDefault()
            isPressed = false
            clearTimeout(timer)
            timer = null
            if(video.playbackRate === 3){
                video.playbackRate = initSpeed
            }else{
                video.currentTime += 5
                const skip = document.querySelector('.ytp-ad-skip-button-text')
                if(!!skip){
                    skip.click()
                }
            }
        }
    })
}