// ==UserScript== // @name 超星学习通(个人版)助手(支持配课程) // @version 3.2 // @authon grb // @description 超星学习通个人版助手(本工具全面支持章节测试、文档学习、直播课程、作业及考试等多种学习场景。采用一键启动脚本,单页面全自动运行,支持最小化后台运行且任务不中断。其运行过程不占用网速与流量,开热点亦可流畅使用。内置题库,题目覆盖率高达9.999%,涵盖单选、多选、填空、判断及图片题、编程题、听力题等多种题型。题目答案实时更新收录,助您轻松掌握知识点,高效拿高分。)其它课程联系站长群:967409707 // @author You // @match https://mooc1.chaoxing.com/mooc-ans/knowledge/cards* // @match https://mooc1.chaoxing.com/mycourse/studentstudy* // @match https://*.chaoxing.com/* // @match *://*.chaoxing.com/* // @match *://*.edu.cn/* // @match *://*.nbdlib.cn/* // @match *://*.hnsyu.net/* // @match *://*.gdhkmooc.com/* // @match *://*.zhihuishu.com/* // @match *://*.tmall.com/* // @match *://chaoshi.detail.tmall.com/* // @match *://*.tmall.hk/* // @match *://*.liangxinyao.com/* // @match *://*.jd.com/* // @match *://*.jd.hk/* // @match *://*.jkcsjd.com/* // @match *://*.yiyaojd.com/* // @match *://*.vip.com/* // @match *://*.uai.unipus.cn/* // @match *://*.u.unipus.cn/* // @match *://*.mooc.yinghuaonline.com/user/login/* // @match *://*.mooc.yinghuaonline.com/* // @match *://*.www.qingshuxuetang.com/* // @match *://*.www.buu.edu.cn/* // @match *://*.www.pmphmooc.com/* // @match *://*.vipglobal.hk/* // @match *://*.welearn.sflep.com/* // @match *://*.www.ouchn.edu.cn/* // @exclude *://login.tmall.com/* // @exclude *://pages.tmall.com/* // @exclude *://wq.jd.com/* // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_info // @grant GM_openInTab // @connect chaoxing.com // @connect p1.learn.tsinghua.edu.cn // @connect p2.learn.tsinghua.edu.cn // @connect p3.learn.tsinghua.edu.cn // @connect p4.edu.cn // @connect p5.edu.cn // @connect p6.edu.cn // @antifeature ads // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js // @source https://qinghy.top // @antifeature payment 答疑收费 // ==/UserScript== (function() { 'use strict'; class ChaoxingVideoAnalyzer { constructor() { this.pageParams = this.extractPageParams(); this.videoSources = []; this.currentPlayingVideo = null; this.videoPlayer = null; this.settings = { showBox: 1, video: 1, rate: 1, reportInterval: 60, showProgressBar: 1, videoMode: 'simulate' }; this.knowledgeData = null; this.courseProgress = null; this.isAutoPlayActive = false; this.init(); } extractPageParams() { const url = new URL(window.location.href); return { clazzid: url.searchParams.get('clazzid'), courseid: url.searchParams.get('courseid'), knowledgeid: url.searchParams.get('knowledgeid'), num: url.searchParams.get('num'), ut: url.searchParams.get('ut'), cpi: url.searchParams.get('cpi'), v: url.searchParams.get('v'), mooc2: url.searchParams.get('mooc2'), isMicroCourse: url.searchParams.get('isMicroCourse'), editorPreview: url.searchParams.get('editorPreview') }; } init() { this.loadSettings(); this.createUI(); this.setupEventListeners(); this.initPageDetection(); this.analyzePageContent(); console.log('超星学习通视频分析播放器已启动', this.pageParams); } loadSettings() { const savedVideoMode = GM_getValue('videoMode', 'simulate'); const savedRate = GM_getValue('videoRate', 1); const savedShowProgressBar = GM_getValue('showProgressBar', 1); this.settings.videoMode = savedVideoMode; this.settings.rate = savedRate; this.settings.showProgressBar = savedShowProgressBar; } createUI() { // 创建浮动按钮 const floatBtn = document.createElement('div'); floatBtn.id = 'chaoxing-video-analyzer-btn'; floatBtn.innerHTML = '🎥 视频分析器'; floatBtn.style.cssText = ` position: fixed; bottom: 100px; right: 20px; z-index: 999999; width: 80px; height: 80px; background: linear-gradient(135deg, #3498db, #2980b9); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 15px rgba(0,0,0,0.3); transition: all 0.3s ease; user-select: none; `; floatBtn.addEventListener('mouseenter', () => { floatBtn.style.transform = 'scale(1.1)'; }); floatBtn.addEventListener('mouseleave', () => { floatBtn.style.transform = 'scale(1)'; }); document.body.appendChild(floatBtn); // 创建主界面 const mainUI = document.createElement('div'); mainUI.id = 'chaoxing-video-analyzer-main-ui'; mainUI.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); z-index: 999998; display: none; justify-content: center; align-items: center; font-family: 'Microsoft YaHei', Arial, sans-serif; color: white; `; mainUI.innerHTML = `

