YouTubeが重い・カクつく時にTampermonkeyでメニュー周辺の負荷を切り分ける方法

YouTube視聴中にブラウザが重い時のメニュー負荷をTampermonkeyで切り分ける方法を示した図解

YouTubeを見ていると、動画がカクついたり、ブラウザー全体が重くなったりすることがあります。

最初はChrome、Edge、Brave、Firefoxなど、使っているブラウザー側の不具合に見えるかもしれません。

ただ、最近の報告では、YouTube側の動画下部メニュー周辺のUI処理が原因候補として挙がっています。特に、高評価・低評価・共有ボタンなどを含む ytd-menu-renderer 周辺で、表示するボタン数や幅の再計算が繰り返され、環境によってブラウザー負荷が高くなる可能性があります。

この記事では、通常の確認手順に加えて、Tampermonkeyを使ってYouTubeのメニュー周辺の負荷を切り分ける方法をまとめます。

なお、これはYouTube公式の修正ではありません。あくまで「原因候補を切り分けるための暫定的な検証方法」として扱ってください。

発生する症状

今回の問題では、次のような症状が出る場合があります。

  • YouTube視聴中に動画がカクつく
  • ブラウザー全体が重くなる
  • YouTubeタブのCPU使用率が高くなる
  • メモリ使用量が急に増える
  • 動画ページを開いたままにしていると徐々に重くなる
  • Chrome、Edge、Brave、Firefoxなど複数ブラウザーで似た症状が出る

この症状は、必ずすべての環境で発生するわけではありません。発生する環境と発生しない環境があるため、ブラウザー設定、拡張機能、表示倍率、YouTube側のUI状態など、複数の条件が関係している可能性があります。

原因候補はYouTubeの動画下部メニュー周辺

Mozilla Bugzillaでは、YouTubeが描画処理のループに入り、再描画にかかる時間が長くなっていく問題として報告されています。

報告内では、YouTubeの動画下部にある高評価・低評価・共有ボタンなどを含む ytd-menu-renderer 周辺が原因候補として挙げられています。

このメニューは、画面幅に応じてボタンの数や表示状態を調整します。ボタンがはみ出すと一部を非表示にし、幅に余裕があると判断すると再び表示する仕組みです。

ところが、環境によっては「ボタンを減らす → 幅が広がったと判断する → ボタンを戻す → またはみ出す」という処理が繰り返され、requestAnimationFrame のループに入る可能性があります。

つまり、動画そのものではなく、動画下部のメニューUIが負荷のきっかけになっている可能性があります。

広告から本編へ切り替わるタイミングも関係する可能性

過去に、Windows 11のChromeで「YouTube広告後に本編が再生されない」「10秒ほどで止まる」という症状を確認したことがあります。

広告から本編へ切り替わるタイミングでは、YouTubeのプレイヤーUIや動画下部メニューが再構成されるため、環境によってはこの再描画処理が負荷のきっかけになっていた可能性があります。

ただし、同じ原因と断定できるわけではありません。Chromeのユーザーデータ、キャッシュ、拡張機能、ハードウェアアクセラレーション、YouTube側の一時的なUI変更など、複数の要因を切り分けて確認する必要があります。

関連する別パターンとして、Chrome環境を作り直してYouTube再生不具合が改善した例もまとめています。

特に、YouTube広告後に本編が再生されない、10秒ほどで止まる、Chrome側のユーザーデータ削除や再インストールで改善する可能性を確認したい場合は、次の記事も参考になります。

関連記事:Windows 11のChromeでYouTube広告後に本編が再生されない時に試したこと

まず試したい通常の確認手順

Tampermonkeyを使う前に、まずは通常の確認から進めます。

