富贵博客 · 免费提供绿色软件、活动线报以及其他网络资源,好货不私藏!
  • 网站首页 > 好玩的网页代码 正文

    一个隐藏视频的小玩意

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

    QQ20251007-090105.png

    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>


    猜你喜欢

    标签列表
    免责声明
    本站广告鱼龙交杂 站长不担保 请自行鉴定,如遇欺诈广告或损害用户利益请第一时间联系我们邮箱:fengge@111.com处理!本站注册机和注册信息及软件的文章仅限用于学习和研究目的。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络收集整理,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。如果您喜欢该程序和内容,请支持正版,购买注册,得到更好的正版服务。我们非常重视版权问题,如有侵权请邮件与我们联系处理。敬请谅解!
    友情链接