本站资源来自互联网收集发布,仅供用于学习和交流。如有侵权之处不妥,请联系站长QQ:9002327删除,敬请谅解。

一个隐藏视频的小玩意

富贵2025-10-07 09:01:1322好玩的网页代码

一个隐藏视频的小玩意

GitHub:https://github.com/IIIStudio/Copy-B

CNB:https://cnb.cool/IIIStudio/HTML/Copy-B

演示:https://iiistudio.github.io/Copy-B/

原理是选择通过 copy /b 命令合并的图片+视频文件

过于简单 ,就不写使用过程了。

点击头像可以更换图片 ,可以拖拽视频到里面也可以点击上传!

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Copy /B</title>
    <style>
        body {
            font-family: "Microsoft YaHei", sans-serif;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            text-align: center;
            background-color: #f5f5f5;
        }
        .container {
        }
        .tab-container {
            display: flex;
            margin-bottom: 20px;
        }
        .tab {
            padding: 10px 20px;
            cursor: pointer;
            background-color: #e0e0e0;
            border-radius: 5px;
            margin-right: 5px;
        }
        .tab.active {
            background-color: #4CAF50;
            color: white;
        }
        .tab-content {
            display: none;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 0 0 5px 5px;
            background-color: white;
        }
        .tab-content.active {
            display: block;
            border: 2px dashed #ccc;
            border-radius: 8px;
        }
        .media-preview {
            max-width: 100%;
            max-height: 300px;
            margin: 15px auto;
            border: 1px solid #ddd;
            border-radius: 5px;
            display: block;
        }
        .video-container {
            position: relative;
            width: 100%;
            max-width: 800px;
            margin: 15px auto;
            background-color: #000;
            border-radius: 5px;
            overflow: hidden;
            display: none;
        }
        .video-container video {
            width: 100%;
            height: auto;
            max-height: 500px;
            display: block;
        }
        .file-input-label, .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 10px 20px;
            min-width: 160px;
            box-sizing: border-box;
            white-space: nowrap;
            background-color: #4CAF50;
            color: white;
            border-radius: 4px;
            cursor: pointer;
            margin: 10px;
            text-align: center;
            border: none;
            transition: background-color 0.3s;
        }
        .file-input-label:hover, .btn:hover {
            background-color: #45a049;
        }
        .btn-secondary {
            background-color: #2196F3;
        }
        .btn-secondary:hover {
            background-color: #0b7dda;
        }
        .btn-danger {
            background-color: #f44336;
        }
        .btn-danger:hover {
            background-color: #da190b;
        }
        #status {
            margin: 15px 0;
            min-height: 20px;
            color: #666;
        }
        .progress-container {
            width: 100%;
            background-color: #f1f1f1;
            border-radius: 5px;
            margin: 10px 0;
            display: none;
        }
        .progress-bar {
            height: 20px;
            border-radius: 5px;
            background-color: #4CAF50;
            width: 0%;
            transition: width 0.3s;
        }
        input[type="text"] {
            padding: 10px;
            width: 80%;
            margin: 10px 0;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        .hidden {
            display: none;
        }
        .controls {
            margin-top: 20px;
        }
        [url=home.php?mod=space&uid=945662]@media[/url] (max-width: 600px) {
            .tab-container {
                flex-direction: column;
            }
            .tab {
                margin-right: 0;
                margin-bottom: 5px;
                border-radius: 5px;
            }
            input[type="text"] {
                width: 95%;
            }
            .video-container {
                max-height: 300px;
            }
        }
 
        #generate .file-input-label,
        #generate #generateBtn {
            width: 150px !important;        
            min-width: 150px !important;    
            height: 40px !important;         
            padding: 0 !important;          
            margin: 10px !important;         
            display: inline-flex !important;
            align-items: center !important;
            justify-content: center !important;
            box-sizing: border-box !important;
            line-height: 44px !important;    
            font-size: 16px !important;
            white-space: nowrap !important;
            vertical-align: middle !important;
        }
        /* 拖拽高亮样式(作用于整个面板区域) */
        .tab-content.drag-accept { position: relative; }
        .tab-content.drag-accept.dragover {
            border-color: #4CAF50 !important;
            box-shadow: 0 0 0 2px #4CAF50 inset;
            background: #f0fff4;
        }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
