如何在Chrome扩展的Content Script中持续检测YouTube视频是否处于广告播放状态
Hey there! I totally get where you're coming from—getting that one-time script to run continuously for ad detection can be tricky, especially when you're new to JavaScript and Chrome extension development. Let's break down a few reliable methods to solve this:
1. Use MutationObserver (Most Efficient)
MutationObserver is built specifically for tracking DOM changes, which makes it ideal for detecting when ads pop up (since YouTube adds/removes ad-related elements from the DOM when ads start/end). Here's how to implement it in your content script:
// Select a parent element that's always present (like the body or YouTube's player container) const targetNode = document.body; // Configure the observer to watch for added/removed child elements const observerConfig = { childList: true, subtree: true, // Watch all nested elements too }; // Callback function that runs when DOM changes are detected const observerCallback = (mutationsList) => { for (const mutation of mutationsList) { // Check if any ad-related elements exist now const isAdPlaying = document.querySelector('.ytp-ad-module') !== null || document.querySelector('ytd-ad-slot-renderer') !== null || document.querySelector('.ytp-ad-overlay-container') !== null; // Do something with the ad state (e.g., send to background script, update your UI) if (isAdPlaying) { console.log('Ad is playing!'); // Your logic here } else { console.log('No ad playing.'); // Your logic here } } }; // Create and start the observer const adObserver = new MutationObserver(observerCallback); adObserver.observe(targetNode, observerConfig); // Don't forget to disconnect the observer when it's no longer needed (e.g., page unload) window.addEventListener('beforeunload', () => { adObserver.disconnect(); });
Note: YouTube's ad element class names might change over time, so you can inspect the page to find the latest selectors (right-click ad → Inspect Element).
2. Simple Interval Polling (Beginner-Friendly)
If MutationObserver feels a bit complex, a timed interval is a straightforward alternative. It checks for ad elements at regular intervals:
// Check ad status every 500ms (adjust the delay as needed) const adCheckInterval = setInterval(() => { const isAdPlaying = document.querySelector('.ytp-ad-module') !== null || document.querySelector('ytd-ad-slot-renderer') !== null; // Handle the ad state if (isAdPlaying) { console.log('Ad detected!'); } }, 500); // Clean up the interval when the page is closed window.addEventListener('beforeunload', () => { clearInterval(adCheckInterval); });
This is easier to set up, though it's slightly less efficient than MutationObserver (since it runs even when nothing changes). For most extension use cases, it works perfectly fine.
3. Inject Script to Use YouTube's Player API (Advanced)
YouTube has a built-in Player API that emits events for ad starts/ends. Since content scripts run in an isolated context, you'll need to inject a script into the page's main context to access the player:
// In your content script, inject a script tag into the page const injectScript = document.createElement('script'); injectScript.textContent = ` // Listen for YouTube player events const player = document.querySelector('video'); if (player) { player.addEventListener('adstart', () => { // Send ad status to content script via postMessage window.postMessage({ type: 'AD_STARTED' }, '*'); }); player.addEventListener('adend', () => { window.postMessage({ type: 'AD_ENDED' }, '*'); }); } `; document.body.appendChild(injectScript); // Listen for messages from the injected script in your content script window.addEventListener('message', (event) => { if (event.data.type === 'AD_STARTED') { console.log('Ad started via Player API!'); // Your logic here } else if (event.data.type === 'AD_ENDED') { console.log('Ad ended via Player API!'); // Your logic here } });
Note: This method relies on YouTube's player events, which might not cover all ad types (like overlay ads), so combining it with MutationObserver can give you full coverage.
Quick Tips
- Make sure your extension's
manifest.jsonincludes the correct host permissions:"host_permissions": ["*://*.youtube.com/*"] - Test with different ad types (pre-roll, mid-roll, overlay) to ensure your detection works in all scenarios.
- If YouTube updates their DOM structure, revisit your selectors to keep the detection working.
内容的提问来源于stack exchange,提问作者user16254995




