Расширение для гугл хром, режим моно для звука

Доброй ночи, вот решил написать для себя расширение для Гугл хром, просто мне надоели школьники на Ютубе которые в одно ухо только звук записывают. Подскажите как мне написать расширение чтобы JavaScript обращался к звуковой дорожке, чтобы она передавала звук в 2 уха. Предложения просто найти сторонние расширения отклоняются сразу, иначе бы я не просил помощи, как минимум мне интересно как это сделать и получить опыт работы в создании расширений, спасибо за отклики!

content.js:(function () {
  let audioContext = null;
  let mediaSourceMap = new Map();

  function findActiveAudioContexts() {
    if (!audioContext) {
      audioContext = new (window.AudioContext || window.webkitAudioContext)();
    }
    return audioContext;
  }

  const ctx = findActiveAudioContexts();

  function adjustVolume(media, volumeLimit, boostVolume) {
    if (!mediaSourceMap.has(media)) {
      const source = ctx.createMediaElementSource(media);
      mediaSourceMap.set(media, source);
      const gainNode = ctx.createGain();
      source.connect(gainNode);
      gainNode.connect(ctx.destination);

      media.volume = Math.min(volumeLimit / 100, 1);

      if (boostVolume > 0) {
        gainNode.gain.setValueAtTime(Math.pow(10, boostVolume / 20), ctx.currentTime);
      }
    }
  }

  function enableMono(media) {
    const source = ctx.createMediaElementSource(media);
    const leftGain = ctx.createGain();
    const rightGain = ctx.createGain();

    // Проверка, какой канал активен
    leftGain.gain.value = media.volume > 0 ? 1 : 0; // Если звук есть, оставляем его
    rightGain.gain.value = media.volume > 0 ? 1 : 0; // Если звук есть, оставляем его

    // Подключение источников
    source.connect(leftGain);
    source.connect(rightGain);

    // Создаем gainNode для контроля общего уровня громкости
    const gainNode = ctx.createGain();
    leftGain.connect(gainNode);
    rightGain.connect(gainNode);

    gainNode.connect(ctx.destination);
    
    media.play();
  }

  chrome.runtime.onMessage.addListener((message) => {
    if (message.type === 'applyVolumeSettings') {
      const { volumeLimit, boostVolume, monoEnabled } = message;
      const mediaElements = document.querySelectorAll('audio, video');
      mediaElements.forEach(media => {
        adjustVolume(media, volumeLimit, boostVolume);
        
        // Включение моно режима, если он активирован
        if (monoEnabled) {
          enableMono(media);
        }
      });
    }
  });
})();