順番確認すること目的
1YouTubeページを再読み込み一時的な読み込み不具合を除外する
2ブラウザーを再起動ブラウザー側の一時的な負荷をリセットする
3PCを再起動OS側の負荷やメモリ状態をリセットする
4別ブラウザーで確認ブラウザー固有の問題か切り分ける
5シークレットウィンドウで確認拡張機能やCookieの影響を切り分ける
6拡張機能を一時停止広告ブロック、UI変更系、動画補助系の影響を確認する
7ハードウェアアクセラレーションを切り替えるGPU描画まわりの影響を確認する
8ブラウザーのタスクマネージャーを見るYouTubeタブのCPU・メモリ使用量を確認する

これらで改善する場合は、Tampermonkeyを使う必要はありません。

Tampermonkeyでメニュー周辺の負荷を切り分ける

通常の確認をしても改善しない場合、Tampermonkeyで ytd-menu-renderer 周辺の表示を切り替え、負荷が変わるかを確認します。

今回のスクリプトでは、YouTube動画ページの左下に小さな切り替えボタンを表示します。

クリックするたびに、次のモードを切り替えます。

モード内容使い方
OFF何もしない通常状態基準確認用
FIXytd-menu-renderer の幅を固定最初に試す候補
HIDEytd-menu-renderer を非表示強めの切り分け
ESCytd-menu-renderer を画面外へ退避検証用

右下はYouTube標準の設定・全画面・ミニプレイヤーなどの操作ボタンと重なりやすいため、このスクリプトでは切り替えボタンをブラウザー画面の左下に固定表示しています。

通常表示では、動画プレイヤー内ではなく動画エリアの外に表示される場合があります。ボタンが見つからない場合は、ブラウザー画面の左下付近を確認してください。

全画面表示中は、左下に再生ボタンやシークバーが表示されるため、切り替えボタンを少し上へ移動するようにしています。

Tampermonkeyスクリプト

以下をTampermonkeyの新規スクリプトとして追加します。

