Youtubeの画質は下げた状態が一番良いのだ。テザリング生活者にとってデータ通信量は死活問題なのだから。
というわけで、クロームの拡張機能制作の第二弾として「Youtubeの画質下げる君」に着手したお話。
とても難航しましたが、なんとか目的を達成。
この手の操作はYoutubeが公開しているapiを通じて操作をするものと思っていましたが、このapiは、動画プレイヤーをウェブページに埋め込む時を想定しているようで、つべ本家のページで設定をいじる情報が中々出なくて困りました。
調べ物をしている途中、
本家ページで、コンソールに「document.getElementById('movie_player').playVideo()」とか打てばプレイヤーを操作できるんだよ、という情報をキャッチ。
え、マジで? と思って実際やってみたら...プレイヤーが操作できた。
こ、こんなことが可能だったのかどぉー! 知らなかったどぉーーーーー!!!(重ちぃー風)
もしかしてapiの読み込みとかいらないのか?ただ命令を飛ばせばプレイヤーが操作できるのでは?
今回の機能の動作イメージとしては
つべの動画ページを開く →
getPlaybackQuality()で動画の画質情報をゲット →
低画質でなかった場合は強制的に低画質に設定 setPlaybackQuality() →
動画を選ぶたびに画質チェックとセットをしなおす。これだけです。
さて、具体的な可能性は...
1 Content Scriptを使う。
2 Event Script(Background Script)を使う。
3 javascriptをページにインジェクトし操作する。
この三つです。
1はDOMアクセスはできるけどページ内の関数にはアクセスできない。2はDOMアクセスも関数アクセスもできない。ページ内の関数にアクセスできるのは、3のインジェクトスクリプトのみ。
つまり...
インジェクトスクリプト「画質情報をゲット、結果をコンテンツスクリプトに通知します」 →
コンテントスクリプト「むむ、高画質再生してますぞ! 低画質に直しなさい!」 →
インジェクトスクリプト「オス!画質設定を直しました! 結果を通知します」 →
コンテントスクリプト「うむ、よろしい」
みたいな感じになりますかね。
ただし調べてみると、インジェクトスクリプトにメッセージを飛ばしたり、逆にメッセージを送ってもらうことは基本的に無理な様子 ※できます、詳細は追記にて。
画質を調べた結果の通知や画質を設定したいときの命令通知をどうするのか...
えーいもどかしい。
メッセージとか無視して、インジェクトしたスクリプトから有無をいわさず画質を設定することは可能、onClickイベントで早々に動作確認が出来ました。ハイめでたし。でもなぜかload / onload関数が効かないのです...画質変更は自動でして欲しいのに。
さて、せっかくなのでメッセージのやりとりをもう少しがんばってみた所、以下の書式でインジェクトスクリプトからコンテントスクリプトへのメッセージ通知に成功。
new CustomEvent('関数名', { 'プロパティ名': データ });
コンテントスクリプト内でイベント設定し、インジェクトスクリプト内で上の関数にプロパティとしてデータを持たせ。コンテントスクリプト内で引数としてゲットできます。なんかわけがわからないので嫌になりました。
やっぱ素直にapiを通すのが良かったのかなどと思いつつ、作業終了。
追記:
・ウェブページからメッセージを送受信するには、マニフェストファイルでの設定とonMessageExternalを使うことで可能、ただしコンテントスクリプトとではなく、バックグラウンド / イベントスクリプトとの通信になります。
・load / onload関数が実行されないのは謎のままですが、ページの変換をMutationObserverで監視することで同じ機能を実装できました。
・学習のためにメッセージの送受信にこだわっていましたが、動作のみを考えると不要。実際の挙動は コンテントスクリプトからYoutubeページにスクリプトをインジェクト → そのスクリプトにて画質を取得したり低画質に設定する関数を叩く、インジェクトされたスクリプトにはMutationObserverも仕込んであり、ページの移動を監視し、新しい動画ページに移った時に画質の取得と設定を繰り返すだけです。
さて、誰のPCにイタズラで仕込んでやろうか...。