让没有小窗播放的视频网站的视频小窗播放

让没有小窗播放的视频网站的视频小窗播放

javascript 复制代码
// 视频小窗播放控制台脚本
// 将此代码复制到浏览器控制台运行
// 运行后,页面中的视频将添加小窗播放功能

(function() {
    // 获取页面中的所有video元素
    const videos = document.querySelectorAll('video');
    
    if (videos.length === 0) {
        console.log('页面中没有找到video元素');
        return;
    }
    
    // 创建小窗容器
    const pipContainer = document.createElement('div');
    pipContainer.id = 'pip-container';
    pipContainer.style.cssText = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        width: 300px;
        height: 200px;
        border-radius: 10px;
        overflow: hidden;
        box-shadow: 0 10px 30px rgba(0,0,0,0.5);
        z-index: 10000;
        border: 2px solid #ff6b6b;
        background: black;
        display: none;
        cursor: move;
    `;
    
    // 创建小窗标题栏
    const pipHeader = document.createElement('div');
    pipHeader.style.cssText = `
        background: rgba(0,0,0,0.7);
        padding: 8px 12px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-family: Arial, sans-serif;
        color: white;
        font-size: 14px;
    `;
    pipHeader.textContent = '小窗播放 (可拖拽)';
    
    // 创建关闭按钮
    const closeBtn = document.createElement('button');
    closeBtn.textContent = '×';
    closeBtn.style.cssText = `
        background: none;
        border: none;
        color: white;
        cursor: pointer;
        font-size: 20px;
        line-height: 1;
        padding: 0;
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
    `;
    
    pipHeader.appendChild(closeBtn);
    pipContainer.appendChild(pipHeader);
    
    // 创建小窗中的video元素
    const pipVideo = document.createElement('video');
    pipVideo.id = 'pip-video';
    pipVideo.style.cssText = `
        width: 100%;
        height: calc(100% - 36px);
        object-fit: contain;
        background: black;
    `;
    pipVideo.controls = true;
    pipContainer.appendChild(pipVideo);
    
    // 添加到页面中
    document.body.appendChild(pipContainer);
    
    // 状态存储
    const videoStates = new Map();
    
    // 为每个视频添加小窗按钮
    videos.forEach((video, index) => {
        // 创建按钮容器
        const btnContainer = document.createElement('div');
        btnContainer.style.cssText = `
            position: absolute;
            bottom: 10px;
            right: 10px;
            z-index: 100;
        `;
        
        // 创建小窗按钮
        const pipBtn = document.createElement('button');
        pipBtn.textContent = '小窗播放';
        pipBtn.style.cssText = `
            background: rgba(255, 107, 107, 0.8);
            color: white;
            border: none;
            padding: 8px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-family: Arial, sans-serif;
            font-size: 14px;
            font-weight: bold;
            backdrop-filter: blur(5px);
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
            transition: all 0.2s;
        `;
        
        pipBtn.addEventListener('mouseover', () => {
            pipBtn.style.background = 'rgba(255, 107, 107, 1)';
            pipBtn.style.transform = 'scale(1.05)';
        });
        
        pipBtn.addEventListener('mouseout', () => {
            pipBtn.style.background = 'rgba(255, 107, 107, 0.8)';
            pipBtn.style.transform = 'scale(1)';
        });
        
        // 添加到视频容器
        if (video.parentNode) {
            video.parentNode.style.position = 'relative';
            video.parentNode.appendChild(btnContainer);
            btnContainer.appendChild(pipBtn);
        }
        
        // 保存原始视频状态
        videoStates.set(video, {
            originalParent: video.parentNode,
            originalIndex: index,
            originalPosition: {
                top: video.style.top,
                left: video.style.left,
                width: video.style.width,
                height: video.style.height,
                position: video.style.position
            }
        });
        
        // 按钮点击事件
        pipBtn.addEventListener('click', () => {
            // 如果小窗已经在播放此视频,则关闭小窗
            if (pipContainer.style.display === 'block' && pipVideo.src === video.src) {
                pipContainer.style.display = 'none';
                pipVideo.pause();
                pipVideo.src = '';
                
                // 恢复原始视频
                if (videoStates.has(video)) {
                    const state = videoStates.get(video);
                    if (state.originalParent) {
                        state.originalParent.appendChild(video);
                        Object.assign(video.style, state.originalPosition);
                    }
                }
                
                video.play();
                return;
            }
            
            // 保存当前播放时间
            const currentTime = video.currentTime;
            
            // 克隆原始视频的源设置
            pipVideo.innerHTML = '';
            const sources = video.querySelectorAll('source');
            sources.forEach(source => {
                const newSource = document.createElement('source');
                newSource.src = source.src;
                newSource.type = source.type;
                pipVideo.appendChild(newSource);
            });
            
            // 设置小窗视频源
            pipVideo.src = video.src;
            pipVideo.currentTime = currentTime;
            pipContainer.style.display = 'block';
            
            // 隐藏原始视频
            video.style.display = 'none';
            
            // 播放小窗视频
            pipVideo.play().catch(error => {
                console.error('小窗视频播放失败:', error);
                // 恢复原始视频
                video.style.display = '';
                pipContainer.style.display = 'none';
                
                // 尝试使用画中画API作为备选方案
                if (document.pictureInPictureEnabled) {
                    video.requestPictureInPicture().catch(pipError => {
                        console.error('画中画API失败:', pipError);
                    });
                }
            });
        });
    });
    
    // 关闭按钮事件
    closeBtn.addEventListener('click', () => {
        pipContainer.style.display = 'none';
        pipVideo.pause();
        pipVideo.src = '';
        
        // 恢复所有视频
        videos.forEach(video => {
            if (videoStates.has(video)) {
                const state = videoStates.get(video);
                if (state.originalParent) {
                    video.style.display = '';
                    state.originalParent.appendChild(video);
                    Object.assign(video.style, state.originalPosition);
                }
            }
        });
    });
    
    // 拖拽功能
    let isDragging = false;
    let offsetX, offsetY;
    
    pipHeader.addEventListener('mousedown', (e) => {
        isDragging = true;
        offsetX = e.clientX - pipContainer.getBoundingClientRect().left;
        offsetY = e.clientY - pipContainer.getBoundingClientRect().top;
        pipContainer.style.cursor = 'grabbing';
    });
    
    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            pipContainer.style.left = (e.clientX - offsetX) + 'px';
            pipContainer.style.top = (e.clientY - offsetY) + 'px';
        }
    });
    
    document.addEventListener('mouseup', () => {
        isDragging = false;
        pipContainer.style.cursor = 'grab';
    });
    
    console.log('小窗播放功能已激活!页面中找到 ' + videos.length + ' 个视频');
    console.log('使用方法:点击视频右下角的"小窗播放"按钮');
})();
相关推荐
胡gh4 小时前
页面卡成PPT?重排重绘惹的祸!依旧性能优化
前端·javascript·面试
胡gh4 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
言兴4 小时前
# 深度解析 ECharts:从零到一构建企业级数据可视化看板
前端·javascript·面试
山有木兮木有枝_4 小时前
TailWind CSS
前端·css·postcss
烛阴5 小时前
TypeScript 的“读心术”:让类型在代码中“流动”起来
前端·javascript·typescript
杨荧5 小时前
基于Python的农作物病虫害防治网站 Python+Django+Vue.js
大数据·前端·vue.js·爬虫·python
Moment6 小时前
毕业一年了,分享一下我的四个开源项目!😊😊😊
前端·后端·开源
程序视点7 小时前
Escrcpy 3.0投屏控制软件使用教程:无线/有线连接+虚拟显示功能详解
前端·后端
silent_missile7 小时前
element-plus穿梭框transfer的调整
前端·javascript·vue.js
专注VB编程开发20年7 小时前
OpenXml、NPOI、EPPlus、Spire.Office组件对EXCEL ole对象附件的支持
前端·.net·excel·spire.office·npoi·openxml·spire.excel