在线云课堂(腾讯、网易、慕课网...)增加多倍速/去除xxx正在播放/自动播放下一条视频

腾讯课堂、慕课网、网易云课堂添加多倍速播放(默认最大 2 倍速,支持到 4 倍速)/自动播放下一个视频(携带上一个视频的倍速);腾讯课堂去除漂浮水印;

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @icon         http://9.url.cn/edu/lego_modules/edu-ui/0.0.1/img/nohash/logo_pc_rich.png
// @name         在线云课堂(腾讯、网易、慕课网...)增加多倍速/去除xxx正在播放/自动播放下一条视频
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  腾讯课堂、慕课网、网易云课堂添加多倍速播放(默认最大 2 倍速,支持到 4 倍速)/自动播放下一个视频(携带上一个视频的倍速);腾讯课堂去除漂浮水印;
// @author       Bamboo
// @include      /^http(s?)://www.imooc.com/(.*)$/
// @include      /^http(s?)://ke.qq.com/(.*)$/
// @include      /^http(s?)://study.163.com/(.*)$/
// @match        *://ke.qq.com/webcourse/*
// @match        *://study.163.com/course/*
// @require      http://libs.baidu.com/jquery/2.0.0/jquery.min.js
// @run-at       document-end
// @license MIT
// ==/UserScript==
var website_url = window.location.href || document.location.href;
var website_host = window.location.host || document.location.host;

/**
 * 网易云课堂
 */
var StudyWy = {
    //添加多倍速播放
    addWyExtSpeedPlay() {
        $('.m-popover-rate').css('display', 'none');
        let appendHtml = '<select class="changePlayRateSelect" style="margin-left: 50px">' +
            '<option value="0.5">0.5倍速</option>' +
            '<option value="0.75">0.75倍速</option>' +
            '<option value="1">1倍速</option>' +
            '<option value="1.25">1.25倍速</option>' +
            '<option value="1.5">1.5倍速</option>' +
            '<option value="2">2倍速</option>' +
            '<option value="2.5">2.5倍速</option>' +
            '<option value="3">3倍速</option>' +
            '<option value="3.5">3.5倍速</option>' +
            '<option value="4">4倍速</option>' +
			'<option value="4.5">4.5倍速</option>' +
			'<option value="5">5倍速</option>' +
			'<option value="5.5">5.5倍速</option>' +
			'<option value="6">6倍速</option>' +
			'<option value="6.5">6.5倍速</option>' +
			'<option value="7">7倍速</option>' +
            '</select>';
        $('.j-aotoplaybox').after(appendHtml);
    }
}

/**
 * 腾讯课堂
 */
