Quden の〇〇を支える技術
TIP
アーキテクチャ全体像は Quden アーキテクチャ を参照してください
WARNING
このドキュメントの内容は2021年頃に書かれたものが中心です。内容が古くなっている可能性があります。
Chrome 拡張
概要
Chrome 拡張は、React を TypeScript で書きつつ、トランスパイルして webpack でバンドル化することで開発している。
Chrome 拡張の開発に関する全体像は、ドキュメント[1]やQiita記事[2]を参照してほしい。
TIP
2021年2月5日現在ドキュメントを見ると version 3 のドキュメントが出てくるが、toruca は version 2 で開発している(開発スタート時点で v2 しかなかったため...移行が難しくないなら移行したい)
上記のドキュメントや記事を見れば、Chrome 拡張には以下の3つの世界が存在することが理解できると思う。
- Content scripts
- ブラウザに表示されている Web ページに対して挿入されるスクリプト
- Web ページ上の DOM を操作できる
- Web ページに存在するスクリプトとは独立している
- このページで、DOM(React)を注入して、メニューを表示させている
- Background scripts
- Chrome を起動している間、バックグラウンドで起動し続けるスクリプト
- このスクリプトで「録画」や「サーバーへの送信」などの処理を行う
- Page action
- 拡張機能をクリックしたときに実行するアクションを記述する
toruca では、Custom Elements [3] という仕組みを使って、オリジナルの DOM を定義して、web ページに注入している。このようにしている主な理由は「Webページに存在する JavaScripts や CSS から独立した環境を作ることができるから」である。
Chrome 拡張開発において理解するのに時間がかかったのは、クリックなどで発生するイベントの受け渡しである。
Qiitaの記事[2]などにも書いてあるが、content scripts から利用できる chrome API が制限されており、操作したい API を直接 content scripts から呼び出すことができない。さらに、content scripts から注入した React コンポーネントからの chrome API 呼び出しは全くできない状況である。
そこで、ワークアラウンドとして、以下のような手順を踏んでいる。
- 「content scripts も、content scripts から注入した DOM/scripts(React) もDOM を共有している」ということを利用して、カスタムイベントで DOM を経由して React → content scripts へのイベントを伝える
- content scripts はそのイベントを受け取って、background にイベントを伝える
いわば、chrome API をプロキシを通して操作している感じである。
TODO: あとでキレイに図示する。。。
ここまでの仕組みを理解するのに結構苦労した。。
なにはともあれ、上述のように Chrome extension 開発はイベントを3つの世界の間でやり取りすることによって機能を実現している。それらのイベントがやり取りされる方向を図示した概念図を下記のドキュメントにまとめている。
参考リソース
- [1] Extensions - Chrome Developers
- [2] Chrome Extension の作り方 (その1: 3つの世界) - Qiita
- [3] Using custom elements - Web Components | MDN
動画録画(クライアント側)
概要
ファーストリリースにおいて、録画クライアントとなるのは Chrome 拡張機能である。(将来的にはよりリッチな機能提供のために Desktop アプリの開発を目指している)
Chrome 拡張の background 上で、MediaRecorder [1] などの API を利用して、録画を行っている。
2021年2月5日時点での想定では、MediaRecorder で録画したキャプチャを、録画中も随時細切れにサーバーに送信し、サーバー側でデータを concat して保存する、という仕組みを取ろうとしている。
参考リソース
動画録画(サーバー側)
概要
Loom の技術ブログ[1]はキャプチャを保存して配信する全体像を掴むのに参考になる。
仕様を変更をしたので、以下にまとめつつある。
参考リソース
- [1] Behind the Scenes: Building Loom for Desktop - Loom Blog
- [2] node.js - How to concat chunks of incoming binary into video (webm) file node js? - Stack Overflow
- 動画の録画・配信まわりの技術仕様
動画配信
概要
Webm コンテナ形式で保存されるキャプチャ動画を、以下のような構成で DASH [3]に変換して、配信することを想定している。いわゆる adaptive streaming をやりたい。
もちろん、DASH などに対応していないクライアント向けに、mp4 などの静的ファイルに保存する必要もありそう。
AWS Elemental MediaConvert [2] を使って、動画を変換できるので、かなり楽になりそうな感覚がある。コストを考慮して、将来的には docker で ffmpeg をぶん回して変換したりする。かも。
動画などのストリーミングの技術に関しては、[4], [5], [6] あたりのドキュメントからディグりつつ、理解を深めてほしい。(自分もまだ全然ちゃんと理解できていないので、是非知見を共有してほしい。。。)
あらくんが教えてくれた書(AWSによるサーバーレスアーキテクチャ(Peter Sbarski 長尾 高弘 吉田 真吾)|翔泳社の本)気になる。。
参考リソース
- [1] オンデマンド動画配信のためのクラウド構成と料金試算例 | AWS
- [2] AWS Elemental MediaConvert(動画を処理してオンデマンドコンテンツを準備)| AWS
- [3] AWS Elemental MediaConvert で WebM DASH 出力が利用可能に
- [4] ウェブの音声や動画のライブストリーミング - 開発者ガイド | MDN
- [5] HTML 5 ビデオ用の DASH アダプティブストリーミング - Web メディア技術 | MDN
- [6] Web技術で実装するAdaptive HTTP Streaming | TOAST Meetup
コア API (NestJS)
概要
フレームワークには NestJS [1] を利用している。NestJS は TypeScript で書ける Node.js のサーバーサイドアプリケーション向けフレームワークである。
少々学習コストがある気がするので、是非ドキュメント[1]に一通り目を通してほしいところではある。
参考リソース
データモデル
概要
データモデルは概要だけ決めつつ、スプリントごとに詳細を決めていきたいところではある。
ストレージ・DBとしては以下のようなものの利用を想定している。(確定し次第、更新します)
- S3
- Schema-less DB (MongoDB)
動画プレイヤー
概要
このプロダクトで重要なコンポーネントとなってくるのが、動画プレイヤーである。
以下のような機能を実現しつつ、UI/UX の優れた動画プレイヤーを開発したい。
- 動画をトリムする
- 動画上にボタンを表示する
- 動画上にリアクションを表示できる
- and more...
動画プレイヤーの開発方法は、スクラッチで開発したり、video.js [1] のような OSS を改造する方法があり、決めあぐねている。これも良い方法があったら教えてほしい。。。