ぼくフルスタックエンジニア。

フルにスタックされすぎて積んでる人のブログ

reactでタイピングアプリのプロトタイプを作ってみた / 「2020年度未踏IT人材発掘・育成事業」に応募しました

今回は、未踏事業に応募したことの報告と、その時に作成したプロトタイプの技術的な解説を書いていこうと思います。

未踏事業とは、簡単に言えば「今まで見たことも聞いたこともない面白いプロジェクトを応援するよ〜」ってやつで、デザイニウムで誘われて知りました。最初聞いたときは水戸納豆と聞こえて、工場見学か何かだと思っていましたw

応募した企画

f:id:gpioblink:20200310145424p:plain
プロトタイプへのリンク

今回作る予定のものは、「誤答理由判定機能付きディクテーションプラットフォームの作成」で、英語学習に動画とタイピングを足した、新しい英語学習メソッドです。

まずは、ぜひプロトタイプを触ってみてください。動画を再生して、聞き取った内容をぜひ入力してみてください。未実装ですが、本来なら右枠にダミーテキストではなく、間違えた部分の解説が表示されます。

正直、あまり未踏を感じないというか、既存のものを組み合わせただけではないかと思うかもしれません。実際、タイピング部分ならDicaptionTypingTubeが、復習ゲームなら懐かしの特打にだってあります。もちろん私自身、このプラットフォーム全体で見ると、ほとんどの機能は常にどこかにあると思っています。

そこで、今回作るものには次の4つのユニークな特徴があることを強調しておきます。

  • 様々な動画サイトのコンテンツを使える
  • キーボードの入力から誤答理由を判定して活用できる
  • 実際の文法書と構文解析を組み合わせて適切な解説を表示できる
  • タイピングだけで終わらず様々なアプリや機能と連携する

つまり、「キーボードで好きな動画を見ながら文を入力しているだけで自分の語学レベルに応じた今知るべき解説やフォローが得られる」ということです。全く同じ動画で遊んでいても、利用者の傾向に合わせて解説や学習方法が自動的にレコメンドされるのです。これまで、フロントやバックエンドを書くことはあっても、人工知能などをゼロから実装することはありませんでした。未踏を1つの機会として、自分の弱い部分を埋めていこうと思います。(注: 応募段階です)

ここではプロトタイプの技術的な解説もしたいので、詳細な説明は省きます!興味を持たれた方はぜひ全文をご覧ください。

docs.google.com

プロトタイプについて

ここからはプロトタイプの中身について詳しく説明していきます。

まず、今までVueしかやっていなかったため、そろそろ別の言語をと思いReactに挑戦してみました。ちなみに、VueといってもいつもデザインフレームワークのVuetifyとBackend-as-a-ServiceのFirebaseで手抜きばっかりしていました。今回は、キーボードの入力コンポーネントや動画取得のためのバックエンドなどが必要だったためこのような手抜きはせず1つ1つ作っています。

Reactやコンポーネント作成経験ゼロの人がどこにつまづくか知る記事としてもご利用ください(苦笑)

事前学習・環境構築

まず、ReactもStorybookも利用経験がなかったため、Reactは公式の日本語ドキュメントを一通り読み、Storybookは公式のチュートリアルを終しました。 www.learnstorybook.com

また、新しい言語や手法でコードを書くときはリファレンスにするリポジトリを作って、分からなくなったときはそれの通りに実装するようにしています。今回はこのリポジトリに、「create-react-app-typescript-todo-example-2019」を選んでみました。定番のTODOながらHooksはもちろんテストやデザインに関するツールが多数含まれていて、参照するのにとても役立ちました。

github.com

というわけで、ボイラープレートには、create-react-appを使用しました。 create-react-app.dev

コンポーネント作成にはstorybookを使用しましたが、typescriptのテンプレートを使用している場合でも公式サイトにあるやり方では、jsで入ってしまうようでした。いろいろググりまくった結果、この記事の通りやると上手くtsで導入できました。

npx -p @storybook/cli sb init --story-format=csf-ts

Storybook Docs Typescript Walkthrough · GitHub

設計

普通はFigmaのようなプロトタイプツールを使うのでしょうが、やっぱり紙に書いたほうが早いので最近は紙で設計するようにしています。

データをどこで持つかなども含め、画面のレイアウト等を設計しました。

f:id:gpioblink:20200314113701p:plain

タイピングコンポーネント作成

準備ができたので、早速キーボード入力部分のコンポーネントを作成してみます。 CSSのGridを使って、フォントによらず文字を等間隔に並べたりタグバーの表示が簡単に範囲指定出来るように工夫しました。

f:id:gpioblink:20200314105641p:plain

ここでちょっと悩んだのは、キーボードの入力をどこで受け付けるかです。

このアプリでは文字の1つ1つが独立してコンポーネントになっており、それぞれが「入力前」「入力中」「入力完了」といった状態を持つようになっています。 最初は、この独立した文字1つ1つにキーボード入力をもたせるようにしていましたが、同時に入力中になってよいのは入力完了した文字の次の文字1つのみのため、この方法では管理が大変でした。

そのため、タイピングコンポーネント全体でキーボードからの入力イベントを受け取り、それをPropsのバケツリレーで回す形を取りました。

動画再生コンポーネントの作成

今回は、YouTubeに縛らず世界の様々な動画サイトに対応させたかったため、YouTubeの埋め込みプレーヤーはあえて使用せずに、video.jsを使って実装しました。

そのため、YouTubeの埋め込みのリンクではなく、「.m3u8」や「.mp4」といった動画そのもののソースURLが必要になりました。これはPythonの超有名リポジトリyoutube-dlで取得できるので、このソースURLを取得するためのバックエンドをサーバーレスで作成しました。

f:id:gpioblink:20200314112108p:plain

一度にリクエストがあると、「429 Too Many Requests」になって上手くいかないため、キャッシュするなどして対応しています。

このサンプルではYouTubeから動画を取得していますが、この実装方法によりイギリスBBCやオーストラリアSBSなどテレビ局のオンデマンドサービスや、PokemonTVなどのマイナーな配信サービスのサイトURLを使っても動画が取得できるようになっています。

ソースコード

github.com

今回作成したプロトタイプのソースコードはこちらで公開しています。 (バックエンド部分は、video-typing/misc/serverless-video-source-finder/video-typing-backend/に入っています)

今後

今回、設計の面では紙に書いたとは言え、データの持つ場所などかなり適当になってしまいました。 表示だけのコンポーネントがあると思えば、キーボード受付しているものもありあまり良くないと思っています。

結局Fluxも使わずにPropのバケツリレーなどを行なっていたので、また何か開発しつつ改善していこうと思います。(調べてみると、必ずしも悪ではないと書いてありますが、経験が少ないためまだまだよく分かっていません。。)

いま、そんなことを考えながらもう一つReactでアプリを作っているので、完成次第報告していきます。