日記

日本語の勉強のためのブログ

YouTube動画の投稿日時が隠れるので別の場所に表示するブックマークレット+Chrome拡張

2022/08/26追記
この記事に記したブックマークレットについて、大きな問題点を直した修正版を以下記事に載せたので、もし使用する場合はそちらを使ってください。 everykalax.hateblo.jp

1. はじめに

PCでYouTubeの動画を閲覧しているときに,たまに投稿日時がほかのボタンに隠されてしまう状況が発生する.
これは,スーパーサンクスや動画のダウンロード,クリップを許可しているチャンネルの動画にはそれらのボタンが追加されるために生じる.

文字だけでは説明しづらいため,スクリーンショットを撮った.
図1は標準的な動画画面であり,投稿日時が問題なく表示されている.
図2はスーパーサンクスなどが許可されている動画の画面であり,投稿日時が隠れて見えなくなってしまっている.
※隠れていることの証拠に,図3のようにページの表示倍率を変更すると見えるようになるが,文字が小さく少し見づらい.

図1. 標準的な動画画面
図2. 投稿日時が隠れてしまった動画画面.再生数も巻き添えを食らっている.
図3. 表示倍率を95%→85%に縮小したら見えるようになったが,文字が小さくなって見づらい.

これを解決するためにブックマークレットを作成した.
なお,暇なときにChrome拡張機能にしようと思っているので,そちらも作成したら追記する.作成したので4節に追記した.

2. 環境

  • Windows10 home
  • Vivaldi 5.3.2679.58 (Stable channel) (64-bit)

おそらくChromeでも動作すると思う.

3. ブックマークレットの作成

完成したものがこちら.

javascript:(function(){document.getElementById("owner-sub-count").innerText+=" / "+document.querySelector("div#info-strings>yt-formatted-string").innerText;
}());

これを実行すれば,チャンネル登録者が表示されている部分に投稿日時が追記される.
表示個所はどこでもよかったので,今回はその位置に表示することにした.

ブックマークレットの使用法については次の記事などを参照.

ブックマークレットの登録方法 - Qiita

実行後の動画画面を図4に示す.投稿日時がチャンネル登録者数の横に表示されたことが確認できる.

図4. ブックマークレット実行後の動画画面

3.1 作成手順(読み飛ばしてもらって結構です)

特に難しい部分はない.日時をクエリセレクタで取得し,別の適当な場所に追記するだけである.
スペースが余っている部分を探した結果,ここではチャンネル登録者数が表示されている部分に追記することにした.

日時はdocument.querySelector("div#info-strings>yt-formatted-string").innerTextで,チャンネル登録者数が表示されている要素はdocument.getElementById("owner-sub-count")で取得できるから,あとは後者に前者を追記するだけである.

4. Chrome拡張機能の作成

荒削りではあるがひとまず完成したため,GitHubに上げた.

github.com

(2022/06/24 追記)
関連動画などから別の動画画面に遷移すると以前の表示が残ったままになる現象を確認した.再読み込みすれば正常に機能するので,必要な際はリロードしてほしい.また時間あったら直すつもり.

(2022/06/26 追記)
閲覧数も表示するようにした.またフォーマットもちょっと修正.

4.1 作成手順

まず,ロードし終えたら実行するように以下のコードを書いたが,失敗した.

window.addEventListener("load", () => {
    document.getElementById("owner-sub-count").innerText += " / " + document.querySelector("div#info-strings>yt-formatted-string").innerText;
});

なぜ失敗したのかというと."load"イベントが発火した後に投稿日時などのDOMが生成される仕様となっていたためである.
そのため,"load"イベントに頼らずに,それらのDOMが生成されるまで待つ必要がある.

いろいろ調べた結果,愚直にsetInterval()setTimeout()を使用してループを組み,待機している例が多かった[1][2][3].そのアイデアを用いて自分なりにコードを組んでみたところ,うまく動作した.

以下に作成したコード(script.js)の概略(疑似コード)を示す.

if (URLが"https://www.youtube.com/watch~"という形式ならば) {
    setInterval(() => {
        if (チャンネル登録者数のDOMが存在する(すでに生成された)ならば){
            clearInterval();
            チャンネル登録者数のDOMに投稿日時を追記する;
        }
    }, 300ミリ秒);
}

なお,1行目で動作対象のURLかどうかを調べているが,これは,manifest.jsonでは動作対象のURLをhttps://www.youtube.com/watch?v=<動画ID>のように指定することができないためである.
具体的には,https://www.youtube.com/*のような指定しかできないため,これでは登録チャンネル一覧のページhttps://www.youtube.com/feed/subscriptionsなども誤検知してしまう(おそらく).
そのため,手間ではあるがscript.jsでも確認するようにしている.

参考資料

[1] jsで対象のDOMが出現するまで待つ(javascript) | Once and Only
[2] 【Javascript】setInterval()で要素が現れるまで待つ - Qiita
[3] javascript — 要素が存在するまで待つ方法は?

その他,以下のページは非常に役立った.
2. 実践編 - Chrome 拡張機能を作ろう

また,この記事の図に使用した動画は以下の通り.