You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用JavaScript实现Chrome视频下载器扩展?

Hey there! Congrats on diving into your first Chrome extension project—video downloaders are super handy, so this is a great starting point. Let’s break down how to build something similar to Video Downloader Plus, step by step, with practical code examples.

Core Implementation Steps

1. Set Up Your Manifest File (manifest.json)

This is the backbone of your extension, defining permissions, UI elements, and core behavior. We’ll use Manifest V3 (the current standard for Chrome extensions):

{
  "manifest_version": 3,
  "name": "My Video Grabber",
  "version": "1.0",
  "description": "Download videos from any web page with a single click",
  "permissions": ["activeTab", "scripting", "downloads"],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ]
}
  • activeTab lets you access the user’s current open tab.
  • scripting allows you to inject JavaScript into web pages.
  • downloads gives you access to Chrome’s download API (bypasses some CORS issues).
  • The content_script ensures our code runs on every page to detect videos.

2. Detect Videos on the Page

First, we’ll create a function to scan the page for <video> elements and extract their source URLs. Add this to content.js:

function getVideoSources() {
  const videoSources = [];
  const videos = document.querySelectorAll('video');

  videos.forEach(video => {
    // Grab direct video src
    if (video.src && video.src.startsWith('http')) {
      videoSources.push({
        url: video.src,
        title: document.title,
        type: video.type || 'video/mp4'
      });
    }
    // Also check <source> child elements (common for multi-quality videos)
    const sourceTags = video.querySelectorAll('source');
    sourceTags.forEach(tag => {
      if (tag.src && tag.src.startsWith('http')) {
        videoSources.push({
          url: tag.src,
          title: document.title,
          type: tag.type || 'video/mp4'
        });
      }
    });
  });

  // Remove duplicate URLs
  return [...new Map(videoSources.map(item => [item.url, item])).values()];
}

3. Add a Floating Download Button (Like Video Downloader Plus)

Video Downloader Plus shows a floating button when videos are detected—let’s replicate that. Add this to content.js:

function createFloatingBtn() {
  const btn = document.createElement('button');
  btn.textContent = '📥 Download Video';
  btn.dataset.videoDownloadBtn = true;
  btn.style.cssText = `
    position: fixed;
    bottom: 20px;
    right: 20px;
    padding: 12px 16px;
    background: #ff4444;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    z-index: 99999;
    font-size: 14px;
    font-weight: 500;
  `;

  btn.addEventListener('click', () => {
    const sources = getVideoSources();
    if (sources.length === 0) {
      alert('No downloadable videos found on this page!');
      return;
    }

    // Use Chrome's download API to avoid CORS issues
    sources.forEach((source, index) => {
      const fileExt = source.type.split('/')[1] || 'mp4';
      const fileName = `${source.title.replace(/[<>:"/\\|?*]/g, '_')}_${index + 1}.${fileExt}`;
      
      chrome.runtime.sendMessage({
        action: 'downloadVideo',
        url: source.url,
        filename: fileName
      });
    });
  });

  document.body.appendChild(btn);
}

// Watch for videos appearing on the page (even if loaded dynamically)
const observer = new MutationObserver(() => {
  const hasVideo = document.querySelector('video') !== null;
  const existingBtn = document.querySelector('[data-video-download-btn]');

  if (hasVideo && !existingBtn) {
    createFloatingBtn();
  } else if (!hasVideo && existingBtn) {
    existingBtn.remove();
  }
});

observer.observe(document.body, { childList: true, subtree: true });

4. Handle Downloads with a Background Script

We need a background script to listen for download requests and use Chrome’s downloads API. Create a background.js file and add it to your manifest:

// Add this to manifest.json
"background": {
  "service_worker": "background.js"
}

Then in background.js:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'downloadVideo') {
    chrome.downloads.download({
      url: request.url,
      filename: request.filename,
      conflictAction: 'uniquify' // Adds a number if filename exists
    }, (downloadId) => {
      if (chrome.runtime.lastError) {
        console.error('Download failed:', chrome.runtime.lastError);
      }
    });
  }
});

5. Add a Popup UI (Optional)

If you want users to access download options via the extension icon, create popup.html:

<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 250px; padding: 16px; font-family: Arial, sans-serif; }
    #downloadBtn { width: 100%; padding: 8px; background: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; }
    #options { margin-top: 12px; }
  </style>
</head>
<body>
  <button id="downloadBtn">Find Videos on Page</button>
  <div id="options"></div>
  <script src="popup.js"></script>
</body>
</html>

And popup.js:

document.getElementById('downloadBtn').addEventListener('click', async () => {
  const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
  
  chrome.scripting.executeScript({
    target: { tabId: activeTab.id },
    function: getVideoSources
  }, (results) => {
    const optionsDiv = document.getElementById('options');
    optionsDiv.innerHTML = '';

    if (!results[0].result.length) {
      optionsDiv.textContent = 'No videos found.';
      return;
    }

    results[0].result.forEach((source, index) => {
      const link = document.createElement('div');
      link.style.padding = '8px 0';
      link.style.borderBottom = '1px solid #eee';
      
      const btn = document.createElement('button');
      btn.textContent = `Download Video ${index + 1}`;
      btn.style.width = '100%';
      btn.style.padding = '6px';
      btn.style.background = '#4CAF50';
      btn.style.color = 'white';
      btn.style.border = 'none';
      btn.style.borderRadius = '4px';
      btn.style.cursor = 'pointer';
      
      btn.addEventListener('click', () => {
        const fileExt = source.type.split('/')[1] || 'mp4';
        const fileName = `${source.title.replace(/[<>:"/\\|?*]/g, '_')}_${index + 1}.${fileExt}`;
        
        chrome.runtime.sendMessage({
          action: 'downloadVideo',
          url: source.url,
          filename: fileName
        });
        window.close();
      });

      link.appendChild(btn);
      optionsDiv.appendChild(link);
    });
  });
});

Key Notes to Keep in Mind

  • CORS Bypass: Using chrome.downloads.download() instead of regular <a> tags avoids most cross-origin download errors.
  • Dynamic Content: The mutation observer ensures we detect videos loaded after the initial page load (like in single-page apps).
  • Copyright Disclaimer: Add a note in your extension description that users should only download videos they have rights to—this protects you legally.
  • Advanced Cases: For streaming videos (like YouTube’s HLS/DASH), you’ll need to capture network requests with the webRequest permission, but that’s more complex. Start with the basics first!

内容的提问来源于stack exchange,提问作者iLiA

火山引擎 最新活动