2022.12.12
東海オンエアのすきなシーンを共有できるサービスを作りました
この記事は個人開発 Advent Calendar 2022 12日目の記事です<br> 東海オンエアがすきすぎて東海オンエアのすきなシーンを共有できるサービスを作りました
作ったもの
アプリ<br> Githubリポジトリ<br> 制作期間としては2週間で作りました
モチベーション
東海オンエアの動画がすごくすきで、特に気に入ったシーンとか一瞬の煌めきみたいなところはいつでも見返せるようにスクショを撮る習慣がありました。何年も見ているうちに気づいたらスマホのスクショフォルダが東海オンエアで溢れていて、逆に探すのがむずかしくなりました<br> 友達と話す時に過去の動画の一場面を引用したくなるときがよくあり、そういうときにサッとスクショを貼りたいのですが、フォルダの画像が多すぎて遡って探しているうちに次の話題に移ってしまうというときもよくありました<br> そこで、すきなシーンのスクショをアップロードしておき、すぐにその場面を探せるようになりたいなと思いました。あわよくばそのスクショのリンクをシェアしたらOGPとして展開されるような便利ツールがあったら最高だなと思いました<br> ちなみにアイカツ!にはAikatsUP!というものがあります<br> また、スクショを撮り溜めているときに感じるもう一つの不便なところとして、探しているときにもどかしいポイントとして「場面はなんとなく思い出せるのに元の動画がわからない」ということがあります。動画にさえたどり着いてしまえばコメント欄の時間のアンカーでシーンに飛ぶことができるのですが、元の動画自体がわからないと困ります<br> 探している場面のスクショを見つけたらついでにどの動画かもわかると便利そうです<br> なので今回はこれらの課題を解決するサービスを作りました
技術構成
技術構成は今年さわってすきになったものを詰め込みました<br> フロントエンドはNext.js, コンポーネントライブラリはMantine, フォームとバリデーションはReact Hook FormとZod, DBはFirestore, サーバー側で行いたい処理にはCloud Functionsを使っています
気に入っているところ
OGPの展開
作り始めた時のモチベーションにもあった通り、スクショのリンクをシェアしたらOGPとして展開されるようにしました<br>
スクショ一覧のページではフロントエンドから直接Firestoreと通信しているため、ページを開いた時点ではデータはなく、OGP画像はデフォルトで設定されたものが使われてしまいます
<br>
スクショのリンクを共有したときにそのスクショがOGP画像として設定されるためには、サーバー側であらかじめ用意しておく必要があります<br>
まずはNext.jsのAPI routesを使ってスクショのデータを取得するエンドポイントを用意し、スクショごとのページ(/scenes/[id].tsx
)を作ります。このページ内の getServerSideProps
であらかじめデータを取得しておくようにしました。これでhttpリクエストがあったらページのロードを待たずにOGPに使うデータが取得されるようにできました
export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.query
const res = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/scenes/${id}`)
const ogpData = await res.json()
return { props: { scene: ogpData.data } }
}
投稿画面
投稿のUIはボトムシートっぽくしました。下からにゅっと出てくるアニメーションはMantineのTransitionを使いました。かわいくできたと思います
気をつけたこと
アップロードされる画像のサイズ
スクショを撮ったときに、端末によっては画質が良くてファイルサイズが大きくなってしまうこともあります。Firebaseには画像をresizeするextensionがあります。今回はこちらを使いました<br> まずふつうに画像をアップロードすると、Firebase Storageのダウンロードリンクが発行されます。同時にResize Images Extensionが動き出し、リサイズされた画像も生成されます<br> スクショを投稿するとFirestoreにドキュメントが作られ、最初にアップロードした画像のURLがドキュメントに保存されます<br> その後、Cloud Functions側で画像のURLをリサイズ後のものに差し替え、元の画像を削除します
const imageFilename = scene.screenshotURL.slice(85, 121)
const resizedImageFilenamae = `${imageFilename}_640x360`
const ref = bucket.file(`${imagePath}${resizedImageFilenamae}`)
const [metadata] = await ref.getMetadata()
const token = metadata.metadata.firebaseStorageDownloadTokens
const resizedImageUrl = `https://firebasestorage.googleapis.com/v0/b/${bucketId}/o/${encodeURIComponent(
`${imagePath}${resizedImageFilenamae}`,
)}?alt=media&token=${token}`
sceneRepository.updateByBatch(batch, scene.sceneId, {
screenshotURL: resizedImageUrl,
updatedAt: serverTimestamp,
})
実際のコードはこちら<br> こうすることでストレージの容量を圧迫しないようにしました
タグの複数選択
スクショの投稿時に、誰が写っているかのタグをつけることができます。このタグは複数選択することができます。ちょうどMantineにMulti Selectコンポーネントがあり、こちらを使うことですいすい選ぶことができます<br>
今後作りたいもの
スクショを投稿するときに動画のURLと、何分何秒かも書き込めるようにし、動画をクリックしたらすぐにそのシーンに飛べる機能もいずれつけたいと思います
さいごに
明日はTomorrowです