// ==UserScript==
// @name         YouTube ytd-menu-renderer Lag Workaround
// @namespace    jp.captim.youtube-menu-lag-workaround
// @version      0.0.1
// @description  YouTubeのytd-menu-renderer周辺による重さ・カクつき疑いを切り分けるための検証用スクリプトです。
// @author       Captim
// @match        https://www.youtube.com/*
// @run-at       document-idle
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
  'use strict';

  const BUTTON_ID = 'captim-yt-menu-lag-button';
  const STYLE_ID = 'captim-yt-menu-lag-style';
  const MODE_KEY = 'captim_youtube_menu_lag_mode';
  const MODES = ['OFF', 'FIX', 'HIDE', 'ESC'];

  let lastUrl = location.href;
  let retryTimer = null;

  function isWatchPage() {
    return location.hostname === 'www.youtube.com' && location.pathname === '/watch';
  }

  function getMode() {
    const saved = GM_getValue(MODE_KEY, 'OFF');
    return MODES.includes(saved) ? saved : 'OFF';
  }

  function setMode(mode) {
    GM_setValue(MODE_KEY, mode);
  }

  function nextMode(current) {
    const index = MODES.indexOf(current);
    return MODES[(index + 1) % MODES.length];
  }

  function getTargets() {
    const selectors = [
      'ytd-watch-metadata ytd-menu-renderer',
      'ytd-video-primary-info-renderer ytd-menu-renderer',
      '#above-the-fold ytd-menu-renderer',
      'ytd-menu-renderer.ytd-watch-metadata'
    ];

    const found = new Set();

    selectors.forEach((selector) => {
      document.querySelectorAll(selector).forEach((element) => found.add(element));
    });

    return Array.from(found);
  }

  function clearTargetStyle(element) {
    [
      'width',
      'min-width',
      'max-width',
      'height',
      'overflow',
      'display',
      'visibility',
      'opacity',
      'pointer-events',
      'position',
      'left',
      'top',
      'transform',
      'contain',
      'flex'
    ].forEach((property) => {
      element.style.removeProperty(property);
    });
  }

  function setImportant(element, property, value) {
    element.style.setProperty(property, value, 'important');
  }

  function applyMode() {
    const mode = getMode();
    const targets = getTargets();

    targets.forEach((element) => {
      clearTargetStyle(element);

      if (mode === 'FIX') {
        setImportant(element, 'width', '360px');
        setImportant(element, 'min-width', '360px');
        setImportant(element, 'max-width', '360px');
        setImportant(element, 'overflow', 'hidden');
        setImportant(element, 'contain', 'layout paint style');
        setImportant(element, 'flex', '0 0 auto');
      }

      if (mode === 'HIDE') {
        setImportant(element, 'display', 'none');
      }

      if (mode === 'ESC') {
        setImportant(element, 'position', 'fixed');
        setImportant(element, 'left', '-9999px');
        setImportant(element, 'top', '0');
        setImportant(element, 'width', '1px');
        setImportant(element, 'height', '1px');
        setImportant(element, 'overflow', 'hidden');
        setImportant(element, 'opacity', '0');
        setImportant(element, 'pointer-events', 'none');
      }
    });

    updateButton();
  }

  function ensureButton() {
    let button = document.getElementById(BUTTON_ID);

    if (!isWatchPage()) {
      if (button) {
        button.remove();
      }
      return null;
    }

    if (!button) {
      button = document.createElement('button');
      button.id = BUTTON_ID;
      button.type = 'button';

      button.addEventListener('click', () => {
        const current = getMode();
        const next = nextMode(current);
        setMode(next);
        applyMode();
      });

      document.body.appendChild(button);
    }

    updateButton();
    return button;
  }

  function updateButton() {
    const button = document.getElementById(BUTTON_ID);
    if (!button) return;

    const mode = getMode();
    button.textContent = `YT Menu: ${mode}`;
    button.setAttribute('data-mode', mode);
    button.title = 'YouTubeメニュー周辺の負荷切り分けモードを切り替えます。';
  }

  function ensureStyle() {
    if (document.getElementById(STYLE_ID)) return;

    const style = document.createElement('style');
    style.id = STYLE_ID;
    style.textContent = `
      #${BUTTON_ID} {
        position: fixed !important;
        left: 12px !important;
        bottom: 12px !important;
        z-index: 2147483647 !important;
        padding: 8px 10px !important;
        border-radius: 999px !important;
        border: 1px solid rgba(255,255,255,.35) !important;
        background: rgba(20,20,20,.86) !important;
        color: #fff !important;
        font-size: 12px !important;
        line-height: 1 !important;
        font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
        cursor: pointer !important;
        box-shadow: 0 2px 8px rgba(0,0,0,.28) !important;
      }

      #${BUTTON_ID}:hover {
        background: rgba(0,0,0,.95) !important;
      }

      #${BUTTON_ID}[data-mode="FIX"] {
        background: rgba(0, 96, 160, .90) !important;
      }

      #${BUTTON_ID}[data-mode="HIDE"] {
        background: rgba(160, 80, 0, .90) !important;
      }

      #${BUTTON_ID}[data-mode="ESC"] {
        background: rgba(120, 0, 120, .90) !important;
      }

      html.captim-yt-fullscreen #${BUTTON_ID} {
        bottom: 84px !important;
      }
    `;
    document.head.appendChild(style);
  }

  function updateFullscreenClass() {
    const isFullscreen = Boolean(document.fullscreenElement);
    document.documentElement.classList.toggle('captim-yt-fullscreen', isFullscreen);
  }

  function scheduleApply() {
    clearTimeout(retryTimer);

    let count = 0;
    const run = () => {
      ensureStyle();
      ensureButton();
      updateFullscreenClass();

      if (isWatchPage()) {
        applyMode();
      }

      count += 1;
      if (count < 6) {
        retryTimer = setTimeout(run, 600);
      }
    };

    run();
  }

  function onNavigationLikeChange() {
    if (lastUrl !== location.href) {
      lastUrl = location.href;
      scheduleApply();
    }
  }

  document.addEventListener('fullscreenchange', () => {
    updateFullscreenClass();
    updateButton();
  });

  window.addEventListener('yt-navigate-finish', scheduleApply);
  window.addEventListener('popstate', scheduleApply);

  setInterval(onNavigationLikeChange, 1000);

  scheduleApply();
})();

