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

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

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('使用方法:点击视频右下角的"小窗播放"按钮');
})();
相关推荐
Junerver29 分钟前
Kotlin 2.1.0的新改进带来哪些改变
前端·kotlin
千百元1 小时前
jenkins打包问题jar问题
前端
喝拿铁写前端1 小时前
前端批量校验还能这么写?函数式校验器组合太香了!
前端·javascript·架构
巴巴_羊1 小时前
6-16阿里前端面试记录
前端·面试·职场和发展
我是若尘1 小时前
前端遇到接口批量异常导致 Toast 弹窗轰炸该如何处理?
前端
该用户已不存在2 小时前
8个Docker的最佳替代方案,重塑你的开发工作流
前端·后端·docker
然我2 小时前
面试官最爱的 “考试思维”:用闭包秒杀递归难题 🚀
前端·javascript·面试
明月与玄武2 小时前
HTML知识全解析:从入门到精通的前端指南(上)
前端·html
teeeeeeemo2 小时前
CSS place-items: center; 详解与用法
前端·css·笔记
未来之窗软件服务2 小时前
html读取身份证【成都鱼住未来身份证】:CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构
前端·html·身份证读取