var Bamboo = {
    /**
    * 根据属性获取标签,列表返回。
    * tagName 要获取元素的标签
    * attrName 属性名
    * attrVal 属性值
    **/
    getDom(tagName, attrName, attrVal) {
        var selectElement = [];
        var element = document.getElementsByTagName(tagName);
        for (var i = 0; i < element.length; i++) {
            var tmpVal = element[i].getAttribute(attrName);
            if (attrVal === tmpVal) {
                selectElement.push(element[i]);
            }
        }

        return selectElement;
    },
    /**
    * 根据父 dom 元素获取子 dom 元素,
    * parentDom 要获取的父 dom 元素
    * tagName 要获取的子 dom 的标签
    * index 要获取子 dom 的索引(第几个元素,默认第 1 个元素-index=0)
    **/
    getChildDom(parentDom, tagName, index) {
        var children = parentDom.getElementsByTagName(tagName);
        if (children) {
            if (index) {
                return children[index]
            }
            return children[0]
        }
        return null;
    },
    removeWatermark() {
        var head = document.head
        var style = document.createElement("style")
        style.type = "text/css"
        var css = [
            "a[class*='marquee animation'],txpdiv[class*='player-inject'] {",
            "    display: none!important;",
            "}",
            "#x-tcp-container > txpdiv {",
            "    display: none!important;",
            "}",
        ].join("\n")
        var text = document.createTextNode(css)
        style.appendChild(text)
        head.appendChild(style)
    },
    liClickEvent() {
        var tmpList = document.querySelectorAll("div.loki-playbackrate");
        var tmpUlList;
        for (var i = 0; i < tmpList.length; i++) {
            var tmp = Bamboo.getChildDom(tmpList[i], 'ul');

            if (tmp) {
                tmpUlList = tmp
            }
        }

        var childNodes = tmpUlList.childNodes;
        for (var j = 0; j < childNodes.length; j++) {
            var li = childNodes[j];
            var attrVal = li.getAttribute("loki-menu-selected");
            var classAttrVal = li.getAttribute("class");
            if (classAttrVal && classAttrVal.indexOf('loki-menu-selected') > -1) {
                li.setAttribute('class', classAttrVal.substring(0, classAttrVal.indexOf('loki-menu-selected') - 1));
            }
        }
        var rateDiv = document.querySelector("div.loki-playbackrate");
		var rateVal = rateDiv.querySelectorAll('button.loki-rate-button')
        var classVal = this.getAttribute('class')
        classVal = classVal.concat("loki-menu-selected");

        var selectSpeedText = this.innerText;
        var selectSpeed = 1;
        rateVal[0].innerText = selectSpeedText;
        if (selectSpeedText) {
            selectSpeed = selectSpeedText.replace(/x/, '').replace(/倍/, '')
        }

        var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
        if (video) {
            video.play();
            video.playbackRate = selectSpeed;
        }
    },
    initFunc(){
        console.log('initFunc ----- bamboo')
        var ulList;
        //定义播放速度列表
        var extSpeedArr = [0.8, 1, 1.25, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7];
        var playSpeedList = document.querySelectorAll("div.loki-playbackrate");
        var button;
        for (var i = 0; i < playSpeedList.length; i++) {
            var tmp = Bamboo.getChildDom(playSpeedList[i], 'ul');
            var tmp1 = Bamboo.getChildDom(playSpeedList[i], 'button');
            if (tmp) {
                ulList = tmp
            }
            if (tmp1) {
                button = tmp1;
            }
        }
		if (!ulList || !ulList.innerHTML) {
			return
		}
        ulList.innerHTML = '';

        for (var j = 0; j < extSpeedArr.length; j++) {
            var appendLi = document.createElement('li');
            appendLi.setAttribute('class', 'vjs-menu-item')
            appendLi.setAttribute('tabindex', '-1')
            appendLi.setAttribute('role', 'menuitemcheckbox')
            appendLi.setAttribute('aria-live', 'polite')
            appendLi.setAttribute('aria-disabled', 'false')
            appendLi.setAttribute('aria-checked', 'false')

            var liSpan1 = document.createElement('span');
            liSpan1.setAttribute('class', 'vjs-menu-item-text');
            liSpan1.innerText = extSpeedArr[j] + 'x';
            appendLi.appendChild(liSpan1);

            var liSpan2 = document.createElement('span');
            liSpan2.setAttribute('class', 'vjs-control-text');
            appendLi.appendChild(liSpan1);
            appendLi.appendChild(liSpan2);

            ulList.append(appendLi)

            if (appendLi.addEventListener) {
                appendLi.addEventListener("click", Bamboo.liClickEvent, false);
            }
            if (appendLi.attachEvent) {
                appendLi.attachEvent("onclick", Bamboo.liClickEvent);
            }
        }
    }
};

/**
 * imooc 网
 */
