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

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

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('使用方法:点击视频右下角的"小窗播放"按钮');
})();
相关推荐
开开心心就好42 分钟前
电脑息屏工具,一键黑屏超方便
开发语言·javascript·电脑·scala·erlang·perl
江号软件分享43 分钟前
有效保障隐私,如何安全地擦除电脑上的敏感数据
前端
web守墓人2 小时前
【前端】ikun-markdown: 纯js实现markdown到富文本html的转换库
前端·javascript·html
Savior`L2 小时前
CSS知识复习5
前端·css
许白掰2 小时前
Linux入门篇学习——Linux 工具之 make 工具和 makefile 文件
linux·运维·服务器·前端·学习·编辑器
中微子6 小时前
🔥 React Context 面试必考!从源码到实战的完整攻略 | 99%的人都不知道的性能陷阱
前端·react.js
秋田君7 小时前
深入理解JavaScript设计模式之命令模式
javascript·设计模式·命令模式
中微子7 小时前
React 状态管理 源码深度解析
前端·react.js
风吹落叶花飘荡8 小时前
2025 Next.js项目提前编译并在服务器
服务器·开发语言·javascript
加减法原则8 小时前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js