百家网课助手

视频与播放|在线客服群:967409707

支持免费视频刷 、超星学习通 、智慧树、 U校园/AI 、 MOOC 、继续教育类 、优课学堂 、考试 、 青书学堂 、 优学院 、 AI解答

学习强国、中国大学mooc 、 智慧职教 、 WeLearn、 知到 、 乐跑、世界运动、阳光跑 、自动刷课、大学生课程、毕业论文降重、教师等等课程提供学习

页面参数: 等待加载...
后台播放 添加课程 注册

页面分析结果:红帽子:站长QQ:417545796

🔍
正在分析页面内容...

检测到的视频资源

🎬
正在扫描页面视频资源...

视频分析详情

正在分析视频格式和可用性...

视频播放控制

请选择要播放的视频

操作说明

  • 页面参数已自动提取: clazzid, courseid, knowledgeid等
  • 点击"重新分析"刷新页面内容扫描
  • "仅显示MP4"过滤非MP4格式视频
  • 支持批量下载和自动播放功能
就绪 - 等待分析页面内容
`; document.body.appendChild(mainUI); // 更新页面参数显示 this.updatePageParamsDisplay(); } updatePageParamsDisplay() { const paramsDiv = document.getElementById('page-params-display'); paramsDiv.innerHTML = ` 获取课程ID: class=${this.pageParams.clazzid}, course=${this.pageParams.courseid}, knowledge=${this.pageParams.knowledgeid}, num=${this.pageParams.num} `; } setupEventListeners() { // 按钮事件 document.getElementById('chaoxing-video-analyzer-btn').addEventListener('click', () => { document.getElementById('chaoxing-video-analyzer-main-ui').style.display = 'flex'; setTimeout(() => { this.analyzePageContent(); }, 100); }); document.getElementById('close-ui-btn').addEventListener('click', () => { document.getElementById('chaoxing-video-analyzer-main-ui').style.display = 'none'; }); document.getElementById('analyze-page-btn').addEventListener('click', () => { this.analyzePageContent(); }); document.getElementById('fetch-knowledge-btn').addEventListener('click', () => { this.fetchKnowledgeData(); }); document.getElementById('play-selected-btn').addEventListener('click', () => { this.playSelectedVideo(); }); document.getElementById('auto-play-btn').addEventListener('click', () => { this.startAutoPlay(); }); document.getElementById('extract-mp4-btn').addEventListener('click', () => { this.extractMp4Links(); }); document.getElementById('download-btn').addEventListener('click', () => { this.downloadSelectedVideo(); }); document.getElementById('batch-extract-btn').addEventListener('click', () => { this.batchExtractVideos(); }); document.getElementById('test-links-btn').addEventListener('click', () => { this.testAllLinks(); }); document.getElementById('filter-mp4-btn').addEventListener('click', () => { this.filterMp4Videos(); }); document.getElementById('export-data-btn').addEventListener('click', () => { this.exportVideoData(); }); // 播放控制事件 document.getElementById('play-btn').addEventListener('click', () => { this.controlVideo('play'); }); document.getElementById('pause-btn').addEventListener('click', () => { this.controlVideo('pause'); }); document.getElementById('stop-btn').addEventListener('click', () => { this.controlVideo('stop'); }); document.getElementById('speed-select').addEventListener('change', (e) => { this.setPlaybackSpeed(parseFloat(e.target.value)); }); } initPageDetection() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { this.analyzePageContent(); }, 2000); }); } else { setTimeout(() => { this.analyzePageContent(); }, 2000); } const observer = new MutationObserver(() => { if (!this.lastAnalysisTime || Date.now() - this.lastAnalysisTime > 5000) { setTimeout(() => { if (document.getElementById('chaoxing-video-analyzer-main-ui').style.display === 'flex') { this.analyzePageContent(); } }, 3000); } }); observer.observe(document.body, { childList: true, subtree: true }); } async analyzePageContent() { this.updateStatus('正在分析页面内容...'); try { // 分析页面结构 const analysisResult = await this.analyzePageStructure(); this.updatePageAnalysis(analysisResult); // 获取视频资源 const videos = await this.extractVideoResources(); this.videoSources = [...new Set([...this.videoSources, ...videos])]; this.videoSources = this.deduplicateVideos(this.videoSources); this.updateVideoList(); this.updateVideoAnalysisDetails(); this.updateStatus(`分析完成,共找到 ${this.videoSources.length} 个视频资源`); this.lastAnalysisTime = Date.now(); } catch (error) { console.error('分析页面内容时出错:', error); this.updateStatus(`分析失败: ${error.message}`); } } async analyzePageStructure() { const analysis = { title: document.title, url: window.location.href, timestamp: new Date().toISOString(), iframeCount: document.querySelectorAll('iframe').length, videoElementCount: document.querySelectorAll('video').length, scriptCount: document.querySelectorAll('script').length, linkCount: document.querySelectorAll('link').length, metaTags: Array.from(document.querySelectorAll('meta')).map(meta => ({ name: meta.name, content: meta.content })), jsVariables: this.extractJsVariables(), embeddedContent: this.extractEmbeddedContent() }; return analysis; } extractJsVariables() { const variables = []; // 常见的视频相关变量名 const commonNames = [ 'videoinfo', 'mediaInfo', 'courseVideo', 'video_config', 'enc', 'd', 'objectId', 'otherInfo', 'defaults', 'apiurl', 'vid', 'videoId', 'resource', 'content', 'courseware', 'chapter', 'lesson', 'task', 'workid', 'jobid', 'property', '_jEncrypted', 'jEncrypted', 'defaults', 'def', 'api', 'video', 'player', 'currentVideo', 'videoObject', 'videoResource', 'courseData', 'knowledge', 'card', 'pageData', 'module', 'contentData' ]; for (const name of commonNames) { try { if (unsafeWindow[name]) { variables.push({ name: name, value: typeof unsafeWindow[name] === 'object' ? JSON.stringify(unsafeWindow[name], null, 2) : String(unsafeWindow[name]), type: typeof unsafeWindow[name] }); } } catch (e) { // 静默处理错误 } } return variables; } extractEmbeddedContent() { const content = []; // iframe 内容 const iframes = document.querySelectorAll('iframe[src*="chaoxing"], iframe[src*="edu"]'); iframes.forEach((iframe, index) => { content.push({ type: 'iframe', src: iframe.src, id: iframe.id, className: iframe.className }); }); // script 标签内容 const scripts = document.querySelectorAll('script'); scripts.forEach((script, index) => { if (script.textContent && script.textContent.includes('video')) { content.push({ type: 'script', content: script.textContent.substring(0, 200) + '...', id: script.id }); } }); return content; } async extractVideoResources() { const videos = []; try { // 1. 直接的video元素 const directVideos = await this.extractDirectVideoElements(); videos.push(...directVideos); // 2. iframe中的视频 const iframeVideos = await this.extractIframeVideos(); videos.push(...iframeVideos); // 3. JavaScript变量中的视频URL const jsVideos = await this.extractJsVideoUrls(); videos.push(...jsVideos); // 4. Ananas状态API的视频 const ananasVideos = await this.extractAnanasVideos(); videos.push(...ananasVideos); // 5. 页面脚本中的视频链接 const scriptVideos = await this.extractScriptVideos(); videos.push(...scriptVideos); // 6. 知识点相关的视频 const knowledgeVideos = await this.extractKnowledgeVideos(); videos.push(...knowledgeVideos); } catch (error) { console.error('提取视频资源时出错:', error); } return videos; } async extractDirectVideoElements() { const videos = []; const videoElements = document.querySelectorAll('video'); for (const [index, video] of videoElements.entries()) { if (video.src) { videos.push({ id: `direct-video-${index}`, url: video.src, name: `直接视频 ${index + 1}`, type: 'direct-video', duration: video.duration ? this.formatDuration(video.duration) : '未知', size: '未知', source: 'video-element', quality: 'high', timestamp: Date.now() }); } const sources = video.querySelectorAll('source'); for (const [sourceIndex, source] of sources.entries()) { if (source.src) { videos.push({ id: `source-video-${index}-${sourceIndex}`, url: source.src, name: `视频源 ${index + 1}-${sourceIndex + 1}`, type: 'source-video', duration: video.duration ? this.formatDuration(video.duration) : '未知', size: '未知', source: 'source-element', quality: 'high', timestamp: Date.now() }); } } } return videos; } async extractIframeVideos() { const videos = []; const iframes = document.querySelectorAll('iframe[src*="chaoxing"], iframe[src*="mooc"], iframe[src*="ananas"]'); for (const [index, iframe] of iframes.entries()) { if (iframe.src && this.isValidVideoUrl(iframe.src)) { videos.push({ id: `iframe-video-${index}`, url: iframe.src, name: `iframe视频 ${index + 1}`, type: 'iframe-video', duration: '未知', size: '未知', source: 'iframe-src', quality: 'medium', timestamp: Date.now() }); } } return videos; } async extractJsVideoUrls() { const videos = []; const jsVars = this.extractJsVariables(); for (const jsVar of jsVars) { if (typeof jsVar.value === 'string') { // 提取URL const urlMatches = jsVar.value.match(/https?:\/\/[^\s"'<>]*\.(mp4|m3u8|flv|avi|mov|wmv|webm)[^"'\s<>]*/gi) || []; for (const urlMatch of urlMatches) { videos.push({ id: `js-video-${Date.now()}-${Math.random()}`, url: urlMatch, name: `JS变量: ${jsVar.name}`, type: 'js-url', duration: '未知', size: '未知', source: 'js-variable', quality: 'medium', timestamp: Date.now() }); } // 提取ObjectId const objectIdMatches = jsVar.value.match(/[0-9a-fA-F]{24}/g) || []; for (const objectId of objectIdMatches) { const videoUrl = `https://mooc1.chaoxing.com/ananas/status/${objectId}?flag=normal`; videos.push({ id: `js-objectid-${objectId}`, url: videoUrl, name: `JS ObjectId: ${objectId.substring(0, 8)}...`, type: 'js-objectid', duration: '未知', size: '未知', source: 'js-objectid', quality: 'high', timestamp: Date.now() }); } } } return videos; } async extractAnanasVideos() { const videos = []; // 从页面文本中提取ObjectId const pageText = document.documentElement.outerHTML; const objectIdPattern = /[0-9a-fA-F]{24}/g; let match; while ((match = objectIdPattern.exec(pageText)) !== null) { const objectId = match[0]; try { const response = await this.fetchVideoStatus(objectId); if (response && response.downloadUrl) { videos.push({ id: `ananas-${objectId}`, url: response.downloadUrl, name: `Ananas视频: ${response.filename || objectId.substring(0, 8) + '...'}`, type: 'ananas-video', duration: response.duration || '未知', size: response.size || '未知', source: 'ananas-api', quality: 'high', timestamp: Date.now() }); } else { videos.push({ id: `ananas-basic-${objectId}`, url: `https://mooc1.chaoxing.com/ananas/status/${objectId}?flag=normal`, name: `Ananas基础: ${objectId.substring(0, 8)}...`, type: 'ananas-basic', duration: '未知', size: '未知', source: 'ananas-basic', quality: 'medium', timestamp: Date.now() }); } } catch (e) { videos.push({ id: `ananas-fallback-${objectId}`, url: `https://mooc1.chaoxing.com/ananas/status/${objectId}?flag=normal`, name: `Ananas回退: ${objectId.substring(0, 8)}...`, type: 'ananas-fallback', duration: '未知', size: '未知', source: 'ananas-fallback', quality: 'low', timestamp: Date.now() }); } } return videos; } async extractScriptVideos() { const videos = []; const scripts = document.querySelectorAll('script'); for (const script of scripts) { if (script.textContent) { // 查找视频URL const urlRegex = /https?:\/\/[^\s"'<>]*\.(mp4|m3u8|flv|avi|mov|wmv|webm)[^"'\s<>]*/gi; let urlMatch; while ((urlMatch = urlRegex.exec(script.textContent)) !== null) { videos.push({ id: `script-url-${Date.now()}-${Math.random()}`, url: urlMatch[0], name: '脚本发现URL', type: 'script-url', duration: '未知', size: '未知', source: 'script-content', quality: 'medium', timestamp: Date.now() }); } // 查找ObjectId const objectIdRegex = /[0-9a-fA-F]{24}/g; let objectIdMatch; while ((objectIdMatch = objectIdRegex.exec(script.textContent)) !== null) { const objectId = objectIdMatch[0]; const videoUrl = `https://mooc1.chaoxing.com/ananas/status/${objectId}?flag=normal`; videos.push({ id: `script-objectid-${objectId}`, url: videoUrl, name: `脚本ObjectId: ${objectId.substring(0, 8)}...`, type: 'script-objectid', duration: '未知', size: '未知', source: 'script-content', quality: 'high', timestamp: Date.now() }); } } } return videos; } async extractKnowledgeVideos() { const videos = []; // 使用页面参数构建API请求 try { // 从页面DOM中查找知识点相关的视频 const knowledgeCards = document.querySelectorAll('[data-knowledgeid], [data-cardid], [data-module]'); for (const card of knowledgeCards) { // 查找卡片内的视频元素 const cardVideos = card.querySelectorAll('video, iframe[src*="video"], iframe[src*="chaoxing"]'); for (const video of cardVideos) { if (video.src && this.isValidVideoUrl(video.src)) { videos.push({ id: `knowledge-video-${Date.now()}-${Math.random()}`, url: video.src, name: `知识点视频: ${card.dataset.knowledgeid || 'unknown'}`, type: 'knowledge-video', duration: '未知', size: '未知', source: 'knowledge-card', quality: 'high', timestamp: Date.now() }); } } } } catch (error) { console.error('提取知识点视频时出错:', error); } return videos; } async fetchVideoStatus(objectId) { return new Promise((resolve) => { GM_xmlhttpRequest({ method: 'GET', url: `https://mooc1.chaoxing.com/ananas/status/${objectId}?flag=normal`, onload: function(response) { try { const data = JSON.parse(response.responseText); resolve(data); } catch (e) { resolve(null); } }, onerror: function(error) { resolve(null); } }); }); } async fetchKnowledgeData() { this.updateStatus('正在获取知识点数据...'); try { // 使用页面参数构建知识点API请求 const apiUrl = `https://mooc1.chaoxing.com/mooc-ans/knowledge/cards?clazzid=${this.pageParams.clazzid}&courseid=${this.pageParams.courseid}&knowledgeid=${this.pageParams.knowledgeid}&num=${this.pageParams.num}&ut=${this.pageParams.ut}&cpi=${this.pageParams.cpi}&v=${this.pageParams.v}`; // 由于跨域限制,我们主要分析页面内容 const knowledgeData = { clazzid: this.pageParams.clazzid, courseid: this.pageParams.courseid, knowledgeid: this.pageParams.knowledgeid, num: this.pageParams.num, ut: this.pageParams.ut, cpi: this.pageParams.cpi, v: this.pageParams.v, timestamp: new Date().toISOString(), pageContentLength: document.documentElement.outerHTML.length, videoElements: document.querySelectorAll('video').length, iframeElements: document.querySelectorAll('iframe').length }; this.knowledgeData = knowledgeData; this.updateStatus('知识点数据获取完成'); } catch (error) { console.error('获取知识点数据失败:', error); this.updateStatus(`获取知识点数据失败: ${error.message}`); } } // 视频播放相关方法 playSelectedVideo() { const selectedVideo = this.getSelectedVideo(); if (selectedVideo) { this.playVideo(selectedVideo.url); this.updateVideoInfo(selectedVideo); } else { this.updateStatus('请先选择一个视频'); } } async playVideo(videoUrl) { const video = document.getElementById('preview-video'); if (!video) return; try { // 设置视频源 video.src = videoUrl; video.load(); // 显示控制面板 document.getElementById('video-controls').style.display = 'block'; // 等待元数据加载 await new Promise((resolve, reject) => { video.onloadedmetadata = () => resolve(); video.onerror = (e) => reject(e); setTimeout(() => reject(new Error('视频加载超时')), 10000); }); // 开始播放 await video.play(); this.currentPlayingVideo = videoUrl; this.updateStatus('视频开始播放'); } catch (error) { this.updateStatus(`播放失败: ${error.message}`); console.error('视频播放错误:', error); } } controlVideo(action) { const video = document.getElementById('preview-video'); if (video) { switch (action) { case 'play': video.play(); this.updateStatus('视频播放'); break; case 'pause': video.pause(); this.updateStatus('视频暂停'); break; case 'stop': video.pause(); video.currentTime = 0; this.updateStatus('视频停止'); break; } } } setPlaybackSpeed(speed) { const video = document.getElementById('preview-video'); if (video) { video.playbackRate = speed; this.updateStatus(`播放速度设置为 ${speed}x`); } } startAutoPlay() { if (this.videoSources.length === 0) { this.updateStatus('没有可播放的视频'); return; } this.isAutoPlayActive = true; this.updateStatus('开始自动播放模式'); this.autoPlayNextVideo(0); } async autoPlayNextVideo(index) { if (!this.isAutoPlayActive || index >= this.videoSources.length) { this.updateStatus('自动播放完成'); this.isAutoPlayActive = false; return; } const video = this.videoSources[index]; this.updateStatus(`播放第 ${index + 1}/${this.videoSources.length} 个视频: ${video.name}`); try { await this.playVideo(video.url); this.updateVideoInfo(video); // 等待视频播放完成或用户中断 const videoElement = document.getElementById('preview-video'); await new Promise((resolve) => { const checkComplete = () => { if (videoElement.ended || !this.isAutoPlayActive) { resolve(); } else { setTimeout(checkComplete, 1000); } }; checkComplete(); }); // 继续播放下一个 if (this.isAutoPlayActive) { setTimeout(() => this.autoPlayNextVideo(index + 1), 1000); } } catch (error) { console.error('自动播放错误:', error); if (this.isAutoPlayActive) { // 继续播放下一个 setTimeout(() => this.autoPlayNextVideo(index + 1), 1000); } } } // UI更新方法 updatePageAnalysis(analysis) { const container = document.getElementById('page-analysis'); if (!analysis) { container.innerHTML = `
🔍
正在分析页面内容...
`; return; } let html = `
页面标题: ${analysis.title}
页面URL: ${analysis.url.substring(0, 80)}${analysis.url.length > 80 ? '...' : ''}
时间戳: ${analysis.timestamp}
统计信息:
iframe数量: ${analysis.iframeCount}
video元素: ${analysis.videoElementCount}
script元素: ${analysis.scriptCount}
link元素: ${analysis.linkCount}
JavaScript变量: ${analysis.jsVariables.length} 个
${analysis.jsVariables.slice(0, 5).map(v => `${v.name}`).join(', ')} ${analysis.jsVariables.length > 5 ? `... 及 ${analysis.jsVariables.length - 5} 个更多` : ''}
嵌入内容: ${analysis.embeddedContent.length} 项
`; container.innerHTML = html; } updateVideoInfo(video) { const infoContainer = document.getElementById('video-info'); infoContainer.innerHTML = `
名称: ${video.name}
类型: ${video.type}
来源: ${video.source}
质量: ${video.quality}
时长: ${video.duration}
${video.url}
`; } updateVideoList(filter = null) { const container = document.getElementById('video-list-container'); if (this.videoSources.length === 0) { container.innerHTML = `
🎬
未找到视频资源
请尝试重新分析或检查页面是否已加载视频内容
`; return; } let filteredVideos = this.videoSources; if (filter) { filteredVideos = this.videoSources.filter(video => filter(video)); } let html = '
'; filteredVideos.forEach((video, index) => { html += `
${video.name}
来源: ${video.source} | 类型: ${video.type} | 质量: ${video.quality}
时长: ${video.duration} | 时间: ${new Date(video.timestamp).toLocaleString()}
${video.url.substring(0, 100)}${video.url.length > 100 ? '...' : ''}
`; }); html += '
'; container.innerHTML = html; } updateVideoAnalysisDetails() { const container = document.getElementById('video-analysis-details'); if (this.videoSources.length === 0) { container.innerHTML = `
未找到视频资源
尝试重新分析或确保页面已完全加载
`; return; } const stats = { total: this.videoSources.length, bySource: {}, byType: {}, byQuality: {}, mp4Count: 0, m3u8Count: 0, others: 0 }; this.videoSources.forEach(video => { stats.bySource[video.source] = (stats.bySource[video.source] || 0) + 1; stats.byType[video.type] = (stats.byType[video.type] || 0) + 1; stats.byQuality[video.quality] = (stats.byQuality[video.quality] || 0) + 1; if (video.url.includes('.mp4')) { stats.mp4Count++; } else if (video.url.includes('.m3u8')) { stats.m3u8Count++; } else { stats.others++; } }); container.innerHTML = `
统计信息:
总数: ${stats.total} | MP4: ${stats.mp4Count} | M3U8: ${stats.m3u8Count} | 其他: ${stats.others}
按来源分布:
按类型分布:
按质量分布:
课程id获取: clazzid=${this.pageParams.clazzid}, courseid=${this.pageParams.courseid}, knowledgeid=${this.pageParams.knowledgeid}
`; } // 辅助方法 isValidVideoUrl(url) { if (typeof url !== 'string') return false; return url.includes('.mp4') || url.includes('.m3u8') || url.includes('.flv') || url.includes('.avi') || url.includes('.mov') || url.includes('.wmv') || url.includes('.webm') || url.includes('chaoxing') || url.includes('ananas') || url.includes('mooc') || url.includes('video'); } formatDuration(seconds) { if (!seconds || isNaN(seconds)) return '未知'; const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); const s = Math.floor(seconds % 60); return h > 0 ? `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}` : `${m}:${s.toString().padStart(2, '0')}`; } deduplicateVideos(videos) { const seen = new Map(); return videos.filter(video => { const key = video.url; if (seen.has(key)) { return false; } seen.set(key, true); return true; }); } updateStatus(message) { document.getElementById('status-bar').textContent = message; } getSelectedVideo() { const selectedElement = document.querySelector('.video-item[style*="border-color: rgb(52, 152, 219)"]') || document.querySelector('.video-item[style*="#3498db"]'); if (selectedElement) { const url = selectedElement.getAttribute('data-url'); return this.videoSources.find(v => v.url === url); } return null; } // 特殊功能方法 extractMp4Links() { const mp4Videos = this.videoSources.filter(video => video.url.includes('.mp4')); if (mp4Videos.length === 0) { this.updateStatus('未找到MP4格式的视频'); return; } const mp4Urls = mp4Videos.map(video => video.url).join('\n'); navigator.clipboard.writeText(mp4Urls) .then(() => { this.updateStatus(`已复制 ${mp4Videos.length} 个MP4链接到剪贴板`); }) .catch(err => { this.updateStatus('复制失败: ' + err.message); }); } downloadSelectedVideo() { const selectedVideo = this.getSelectedVideo(); if (selectedVideo) { try { const a = document.createElement('a'); a.href = selectedVideo.url; a.download = `knowledge-video-${this.pageParams.knowledgeid}-${Date.now()}.mp4`; a.target = '_blank'; document.body.appendChild(a); a.click(); document.body.removeChild(a); this.updateStatus('下载已启动'); } catch (error) { this.updateStatus('下载失败: ' + error.message); } } else { this.updateStatus('请先选择一个视频'); } } batchExtractVideos() { if (this.videoSources.length === 0) { this.updateStatus('没有可提取的视频'); return; } const allUrls = this.videoSources.map(video => video.url).join('\n'); navigator.clipboard.writeText(allUrls) .then(() => { this.updateStatus(`已复制 ${this.videoSources.length} 个视频链接到剪贴板`); }) .catch(err => { this.updateStatus('复制失败: ' + err.message); }); } async testLinkBatch(index, successCount, failedCount) { if (index >= this.videoSources.length) { this.updateStatus(`测试完成: 成功 ${successCount}, 失败 ${failedCount}`); return; } const video = this.videoSources[index]; this.updateStatus(`测试第 ${index + 1}/${this.videoSources.length} 个链接: ${video.name}`); try { const response = await this.testUrl(video.url); if (response.success) { successCount++; // 更新列表项状态 const listItem = document.querySelector(`[data-url="${video.url}"]`); if (listItem) { listItem.style.backgroundColor = '#27ae60'; } } else { failedCount++; // 更新列表项状态 const listItem = document.querySelector(`[data-url="${video.url}"]`); if (listItem) { listItem.style.backgroundColor = '#c0392b'; } } } catch (error) { failedCount++; // 更新列表项状态 const listItem = document.querySelector(`[data-url="${video.url}"]`); if (listItem) { listItem.style.backgroundColor = '#c0392b'; } } setTimeout(() => { this.testLinkBatch(index + 1, successCount, failedCount); }, 100); } async testUrl(url) { return new Promise((resolve) => { GM_xmlhttpRequest({ method: 'HEAD', url: url, timeout: 5000, onload: function(response) { resolve({ success: response.status === 200, status: response.status, headers: response.responseHeaders }); }, onerror: function() { resolve({ success: false, status: 0 }); }, ontimeout: function() { resolve({ success: false, status: 0 }); } }); }); } filterMp4Videos() { this.updateVideoList(video => video.url.includes('.mp4')); this.updateStatus('已过滤,仅显示MP4格式视频'); } exportVideoData() { if (this.videoSources.length === 0) { this.updateStatus('没有可导出的数据'); return; } const data = { pageParams: this.pageParams, analysisTimestamp: new Date().toISOString(), videoCount: this.videoSources.length, videos: this.videoSources, knowledgeData: this.knowledgeData }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `chaoxing-video-data-${this.pageParams.knowledgeid}-${Date.now()}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); this.updateStatus('数据已导出'); } } // 启动视频分析器 const analyzer = new ChaoxingVideoAnalyzer(); window.chaoxingVideoAnalyzer = analyzer; // 暴露到全局作用域以便在内联脚本中使用 })();