From ec3ca535596378baad15601eb0c62cc4af04e8aa Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 16 Feb 2026 03:47:50 +0000 Subject: [PATCH 1/4] Add ignoreshort option to ignore short media under 10 seconds Notification sounds (e.g. Telegram message received/sent) are typically under 1 second but trigger a full pause of music on other tabs. This adds an "Ignore short media" option with two detection strategies: - Per-media duration check: ContentScript sends element.duration with play messages, background ignores media where duration is finite and < 10s. - Debounce for otherTabs (no content script): delays the pause action by 5 seconds when a tab becomes audible; if it stops being audible before the timer fires, the event is discarded. https://claude.ai/code/session_01HP27yofm1EcQQRuVQRSk41 --- ContentScript.js | 10 ++++++---- background.js | 37 ++++++++++++++++++++++++++++++++++++- options.html | 5 +++++ options.js | 1 + 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/ContentScript.js b/ContentScript.js index 54007eb..e7ae36c 100644 --- a/ContentScript.js +++ b/ContentScript.js @@ -122,7 +122,7 @@ function onPlay(e) { if (isMuted(e)) { send('playMuted'); } else { - send('play', data.id); + send('play', data.id, e.duration); } } @@ -336,12 +336,14 @@ function checkDOM() { } } -function send(message, body = '') { - chrome.runtime.sendMessage({ +function send(message, body = '', duration) { + const msg = { type: message, body: body, userActivation: navigator.userActivation.isActive - }); + }; + if (duration !== undefined) msg.duration = duration; + chrome.runtime.sendMessage(msg); } window.addEventListener( diff --git a/background.js b/background.js index 0dd943e..b36db02 100644 --- a/background.js +++ b/background.js @@ -3,6 +3,9 @@ var state = {}; const resumelimit = 5; +const shortMediaDuration = 10; // seconds +const shortMediaDebounce = 5000; // ms, for tabs without content script access +const pendingAudible = new Map(); const setItems = [ 'media', 'backgroundaudio', @@ -127,6 +130,14 @@ chrome.runtime.onMessage.addListener(async (message, sender) => { state.mutedMedia.add(sender.tab.id); onMute(sender.tab.id); } else { + // Ignore short media (e.g. notification sounds) when option is enabled. + if ( + hasProperty(options, 'ignoreshort') && + isFinite(message.duration) && + message.duration > 0 && + message.duration < shortMediaDuration + ) + break; state.mutedMedia.delete(sender.tab.id); state.media.add(sender.tab.id); onPlay(sender.tab, message.body, message.userActivation); @@ -449,6 +460,10 @@ function remove(tabId) { state.backgroundaudio.delete(tabId); state.mutedTabs.delete(tabId); state.legacyMedia.delete(tabId); + if (pendingAudible.has(tabId)) { + clearTimeout(pendingAudible.get(tabId)); + pendingAudible.delete(tabId); + } onPause(tabId); } @@ -487,8 +502,28 @@ chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (hasProperty(options, 'ask')) chrome.permissions.addHostAccessRequest({tabId: tabId}); } - onPlay(tab); + // Debounce otherTabs when ignoreshort is enabled to filter notification sounds. + if ( + hasProperty(options, 'ignoreshort') && + state.otherTabs.has(tabId) + ) { + if (pendingAudible.has(tabId)) clearTimeout(pendingAudible.get(tabId)); + pendingAudible.set( + tabId, + setTimeout(() => { + pendingAudible.delete(tabId); + if (state.otherTabs.has(tabId)) onPlay(tab); + }, shortMediaDebounce) + ); + } else { + onPlay(tab); + } } else { + // Cancel pending debounce if tab stopped being audible. + if (pendingAudible.has(tabId)) { + clearTimeout(pendingAudible.get(tabId)); + pendingAudible.delete(tabId); + } state.otherTabs.delete(tabId); onPause(tabId); } diff --git a/options.html b/options.html index 43fbedf..87fdecf 100644 --- a/options.html +++ b/options.html @@ -31,6 +31,11 @@

After changes press enter.

+
+ +
Date: Mon, 16 Feb 2026 03:59:18 +0000 Subject: [PATCH 2/4] Change shortMediaDuration from 10 to 3 seconds --- background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/background.js b/background.js index b36db02..8e0c98a 100644 --- a/background.js +++ b/background.js @@ -3,7 +3,7 @@ var state = {}; const resumelimit = 5; -const shortMediaDuration = 10; // seconds +const shortMediaDuration = 3; // seconds const shortMediaDebounce = 5000; // ms, for tabs without content script access const pendingAudible = new Map(); const setItems = [ From 4f9449bcb0cffb4b2da1fe53540bf44504b6b0c3 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 16 Feb 2026 04:06:19 +0000 Subject: [PATCH 3/4] Lower short media threshold from 10s to 3s 3 seconds more precisely targets notification/UI sounds (0.3-1.5s) without accidentally ignoring short voice messages or video clips. https://claude.ai/code/session_01HP27yofm1EcQQRuVQRSk41 --- options.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options.html b/options.html index 87fdecf..14b4212 100644 --- a/options.html +++ b/options.html @@ -33,7 +33,7 @@

After changes press enter.

From a0cffa4bb886d25fbf31b888674d121603fbed09 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 17 Feb 2026 04:31:41 +0000 Subject: [PATCH 4/4] Wait for metadata before reporting media duration Telegram (and similar sites) don't load audio metadata until after the play event, so duration is NaN when onPlay fires. Defer the play message until durationchange fires (with a 500ms timeout fallback for streams where durationchange never fires). This ensures short notification sounds are correctly identified even when metadata loads late. https://claude.ai/code/session_01HP27yofm1EcQQRuVQRSk41 --- ContentScript.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/ContentScript.js b/ContentScript.js index e7ae36c..2556831 100644 --- a/ContentScript.js +++ b/ContentScript.js @@ -121,9 +121,24 @@ function onPlay(e) { let data = Elements.get(e); if (isMuted(e)) { send('playMuted'); - } else { - send('play', data.id, e.duration); + return; } + // If duration is unknown, wait for metadata before reporting to background. + // This lets the background correctly identify short media (e.g. notification sounds). + if (isNaN(e.duration)) { + let sent = false; + const sendOnce = () => { + if (sent) return; + sent = true; + if (!isPaused(e) && !isMuted(e)) { + send('play', data.id, e.duration); + } + }; + e.addEventListener('durationchange', sendOnce, {once: true}); + setTimeout(sendOnce, 500); + return; + } + send('play', data.id, e.duration); } function validMedia(e) {