[25-04-02] 青书学堂自动看课

检测网页视频自动播放并设置0.5倍速,播放完毕后自动下一节课.有问题提Issue,时不时看到会修

目前为 2025-04-02 提交的版本。查看 最新版本

// ==UserScript==
// @name         [25-04-02] 青书学堂自动看课
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  检测网页视频自动播放并设置0.5倍速,播放完毕后自动下一节课.有问题提Issue,时不时看到会修
// @author       Hu5
// @match        *://*.qingshuxuetang.com/*
// ==/UserScript==

(function() {
    'use strict';
    async function main() {
        // 查找所有的课程ID
        const kcjsIds = findAllKcjsIds();
        function findAllKcjsIds() {
            const allElements = document.querySelectorAll('*');
            // 获取文档中的所有元素
            const matchingIds = [];

            for (let i = 0; i < allElements.length; i++) {
                const element = allElements[i];
                if (element.id && element.id.startsWith("courseware-kcjs_")) {
                    matchingIds.push(element.id.replace("courseware-", ""));
                }
            }

            return matchingIds;
        }
        // 当前学习类型,如果不是video,自动跳到video
        let nodeInfo = document.querySelector("body").innerHTML.match(/var nodeInfo = ({.*?})/)
        // 不是相关网页搜不到
        if (!nodeInfo)
            return
        let nodeType = JSON.parse(nodeInfo[1]).type
        if (nodeType != "video" && confirm("当前不是视频学习,是否跳转到视频第一课?")) {
            CoursewareNodesManager.onMenuClick(kcjsIds[0])
        }
        if (nodeType == "video") {
            const observer = new MutationObserver(async (mutationsList, observer) => {
                for (const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        const videoElement = document.querySelector('#vjs_video_3_html5_api');
                        if (videoElement) {
                            observer.disconnect();
                            // 开始播放
                            videoElement.autoplay = true;
                            // 慢倍速播放凑时长
                            videoElement.playbackRate = 0.5;
                            // 静音
                            videoElement.muted = "muted";

                            // 等待视频播放完毕自动下一个视频
                            videoElement.onended = () => {
                                // 解析当前的课程ID
                                const nodeId = (new URL(document.URL)).searchParams.get("nodeId")
                                // 下一节课的ID
                                const nextNodeId = kcjsIds[kcjsIds.indexOf(nodeId) + 1]

                                // 如果还有下一节课,继续看
                                if (nextNodeId) {
                                    // 下一节课
                                    CoursewareNodesManager.onMenuClick(nextNodeId)
                                } else {
                                    // 没有就是看完了,不再继续
                                    console.log('看完啦!');
                                }
                            }
                            ;

                            // 确保视频加载后播放(某些情况下可能需要)
                            if (videoElement.readyState >= 2) {
                                // HAVE_CURRENT_DATA
                                videoElement.play().catch(error => {
                                    console.error("播放失败:", error);
                                }
                                );
                            } else {
                                videoElement.addEventListener('loadeddata', () => {
                                    videoElement.play().catch(error => {
                                        console.error("播放失败:", error);
                                    }
                                    );
                                }
                                );
                            }
                            return;
                            // 找到元素并处理后,退出观察器回调
                        }
                    }
                }
            }
            );
        }

        // 开始观察 document.body 或更具体的父元素
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    window.onload = main;
}
)();