popup.js:document.addEventListener('DOMContentLoaded', () => {
  const volumeLimitInput = document.getElementById('volumeLimit');
  const volumeInput = document.getElementById('volumeInput');
  const boostVolumeInput = document.getElementById('boostVolume');
  const boostInput = document.getElementById('boostInput');
  const monoCheckbox = document.getElementById('monoCheckbox');
  const saveSettings = document.getElementById('saveSettings');
  const siteLabel = document.getElementById('siteName');
  const volumeWarning = document.getElementById('volumeWarning');

  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      const url = new URL(tabs[0].url);
      const domain = url.hostname;
      let siteType = 'Other Site';
      if (domain.includes('youtube.com')) siteType = 'YouTube';
      if (domain.includes('vk.com')) siteType = 'VK';
      siteLabel.textContent = siteType;

      chrome.storage.sync.get([siteType], (data) => {
          const settings = data[siteType] || { volumeLimit: 75, boostVolume: 0, monoEnabled: false };
          volumeLimitInput.value = settings.volumeLimit || 75;
          volumeInput.value = settings.volumeLimit || 75;
          boostVolumeInput.value = settings.boostVolume || 0;
          boostInput.value = settings.boostVolume || 0;
          monoCheckbox.checked = settings.monoEnabled || false;

          updateVolumeWarning(settings.volumeLimit || 75);
      });
  });

  volumeLimitInput.addEventListener('input', () => {
      volumeInput.value = volumeLimitInput.value;
      updateVolumeWarning(volumeLimitInput.value);
  });

  boostVolumeInput.addEventListener('input', () => {
      boostInput.value = boostVolumeInput.value;
  });

  saveSettings.addEventListener('click', () => {
      const volumeLimit = parseInt(volumeLimitInput.value);
      const boostVolume = parseInt(boostVolumeInput.value);
      const monoEnabled = monoCheckbox.checked;

      chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
          const url = new URL(tabs[0].url);
          const domain = url.hostname;
          let siteType = 'Other Site';
          if (domain.includes('youtube.com')) siteType = 'YouTube';
          if (domain.includes('vk.com')) siteType = 'VK';

          const settings = { volumeLimit, boostVolume, monoEnabled };
          chrome.storage.sync.set({ [siteType]: settings }, () => {
              console.log('Settings saved for', siteType);
          });

          applySettingsToPage(volumeLimit, boostVolume, monoEnabled, tabs[0].id);
      });
  });

  function updateVolumeWarning(volume) {
      if (volume > 85) {
          volumeWarning.textContent = "Опасно! Уровень звука выше 85 дБ может быть вреден для слуха.";
      } else {
          volumeWarning.textContent = "";
      }
  }

  function applySettingsToPage(volumeLimit, boostVolume, monoEnabled, tabId) {
      chrome.scripting.executeScript({
          target: { tabId: tabId },
          func: (volumeLimit, boostVolume, monoEnabled) => {
              const mediaElements = document.querySelectorAll('audio, video');

              mediaElements.forEach(media => {
                  media.volume = Math.min(volumeLimit / 100, 1);

                  if (boostVolume > 0) {
                      let boostFactor = boostVolume / 100; // Преобразуем в коэффициент
                      media.volume = Math.min(media.volume * (1 + boostFactor), 6); // Максимум 600%
                  }

                  if (monoEnabled) {
                      enableMono(media);
                  }
              });
          },
          args: [volumeLimit, boostVolume, monoEnabled]
      });
  }
});


background.js:
chrome.runtime.onInstalled.addListener(() => {
  chrome.storage.sync.set({
    YouTube: { volumeLimit: 75, boostVolume: 0, monoEnabled: false },
    VK: { volumeLimit: 75, boostVolume: 0, monoEnabled: false },
    'Other Site': { volumeLimit: 75, boostVolume: 0, monoEnabled: false }
  });
});
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SoundFixer</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            width: 300px;
            padding: 10px;
            background-color: #f0f0f0;
            color: #333;
        }
        .vertical-slider-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-bottom: 20px;
        }
        button {
            width: 100%;
            padding: 10px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
    </style>
</head>
<body>
    <h1>SoundFixer</h1>
    <div>Текущий сайт: <span id="siteName">Other Site</span></div>

    <div class="vertical-slider-container">
        <label for="volumeLimit">Пиковая громкость (0-100 дБ):</label>
        <input type="range" id="volumeLimit" min="0" max="100" value="75">
        <input type="number" id="volumeInput" min="0" max="100" value="75">
    </div>

    <div class="vertical-slider-container">
        <label for="boostVolume">Усиление громкости (0-600%):</label>
        <input type="range" id="boostVolume" min="0" max="600" value="0">
        <input type="number" id="boostInput" min="0" max="600" value="0">
    </div>

    <div class="vertical-slider-container">
        <label for="monoCheckbox">Моно режим:</label>
        <input type="checkbox" id="monoCheckbox">
    </div>

    <button id="saveSettings">Сохранить настройки</button>
    <div id="volumeWarning" style="color: red;"></div>
    <script src="popup.js"></script>
</body>
</html>

<!--- Содержимое Манифеста manifest.json

{
  "manifest_version": 3,
  "name": "SoundFixer",
  "version": "1.0",
  "permissions": ["activeTab", "scripting", "storage"],
  "action": {
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ],
  "background": {
    "service_worker": "background.js"
  }
}
--->


Ответы (0 шт):