</head>
<body>
 
    <script>
    document.body.innerHTML = '';
 
    // Create container
    const container = document.createElement('div');
    container.className = 'container';
    document.body.appendChild(container);
 
    // Create heading
    //const h1 = document.createElement('h1');
    //h1.textContent = '隐藏视频播放器';
    //container.appendChild(h1);
 
    // Create tab container
    const tabContainer = document.createElement('div');
    tabContainer.className = 'tab-container';
    container.appendChild(tabContainer);
 
    // Create tabs
    const tabs = [
      { text: '文件生成', tab: 'generate', active: true },
      { text: '本地文件', tab: 'local', active: false },
      { text: 'URL转换', tab: 'url', active: false }
    ];
 
    tabs.forEach(tabData => {
      const tab = document.createElement('div');
      tab.className = `tab ${tabData.active ? 'active' : ''}`;
      tab.textContent = tabData.text;
      tab.setAttribute('data-tab', tabData.tab);
      tabContainer.appendChild(tab);
    });
 
    // Create tab contents
    const tabContents = [
      {
        id: 'local',
        active: false,
        title: '本地文件提取',
        description: '选择通过 copy /b 命令合并的图片+视频文件',
        content: `
          <label for="localFile" id="localChooseLabel">选择本地文件</label>
          <input type="file" id="localFile" accept=".jpg,.jpeg,.png">
           
          <div id="localStatus">等待选择文件...</div>
          <div id="localProgressContainer">
            <div id="localProgress"></div>
          </div>
           
          <img id="localPreview" class="media-preview hidden">
          <div id="localVideoContainer">
            <video controls id="localVideoPlayer"></video>
          </div>
           
          <div>
            <button id="localDownloadBtn" class="btn btn-secondary hidden">下载视频</button>
          </div>
        `
      },
      {
        id: 'url',
        active: false,
        title: 'URL转换工具',
        description: '输入图片URL,提取隐藏视频',
        content: `
          <input type="text" id="imageUrl" placeholder="输入图片URL (如: [img]https://example.com/image.jpg[/img])">
           
          <button id="fetchUrlBtn">提取视频</button>
           
          <div id="urlStatus">等待输入URL...</div>
          <div id="urlProgressContainer">
            <div id="urlProgress"></div>
          </div>
           
          <img id="urlPreview" class="media-preview hidden">
          <div id="urlVideoContainer">
            <video controls id="urlVideoPlayer"></video>
          </div>
           
          <div>
            <button id="urlDownloadBtn" class="btn btn-secondary hidden">下载视频</button>
          </div>
        `
      },
      {
        id: 'generate',
        active: true,
        title: '文件生成工具',
        description: '选择视频文件,生成合并的图片文件',
        content: `
          <div>
            <img id="defaultPreview" src="./img/iii.jpg" title="点击更换图片">
          </div>
          <!-- 隐藏的封面图片选择器 -->
          <input type="file" id="coverImageFile" accept="image/*">
           
          <label for="videoFile">选择视频文件</label>
          <input type="file" id="videoFile" accept="video/*">
           
          <button id="generateBtn">生成合并图片</button>
           
          <div id="generateStatus">等待选择视频文件...</div>
          <div id="generateProgressContainer">
            <div id="generateProgress"></div>
          </div>
           
          <div>
            <button id="generateDownloadBtn" class="btn btn-secondary hidden">下载合并图片</button>
          </div>
        `
      }
    ];
 
    tabContents.forEach(contentData => {
      const content = document.createElement('div');
      content.id = contentData.id;
      content.className = `tab-content ${contentData.active ? 'active' : ''}`;
       
      const h2 = document.createElement('h2');
      h2.textContent = contentData.title;
      if (contentData.id === 'local') h2.id = 'localTitle';
      if (contentData.id === 'url')   h2.id = 'urlTitle';
      content.appendChild(h2);
       
      const p = document.createElement('p');
      p.textContent = contentData.description;
      if (contentData.id === 'local') p.id = 'localDesc';
      if (contentData.id === 'url')   p.id = 'urlDesc';
      content.appendChild(p);
       
      content.innerHTML += contentData.content;
      container.appendChild(content);
    });
 
    // Add tab switching functionality
    const tabsElements = document.querySelectorAll('.tab');
    tabsElements.forEach(tab => {
      tab.addEventListener('click', () => {
        // Remove active class from all tabs and contents
        document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
        document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
         
        // Add active class to clicked tab and corresponding content
        tab.classList.add('active');
        const tabId = tab.getAttribute('data-tab');
        document.getElementById(tabId).classList.add('active');
      });
    });
        // 全局变量
        let currentVideoBlob = null;
        let currentGeneratedBlob = null;
        let droppedVideoFile = null; // 拖拽到“文件生成工具	”的视频文件
        let customCoverImageBlob = null; // 用户自选的封面图片
         
        // 切换选项卡
        document.querySelectorAll('.tab').forEach(tab => {
            tab.addEventListener('click', () => {
                document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
                 
                tab.classList.add('active');
                document.getElementById(tab.dataset.tab).classList.add('active');
            });
        });
         
        // 本地文件处理
        document.getElementById('localFile').addEventListener('change', async function(e) {
            const file = e.target.files[0];
            if (!file) return;
             
            const statusEl = document.getElementById('localStatus');
            const progressContainer = document.getElementById('localProgressContainer');
            const progressEl = document.getElementById('localProgress');
            const videoContainer = document.getElementById('localVideoContainer');
            const videoPlayer = document.getElementById('localVideoPlayer');
            const previewImg = document.getElementById('localPreview');
            const downloadBtn = document.getElementById('localDownloadBtn');
             
            // 重置状态
            statusEl.textContent = "正在处理文件...";
            progressContainer.style.display = 'block';
            progressEl.style.width = '0%';
            videoContainer.style.display = 'none';
            downloadBtn.classList.add('hidden');
            currentVideoBlob = null;
             
            try {
                // 显示预览图片
                previewImg.src = URL.createObjectURL(file);
                previewImg.classList.remove('hidden');
                 
                // 1. 读取文件内容
                const arrayBuffer = await file.arrayBuffer();
                progressEl.style.width = '20%';
                 
                // 2. 查找ZIP文件起始位置
                statusEl.textContent = "正在查找隐藏内容...";
                const uint8Array = new Uint8Array(arrayBuffer);
                let zipStart = -1;
                 
                // 查找ZIP文件头 (PK\x03\x04)
                for (let i = 0; i < uint8Array.length - 4; i++) {
                    if (uint8Array[i] === 0x50 && uint8Array[i+1] === 0x4B && 
                        uint8Array[i+2] === 0x03 && uint8Array[i+3] === 0x04) {
                        zipStart = i;
                        break;
                    }
                }
                 
                if (zipStart === -1) throw new Error("未检测到隐藏内容");
                progressEl.style.width = '40%';
                 
                // 3. 提取ZIP部分
                statusEl.textContent = "正在提取隐藏数据...";
                const zipData = arrayBuffer.slice(zipStart);
                progressEl.style.width = '60%';
                 
                // 4. 使用JSZip解析ZIP
                statusEl.textContent = "正在解析内容...";
                const zip = await JSZip.loadAsync(zipData);
                progressEl.style.width = '80%';
                 
                // 5. 查找视频文件
                statusEl.textContent = "正在查找视频文件...";
                let videoFile = null;
                const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv'];
                 
                for (const [name, file] of Object.entries(zip.files)) {
                    if (!file.dir && videoExtensions.some(ext => name.toLowerCase().endsWith(ext))) {
                        videoFile = file;
                        break;
                    }
                }
                 
                if (!videoFile) throw new Error("未找到支持的视频文件");
                 
                // 6. 提取视频内容
                statusEl.textContent = "正在提取视频...";
                const videoData = await videoFile.async('blob');
                currentVideoBlob = videoData;
                progressEl.style.width = '100%';
                 
                // 7. 播放视频
                videoPlayer.src = URL.createObjectURL(videoData);
                videoContainer.style.display = 'block';
                downloadBtn.classList.remove('hidden');
                 
                statusEl.textContent = `已加载: ${videoFile.name}`;
                 
                // 成功后:隐藏标题	、描述、选择按钮与预览图	,仅保留文件名与视频
                const lt = document.getElementById('localTitle');
                const ld = document.getElementById('localDesc');
                const ll = document.getElementById('localChooseLabel');
                if (lt) lt.style.display = 'none';
                if (ld) ld.style.display = 'none';
                if (ll) ll.style.display = 'none';
                previewImg.classList.add('hidden');
 
                // 自动播放
                videoPlayer.play().catch(e => {
                    statusEl.textContent += " (点击播放按钮开始播放)";
                });
                 
            } catch (error) {
                console.error("处理失败:", error);
                statusEl.textContent = `错误: ${error.message}`;
                progressEl.style.width = '0%';
                videoContainer.style.display = 'none';
            } finally {
                setTimeout(() => {
                    progressContainer.style.display = 'none';
                }, 500);
            }
        });
         
        // 本地图片拖拽上传(整个面板区域可拖拽)
        (function() {
            const dropEl = document.getElementById('local');
            if (!dropEl) return;
            dropEl.classList.add('drag-accept');
            const isImage = (file) => {
                const name = (file.name || '').toLowerCase();
                return file.type.startsWith('image/') || name.endsWith('.jpg') || name.endsWith('.jpeg') || name.endsWith('.png');
            };
            const prevent = (e) => { e.preventDefault(); e.stopPropagation(); };
 
            ['dragenter','dragover'].forEach(ev => {
                dropEl.addEventListener(ev, (e) => { prevent(e); dropEl.classList.add('dragover'); });
            });
            ['dragleave','drop'].forEach(ev => {
                dropEl.addEventListener(ev, (e) => { prevent(e); dropEl.classList.remove('dragover'); });
            });
 
            dropEl.addEventListener('drop', async (e) => {
                const file = e.dataTransfer?.files?.[0];
                if (!file) return;
                if (!isImage(file)) {
                    alert('请拖入 JPG/PNG 图片文件');
                    return;
                }
 
                const statusEl = document.getElementById('localStatus');
                const progressContainer = document.getElementById('localProgressContainer');
                const progressEl = document.getElementById('localProgress');
                const videoContainer = document.getElementById('localVideoContainer');
                const videoPlayer = document.getElementById('localVideoPlayer');
                const previewImg = document.getElementById('localPreview');
                const downloadBtn = document.getElementById('localDownloadBtn');
                currentVideoBlob = null;
 
                try {
                    statusEl.textContent = "正在处理文件...";
                    progressContainer.style.display = 'block';
                    progressEl.style.width = '0%';
                    videoContainer.style.display = 'none';
                    downloadBtn.classList.add('hidden');
 
                    // 预览图片
                    previewImg.src = URL.createObjectURL(file);
                    previewImg.classList.remove('hidden');
 
                    // 读取内容
                    const arrayBuffer = await file.arrayBuffer();
                    progressEl.style.width = '20%';
 
                    // 查找 ZIP 头
                    statusEl.textContent = "正在查找隐藏内容...";
                    const uint8Array = new Uint8Array(arrayBuffer);
                    let zipStart = -1;
                    for (let i = 0; i < uint8Array.length - 4; i++) {
                        if (uint8Array[i] === 0x50 && uint8Array[i+1] === 0x4B && uint8Array[i+2] === 0x03 && uint8Array[i+3] === 0x04) {
                            zipStart = i;
                            break;
                        }
                    }
                    if (zipStart === -1) throw new Error("未检测到隐藏内容");
                    progressEl.style.width = '40%';
 
                    // 提取/解析 ZIP
                    statusEl.textContent = "正在提取隐藏数据...";
                    const zipData = arrayBuffer.slice(zipStart);
                    progressEl.style.width = '60%';
                    statusEl.textContent = "正在解析内容...";
                    const zip = await JSZip.loadAsync(zipData);
                    progressEl.style.width = '80%';
 
                    // 查找视频
                    statusEl.textContent = "正在查找视频文件...";
                    let videoFile = null;
                    const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv'];
                    for (const [name, zf] of Object.entries(zip.files)) {
                        if (!zf.dir && videoExtensions.some(ext => name.toLowerCase().endsWith(ext))) {
                            videoFile = zf;
                            break;
                        }
                    }
                    if (!videoFile) throw new Error("未找到支持的视频文件");
 
                    // 提取视频
                    statusEl.textContent = "正在提取视频...";
                    const videoData = await videoFile.async('blob');
                    currentVideoBlob = videoData;
                    progressEl.style.width = '100%';
 
                    // 播放展示
                    videoPlayer.src = URL.createObjectURL(videoData);
                    videoContainer.style.display = 'block';
                    downloadBtn.classList.remove('hidden');
                    statusEl.textContent = `已加载: ${videoFile.name}`;
 
                    // 成功后:隐藏标题、描述、选择按钮与预览图,仅保留文件名与视频
                    const lt = document.getElementById('localTitle');
                    const ld = document.getElementById('localDesc');
                    const ll = document.getElementById('localChooseLabel');
                    if (lt) lt.style.display = 'none';
                    if (ld) ld.style.display = 'none';
                    if (ll) ll.style.display = 'none';
                    previewImg.classList.add('hidden');
 
                    videoPlayer.play().catch(() => {
                        statusEl.textContent += " (点击播放按钮开始播放)";
                    });
                } catch (err) {
                    console.error('拖拽处理失败:', err);
                    statusEl.textContent = `错误: ${err.message}`;
                    progressEl.style.width = '0%';
                    videoContainer.style.display = 'none';
                } finally {
                    setTimeout(() => { progressContainer.style.display = 'none'; }, 500);
                }
            });
        })();
 
        // 本地文件下载
        document.getElementById('localDownloadBtn').addEventListener('click', function() {
            if (currentVideoBlob) {
                saveAs(currentVideoBlob, 'extracted_video.mp4');
            }
        });
         
        // URL转换处理
        document.getElementById('fetchUrlBtn').addEventListener('click', async function() {
            const imageUrl = document.getElementById('imageUrl').value.trim();
             
            if (!imageUrl) {
                alert("请输入图片URL");
                return;
            }
             
            const statusEl = document.getElementById('urlStatus');
            const progressContainer = document.getElementById('urlProgressContainer');
            const progressEl = document.getElementById('urlProgress');
            const videoContainer = document.getElementById('urlVideoContainer');
            const videoPlayer = document.getElementById('urlVideoPlayer');
            const previewImg = document.getElementById('urlPreview');
            const downloadBtn = document.getElementById('urlDownloadBtn');
             
            // 重置状态
            statusEl.textContent = "正在获取图片...";
            progressContainer.style.display = 'block';
            progressEl.style.width = '0%';
            videoContainer.style.display = 'none';
            downloadBtn.classList.add('hidden');
            currentVideoBlob = null;
             
            try {
                // 显示预览图片
                previewImg.src = imageUrl;
                previewImg.classList.remove('hidden');
                 
                // 1. 获取图片
                const response = await fetch(imageUrl);
                if (!response.ok) throw new Error(`获取图片失败: ${response.status}`);
                 
                progressEl.style.width = '20%';
                 
                // 2. 读取图片内容
                const arrayBuffer = await response.arrayBuffer();
                progressEl.style.width = '40%';
                 
                // 3. 查找ZIP文件起始位置
                statusEl.textContent = "正在查找隐藏内容...";
                const uint8Array = new Uint8Array(arrayBuffer);
                let zipStart = -1;
                 
                for (let i = 0; i < uint8Array.length - 4; i++) {
                    if (uint8Array[i] === 0x50 && uint8Array[i+1] === 0x4B && 
                        uint8Array[i+2] === 0x03 && uint8Array[i+3] === 0x04) {
                        zipStart = i;
                        break;
                    }
                }
                 
                if (zipStart === -1) throw new Error("未检测到隐藏内容");
                progressEl.style.width = '60%';
                 
                // 4. 提取ZIP部分
                statusEl.textContent = "正在提取隐藏数据...";
                const zipData = arrayBuffer.slice(zipStart);
                progressEl.style.width = '80%';
                 
                // 5. 使用JSZip解析ZIP
                statusEl.textContent = "正在解析内容...";
                const zip = await JSZip.loadAsync(zipData);
                 
                // 6. 查找视频文件
                statusEl.textContent = "正在查找视频文件...";
                let videoFile = null;
                const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv'];
                 
                for (const [name, file] of Object.entries(zip.files)) {
                    if (!file.dir && videoExtensions.some(ext => name.toLowerCase().endsWith(ext))) {
                        videoFile = file;
                        break;
                    }
                }
                 
                if (!videoFile) throw new Error("未找到支持的视频文件");
                 
                // 7. 提取视频内容
                statusEl.textContent = "正在提取视频...";
                const videoData = await videoFile.async('blob');
                currentVideoBlob = videoData;
                progressEl.style.width = '100%';
                 
                // 8. 播放视频
                videoPlayer.src = URL.createObjectURL(videoData);
                videoContainer.style.display = 'block';
                 
                statusEl.textContent = `已加载: ${videoFile.name}`;
                 
                // 成功后:仅保留文件名与视频,隐藏其它控件
                const ut = document.getElementById('urlTitle');
                const ud = document.getElementById('urlDesc');
                const urlInput = document.getElementById('imageUrl');
                const fetchBtn = document.getElementById('fetchUrlBtn');
                const urlPrev = document.getElementById('urlPreview');
                const urlDl  = document.getElementById('urlDownloadBtn');
                if (ut) ut.style.display = 'none';
                if (ud) ud.style.display = 'none';
                if (urlInput) urlInput.style.display = 'none';
                if (fetchBtn) fetchBtn.style.display = 'none';
                if (urlPrev) urlPrev.classList.add('hidden');
                if (urlDl) urlDl.classList.add('hidden');
 
                // 自动播放
                videoPlayer.play().catch(e => {
                    statusEl.textContent += " (点击播放按钮开始播放)";
                });
                 
            } catch (error) {
                console.error("处理失败:", error);
                statusEl.textContent = `错误: ${error.message}`;
                progressEl.style.width = '0%';
                videoContainer.style.display = 'none';
            } finally {
                setTimeout(() => {
                    progressContainer.style.display = 'none';
                }, 500);
            }
        });
         
        // URL文件下载
        document.getElementById('urlDownloadBtn').addEventListener('click', function() {
            if (currentVideoBlob) {
                saveAs(currentVideoBlob, 'extracted_video.mp4');
            }
        });
         
        // 点击生成面板图片以更换封面
        (function() {
            const previewImg = document.getElementById('defaultPreview');
            const coverInput = document.getElementById('coverImageFile');
            if (!previewImg || !coverInput) return;
 
            previewImg.style.cursor = 'pointer';
            previewImg.addEventListener('click', () => {
                // 提示并打开文件选择
                coverInput.click();
            });
 
            coverInput.addEventListener('change', async () => {
                const file = coverInput.files && coverInput.files[0];
                if (!file) return;
                // 保存自定义封面并更新预览
                customCoverImageBlob = file;
                try {
                    const objectUrl = URL.createObjectURL(file);
                    previewImg.src = objectUrl;
                    const statusEl = document.getElementById('generateStatus');
                    if (statusEl) statusEl.textContent = `已选择封面图片:${file.name}`;
                } catch (_) {}
            });
        })();
 
        // “文件生成工具”拖拽上传(整个面板区域可拖拽)
        (function() {
            const dropEl = document.getElementById('generate');
            if (!dropEl) return;
            dropEl.classList.add('drag-accept');
            const isVideo = (file) => file.type.startsWith('video/');
 
            const prevent = (e) => { e.preventDefault(); e.stopPropagation(); };
            ['dragenter','dragover'].forEach(ev => {
                dropEl.addEventListener(ev, (e) => { prevent(e); dropEl.classList.add('dragover'); });
            });
            ['dragleave','drop'].forEach(ev => {
                dropEl.addEventListener(ev, (e) => { prevent(e); dropEl.classList.remove('dragover'); });
            });
 
            dropEl.addEventListener('drop', (e) => {
                const file = e.dataTransfer?.files?.[0];
                if (!file) return;
                if (!isVideo(file)) {
                    alert('请拖入视频文件');
                    return;
                }
                droppedVideoFile = file;
                const statusEl = document.getElementById('generateStatus');
                statusEl.textContent = `已选择(拖拽):${file.name}`;
            });
        })();
 
        // 文件生成处理
        document.getElementById('generateBtn').addEventListener('click', async function() {
            const videoFileInput = document.getElementById('videoFile');
            const statusEl = document.getElementById('generateStatus');
            const progressEl = document.getElementById('generateProgress');
            const progressContainer = document.getElementById('generateProgressContainer');
            const downloadBtn = document.getElementById('generateDownloadBtn');
            const videoFile = videoFileInput.files[0] || droppedVideoFile;
 
            if (!videoFile) {
                alert("请选择或拖拽视频文件");
                return;
            }
 
            try {
                statusEl.textContent = "正在准备生成文件...";
                progressContainer.style.display = 'block';
                progressEl.style.width = '0%';
                downloadBtn.classList.add('hidden');
                 
                // 1. 创建ZIP
                const zip = new JSZip();
                zip.file(videoFile.name, videoFile);
                 
                // 2. 生成ZIP
                statusEl.textContent = "正在生成ZIP文件...";
                const zipBlob = await zip.generateAsync({type: 'blob'}, (metadata) => {
                    progressEl.style.width = `${metadata.percent}%`;
                });
                 
                // 3. 获取封面图片(优先使用用户选择的图片)
                let imageBlob;
                if (customCoverImageBlob) {
                    statusEl.textContent = "已选择自定义图片	,正在读取...";
                    imageBlob = customCoverImageBlob;
                } else {
                    statusEl.textContent = "正在获取默认图片...";
                    const imageResp = await fetch('./img/iii.jpg');
                    imageBlob = await imageResp.blob();
                }
                 
                // 4. 合并文件
                statusEl.textContent = "正在合并文件...";
                const mergedBlob = new Blob([
                    await imageBlob.arrayBuffer(),
                    await zipBlob.arrayBuffer()
                ], { type: 'image/jpeg' });
 
                currentGeneratedBlob = mergedBlob;
                statusEl.textContent = "生成成功!";
                downloadBtn.classList.remove('hidden');
 
            } catch (error) {
                console.error("生成失败:", error);
                statusEl.textContent = `错误: ${error.message}`;
                progressEl.style.width = '0%';
            } finally {
                setTimeout(() => {
                    progressContainer.style.display = 'none';
                }, 500);
            }
        });
         
        // 生成文件下载
        document.getElementById('generateDownloadBtn').addEventListener('click', function() {
            if (currentGeneratedBlob) {
                saveAs(currentGeneratedBlob, 'merged_image.jpg');
            }
        });
    // 全局拦截,避免把文件拖到页面其它区域时被浏览器直接打开
    (function() {
        const prevent = (e) => { e.preventDefault(); e.stopPropagation(); };
        window.addEventListener('dragover', prevent);
        window.addEventListener('drop', prevent);
    })();
    </script>
    <style>
        .corner-links {
            position: fixed;
            right: 20px;
            bottom: 20px;
            display: flex;
            align-items: center;
            z-index: 9999;
        }
        .corner-link {
            display: inline-flex;
            align-items: center;
            gap: 8px;
            padding: 8px 10px;
            border-radius: 8px;
            color: #212529;
            text-decoration: none;
            transition: all 0.3s ease;
        }
        .corner-link:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px rgba(0,0,0,0.15);
        }
        .corner-link img,
        .corner-link svg {
            width: 22px;
            height: 22px;
        }
        .corner-link .label {
            font-weight: 600;
            font-size: 0.95rem;
        }
    </style>
    <div aria-label="页面固定链接">
        <a href="https://github.com/IIIStudio/Copy-B" target="_blank" rel="noopener noreferrer" aria-label="前往 GitHub 仓库">
            <!-- 内联 GitHub 图标,避免外部资源依赖 -->
            <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg">
                <path fill="#24292F" d="M12 .5a12 12 0 0 0-3.79 23.41c.6.11.82-.26.82-.58v-2.02c-3.35.73-4.06-1.61-4.06-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.75.08-.74.08-.74 1.2.09 1.83 1.23 1.83 1.23 1.07 1.83 2.8 1.3 3.49.99.11-.78.42-1.3.76-1.6-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.13-.3-.54-1.51.12-3.15 0 0 1.01-.32 3.3 1.23.96-.27 1.99-.4 3.01-.4s2.05.14 3.01.4c2.29-1.55 3.3-1.23 3.3-1.23.66 1.64.25 2.85.12 3.15.77.84 1.24 1.91 1.24 3.22 0 4.61-2.8 5.63-5.47 5.93.43.37.81 1.1.81 2.22v3.29c0 .32.22.7.83.58A12 12 0 0 0 12 .5Z"/>
            </svg>
            <span>Copy-B</span>
        </a>
        <a href="https://cnb.cool/IIIStudio/HTML/Copy-B/" target="_blank" rel="noopener noreferrer" aria-label="前往 Copy-B 文档页面">
            <img src="https://docs.cnb.cool/images/logo/svg/LogoColorfulIcon.svg" alt="CNB Logo">
        </a>
    </div>
</body>
</html>


修改版安卓软件,加群提示为破解者自留,与本站无关 游戏辅助过于长久无法使用。【默认压缩包密码:fgvip】
软件内任何收费,广告宣传,推广信息均为诈骗请勿相信。与本站无关。可反映本站及时删除