//imooc 添加多倍速播放
let Mooc = {
    moocLiClickEvent(obj) {
        $(obj).parent().find('li').removeClass('current')
        $(obj).addClass('current');

        var currentSpeedText = $(obj).text();
        var currentSpeed = currentSpeedText.replace(/[^0-9]/ig, '');
        var cssAttrs = $('.vjs-playback-rate-value').attr('class');
        var rateNum = cssAttrs.replace(/[^0-9]/ig, '');

        $('.vjs-playback-rate-value').removeClass('rate' + rateNum + 'x').addClass('rate' + (currentSpeed * 10 > 100 ? (currentSpeed * 10 / 10) : currentSpeed * 10) + 'x')

        if (currentSpeed.length == 2) {
            currentSpeed = currentSpeed / 10;
        } else if (currentSpeed.length == 3) {
            currentSpeed = currentSpeed / 100;
        }
        $('.vjs-playback-rate-value').css('background-image', 'url()');
        $('.vjs-playback-rate-value').text(currentSpeed + 'x');

        var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
        if (video) {
            video.play();
            video.playbackRate = currentSpeed;
        }
    },
    addMoocExtSpeedPlay() {
        var extSpeedArr = ['2.5x', '3x', '3.5x', '4x','4.5x','5x','5.5x','6x','6.5x','7x'];
        var ulList = $('#vjsMenu').children('ul')
        var appendHtml = '<li class="vjs-menu-item" tabindex="-1" role="menuitem" aria-live="polite">?<span class="vjs-control-text"></span><i class="imv2-check"></i></li>';
        for (var i = 0; i < extSpeedArr.length; i++) {
            var appendLi = appendHtml.replace('?', extSpeedArr[i]);
            ulList.prepend(appendLi)
        }

        $('ul.vjs-menu-content').on('click', 'li', function () { //只要改这一行就可以了
            Mooc.moocLiClickEvent(this);
        });
    }
}

    ; (function () {
        'use strict';
        //网易云课堂
        if (website_host.indexOf('study.163.com') > -1) {
            setTimeout(function () {
                try {
                    StudyWy.addWyExtSpeedPlay();
                    $(document).ready(function () {
                        let speedText = $('.j-ratebtn_text').text().replace(/x/, '');
                        $(".changePlayRateSelect").find("option[value='" + speedText + "']").attr("selected", true);

                        $('.changePlayRateSelect').change(function () {
                            var val = $(this).children('option:selected').val();//这就是selected的值
                            $('.j-ratebtn_text').text(val + 'x');
                            var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
                            if (video) {
                                video.play();
                                video.playbackRate = val;
                            }
                        })
                    });

                    //自动播放下一个视频
                    var studyLoop = setInterval(function () {
                        let replayTxt = $('.j-replay').css('display');
                        if (replayTxt == 'block') {
                            document.getElementById("j-next").click();

                            setTimeout(() => {
                                //重置速度与显示,以及隐藏倍速切换
                                $('.m-popover-rate').css('display', 'none');

                                let speedVal = $('.changePlayRateSelect option:selected').val()
                                $('.j-ratebtn_text').text(speedVal + 'x');
                                var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
                                if (video) {
                                    video.play();
                                    video.playbackRate = speedVal;
                                }
                            }, 3000);
                        }
                    }, 1000);
                } catch (error) {
                }
            }, 5000);
        }

        //腾讯课堂
        if (website_host.indexOf('ke.qq.com') > -1) {
            try {
                Bamboo.removeWatermark();
                setTimeout(Bamboo.initFunc, 5000);


                //自动播放下一个视频
                var qqLoop = setInterval(function () {
                    if ($('.next-btn') != null && $('.next-btn') != undefined && $('.next-btn').length > 0) {
                        $('.next-btn').click();

                        let speedVal = $('.loki-playbackrate .loki-rate-button').html().replace(/x/, '');
                        setTimeout(() => {
                            if (speedVal != undefined && /[0-9]{1}\.{0,1}[0-9]{0,2}/.test(speedVal)) {
                                var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
                                if (video) {
                                    console.log('speedVal:' + speedVal)
                                    video.play();
                                    video.playbackRate = speedVal;
                                    Bamboo.initFunc();
                                }
                            }
                        }, 3000);
                    }
                }, 1000);
            } catch (error) {
            }
        }

        // 慕课网
        if (website_host.indexOf('imooc.com') > -1) {
            try {
                //imooc 自动播放下一条视频 参考372498,不过有的失效的地方我已经改掉
                var nextMask = document.querySelector('div.next-box.J_next-box');
                var moocLoop = setInterval(function () {
                    if (!nextMask.classList.contains('hide')) {
                        //写入 cookie
                        let speedVal = $('.vjs-playback-rate-value').html().replace(/x/, '');
                        let cookieVal = document.cookie;
                        if (cookieVal.indexOf('backPlayRate') > -1) {
                            let oldSpeedVal = cookieVal.split(";")[0].split("=")[1];
                            if (speedVal != oldSpeedVal ){
                                cookieVal = cookieVal.substring(cookieVal.indexOf(';'));
                                document.cookie = 'backPlayRate=' + speedVal + ';' + cookieVal;
                            }
                        } else {
                            document.cookie = 'backPlayRate=' + speedVal + ';' + cookieVal;
                        }

                        document.querySelector('span.J-next-btn.next-auto.moco-btn.moco-btn-green').click();
                    }
                }, 1000);
                //添加多倍速菜单
                setTimeout(function () {
                    Mooc.addMoocExtSpeedPlay();

                    //读取 cookie 设置播放速度
                    let cookieVal = document.cookie;
                    if (cookieVal.indexOf('backPlayRate') > -1) {
                        let speedVal = cookieVal.split(";")[0].split("=")[1];
                        if (speedVal != null && speedVal != undefined && /[0-9]{1}\.{0,1}[0-9]{0,2}/.test(speedVal)) {
                            var cssAttrs = $('.vjs-playback-rate-value').attr('class');
                            var rateNum = cssAttrs.replace(/[^0-9]/ig, '');

                            $('.vjs-playback-rate-value').removeClass('rate' + rateNum + 'x').addClass('rate' + (speedVal * 10 > 100 ? (speedVal * 10 / 10) : speedVal * 10) + 'x')

                            $('.vjs-playback-rate-value').css('background-image', 'url()');
                            $('.vjs-playback-rate-value').text(speedVal + 'x');

                            var video = document.getElementsByTagName("video")[0] || document.getElementById("videoPlayer") || document.querySelector('video');
                            if (video) {
                                video.play();
                                video.playbackRate = speedVal;
                            }
                        }
                    }
                }, 3000)
            } catch (error) {
            }
        }
    })();