使い方

  1. Tampermonkeyをインストールする
  2. 新規スクリプトを作成する
  3. 上記コードを貼り付けて保存する
  4. YouTubeの動画ページを開く
  5. ブラウザー画面の左下付近に表示される YT Menu: OFF ボタンを確認する
  6. クリックして FIX に切り替える
  7. 重さ・カクつき・メモリ使用量が変わるか確認する

最初に試すなら FIX がおすすめです。これで改善する場合は、動画下部メニュー周辺のレイアウト再計算が関係している可能性があります。

HIDEESC は強めの切り分けです。高評価、共有、保存、その他メニューなどの表示や操作に影響する場合があります。

改善しない場合に確認すること

このスクリプトで改善しない場合、ytd-menu-renderer 周辺だけが原因ではない可能性があります。

その場合は、次の点も確認します。

  • ChromeやEdgeのキャッシュ
  • YouTubeのCookieやサイトデータ
  • ブラウザー拡張機能
  • 広告ブロックやUI変更系の拡張機能
  • ハードウェアアクセラレーション
  • ブラウザーの表示倍率
  • Windowsの拡大縮小率
  • 別のGoogleアカウントや未ログイン状態での再現有無

Chrome環境を作り直すことで条件が外れる場合もある

Chromeのユーザーデータ削除や再インストールを検討する場合は、実際に改善した別記事も参考にしてください。

関連:Windows 11のChromeでYouTube広告後に本編が再生されない時に試したこと

この問題は、すべての環境で発生するわけではありません。

そのため、Chromeのキャッシュ、Cookie、サイトデータ、拡張機能、プロファイル設定、表示倍率など、環境側の条件が組み合わさったときに症状が出ている可能性があります。

過去には、Windows 11のChromeでYouTube広告後に本編が再生されない、または10秒ほどで止まる症状について、Chromeのユーザーデータを含めて削除し、Chromeを再インストールすることで改善した例もありました。

これはChromeを入れ直すことでYouTube側の問題を修正したというより、ローカルに残っていたキャッシュやユーザーデータ、拡張機能設定などがリセットされ、負荷が発生する条件から外れた可能性があります。

ただし、Chromeのユーザーデータ削除は影響が大きいため、最初に試す方法ではありません。実施する場合は、ブックマーク、パスワード、拡張機能、ログイン情報などをバックアップしてから行ってください。

注意点

  • このスクリプトはYouTube公式の修正ではありません
  • YouTubeの画面構造が変わると動作しなくなる可能性があります
  • 高評価、共有、保存、その他メニューの表示に影響する場合があります
  • 通常利用に支障がある場合は OFF に戻してください
  • 不要になった場合はTampermonkey側でスクリプトを無効化してください

参考情報

まとめ

YouTube視聴中にブラウザーが重い・カクつく症状では、動画そのものではなく、動画下部メニュー周辺のUI処理が原因候補になる場合があります。

特に ytd-menu-renderer 周辺では、表示するボタン数や幅の再計算が繰り返され、環境によって高負荷につながる可能性があります。

今回のTampermonkeyスクリプトは、その部分が関係しているかを切り分けるための暫定的な検証方法です。

まずは通常の確認手順を試し、それでも改善しない場合に FIX モードから確認するのが安全です。

改善しない場合は、Chromeのユーザーデータ、キャッシュ、拡張機能、表示倍率など、環境側の条件もあわせて確認してください。

Windows11 関連の相談先・運営者情報

Windows11 の不具合対処や更新情報に関する記事を読んだ方向けに、運営者情報と相談先を整理しています。連絡は X を基本窓口とし、内容確認後に対応可否をご案内します。

Xでご依頼・ご相談 ホームを見る

Windowsの不具合対処や更新情報は、確認できた範囲で随時整理しています。内容により個別対応できない場合があります。