リストキーワードフィルタをYouTubeで実装してみた

contents section

みなさん、こんにちは!

第9回の168(いろは)プロジェクトでは、YouTubeのキーワードフィルターを開発しました!

今回はありそうでなかったツールの開発を行いました。

何のために作ったのか?

開発理由はシンプルで”好みではない動画を見ないため”です。

・事前に特定のキーワードが引っかかる動画は見たくない

・最近まで見ていたジャンルだけど今は見たくないのにおすすめ動画として出てくる

・検索したら近しいジャンルだけど見たくない動画も検索に引っかかる

という様にYouTube のおすすめ機能が進化し、アップロードされる動画数も多くなったが故に様々な形で好みではない、または出来れば見たくない動画に遭遇することが増えた気がします。

そんな時にキーワードフィルター出来ればいいのにと思う様になりました。

もちろん見たくない動画を発見したらアカウントブロックしたり試聴を避ければ良いのですが、切り抜き動画の出現等で一つのアカウントをブロックしても、更に別のアカウントで似た様な動画が流れたりすることが多くなった様に感じます。

(切り抜き動画も面白い場面だけをサクサク見れるので時間効率という点では有難いのですが、似た様に動画を前にも見たなという気持ちになることも増えた気がします。)

そんな悩みを解決したい!

フィルター機能に近しい機能は多々あるがこれだ!という機能は公式にない!

無いなら作っちゃえばいいじゃん!

というのが開発のきっかけになります。

今回の機能の使い方

ソースコードはhttps://github.com/engclass-z/youtube_word_filterになります。 こちらの README をご覧ください。

試してみる際は、自己責任の範囲で利用してください。

技術的な話

今回はブラウザ拡張機能と Charles を用いて API レスポンスを操作することでキーワードフィルタ機能を実現しています。

Chrome 拡張機能として実装する場合、基本的にはブラウザから投げられる API のレスポンスに対して何か作用することは難しいですが、今回は background で動く service worker として、debugger の機能を用いて実現しました。

YouTube から動画一覧取得時に実行される API を調べ、その API が投げられようとしたときに一度その API を debugger の機能を用いて停止し、それと同じ API を自前で投げ直す、ということをしています。

レスポンスが正しく返ってきたら自前のフィルタ処理を行って動画一覧を間引いて元の API 通信のコンテキストで使用します。その際、停止していた元の API は完全に終了させることで通信内容を差し替える、という処理を実現させることに成功しました。

ただしこの処理には問題があり、Chrome 拡張の中から通信を投げた場合にリクエストヘッダに含まれる Origin がサイトのものではなく、Chrome 拡張のものになってしまいます。

YouTube の API は Origin が YouTube のものでないと403 が返ってきてしまうのでこれを解決しないといけないのですが、Origin は禁止ヘッダー名(Forbidden header name)に指定されているため、JavaScript から変更することが出来ません。

この問題を解決するのに、今回は Charles を使いました。Charles を使うことで PC から外部に対して行われる通信の内容を解析したり変更したりすることができるため、これを用いて Origin の値を YouTube サイトの値に書き換えることで通信が成功するようにしました。

かなり力技で解決するような方法になってしまいましたが、これらを組み合わせることでなんとかキーワードフィルタリングの機構を自前で作成することが出来ました!

最後に

このプロジェクトでは一週間という期限を設けてサービスを作るということを大事にしているのでここまで作りましたが、時間があれば
・ショート動画にもフィルターをかける
・ハッシュタグにもフィルターを使える様にする
等で様々なシーンでフィルター機能が使える様に出来たら面白そうだなと思いました。

その他、今回はYouTubeの通信に干渉する必要がありましたが、おすすめ動画は公開しているAPIが無かったので自分達でどのAPIに干渉したらフィルター出来るかを探すのが楽しかったりしました。

開発自体は以前にもChromeの拡張機能を作っていたので、中身の機能に集中出来てスムーズな開発が出来ました。

今後機会があったら上記に記載したようにフィルター機能にも挑戦したいと思います! ではでは($・・)/~~~..