// ==UserScript== // @name CKPlayer 强制全自动播放 (防检测增强版) // @namespace https://example.com // @version 9.0 // @description 绕过浏览器拦截并修复播放器状态,防止被检测 // @author You // @match *://*/* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; console.log('🛡️ 防检测版强制全自动播放脚本已加载...'); // --- 配置区域 --- const PLAY_BUTTON_SELECTORS = [ '.ckplayer-play', '.ck-control-bar .play', 'div[title="点击播放"]', '.ck-status', '.ckplayer > .play' ]; let monitorTimer = null; // --- 防检测核心:重写播放器状态 --- // 1. 重写 play() 和 pause() 方法,防止播放器报错 const safePlay = (video) => { // 检查原生方法是否存在 if (video.play) { // 尝试调用原生 play,并捕获错误 const playPromise = video.play(); if (playPromise !== undefined) { playPromise.catch(error => { console.warn('原生 play() 失败,尝试强制设置状态:', error); // 如果原生方法被拦截,强制设置 paused 状态为 false // (注:这通常需要配合 Object.defineProperty 来劫持属性,但受限于沙箱,这里主要做 UI 层欺骗) forceUIState('playing'); }); } } else { // 极端情况:如果 play 方法被删除,尝试触发点击 forceUIState('playing'); } }; // 2. 强制修复 UI 和状态 (欺骗播放器) // 这是防检测的关键:让播放器以为用户真的点击了按钮 const forceUIState = (state) => { const video = document.querySelector('video'); const btn = getPlayBtn(); if (state === 'playing') { if (video) { // 尝试移除暂停属性(虽然不能直接修改 paused,但可以移除 paused 类) video.classList.remove('paused'); video.classList.add('playing'); // 如果播放器通过 dataset 控制,修改它 video.dataset.state = 'playing'; } if (btn) { // 修改按钮样式:例如移除 "播放图标",添加 "暂停图标" // 这里根据 CKPlayer 的常见逻辑进行模拟 btn.classList.remove('play'); // 假设 play 类是播放图标 btn.classList.add('pause'); // 假设 pause 类是暂停图标 btn.setAttribute('title', '点击暂停'); // 如果按钮内有文本,修改文本 if (btn.innerText.includes('播放')) { btn.innerText = btn.innerText.replace('播放', '暂停'); } } } else if (state === 'paused') { if (video) { video.classList.remove('playing'); video.classList.add('paused'); video.dataset.state = 'paused'; } if (btn) { btn.classList.remove('pause'); btn.classList.add('play'); btn.setAttribute('title', '点击播放'); if (btn.innerText.includes('暂停')) { btn.innerText = btn.innerText.replace('暂停', '播放'); } } } }; // 获取播放按钮元素 const getPlayBtn = () => { for (let selector of PLAY_BUTTON_SELECTORS) { const btn = document.querySelector(selector); if (btn) return btn; } return null; }; // 模拟点击函数 (保持原样,但增加了防屏蔽的事件参数) const simulateClick = (element) => { if (!element) return; const event = new MouseEvent('click', { view: window, bubbles: true, cancelable: true, // 增加一些模拟用户行为的参数,减少被识别为机器的概率 button: 0, // 左键 buttons: 1 // 按下的按钮 }); element.dispatchEvent(event); }; // --- 核心动作:强制播放 --- const forcePlay = () => { const video = document.querySelector('video'); if (video) { if (video.paused || video.ended) { console.log('>>> 检测到视频未播放,尝试安全播放模式'); if (video.ended) video.currentTime = 0; // 使用安全播放包装器 safePlay(video); // 双重保险:如果 video.play() 没有效果,强制修改 UI 状态 // (有些播放器只看 UI 状态,不看 video 标签状态) setTimeout(() => { if (video.paused) { console.log('>>> 视频依然暂停,强制同步 UI 状态'); forceUIState('playing'); } }, 500); } } else { // 针对 Flash 或 纯 DOM 模拟 const btn = getPlayBtn(); if (btn) { const style = window.getComputedStyle(btn); if (style.display !== 'none' && style.visibility !== 'hidden') { console.log('>>> 尝试点击播放按钮 (DOM模式)'); simulateClick(btn); // 点击后立即修正状态 forceUIState('playing'); } } } }; // --- 启动流程 --- // 1. 立即执行一次 setTimeout(() => { console.log('🔍 启动时立即检测...'); forcePlay(); }, 800); // 2. 心跳循环检测 if (monitorTimer) clearInterval(monitorTimer); monitorTimer = setInterval(() => { const video = document.querySelector('video'); if (video) { // 智能检测:如果视频处于暂停状态,但播放器 UI 显示正在播放,说明状态不同步 // 或者 视频真的暂停了 if (video.paused) { console.log('⚠️ 检测到视频暂停,强制唤醒并同步状态'); forcePlay(); } // 如果视频在播放,但 UI 显示暂停,修复 UI else if (!video.paused) { forceUIState('playing'); } } else { // 兜底逻辑 forceUIState('playing'); // 强制 UI 显示播放,防止播放器卡死 } }, 2000); })();