2ヶ月間のハッカソンで動画チャプター自動生成アプリを作成した記録

# はじめに
私はオンラインITスクールに所属しています。
そのスクール内で開催されるハッカソンに参加し動画チャプター自動生成アプリ「ちゃぷたん」を作成しました。
github：https://github.com/hackathon-autumn-c/chaptan

そしてこの「ちゃぷたん」をもとに個人で開発を行い、チャプター&要約自動生成してくれる動画共有アプリ「video-learn」を作成しました。

:::note warn
現在アプリは公開していません
:::

<!--
:::note
「video-learn」公開中です。**月〜金の10-19時**に起動しています
サイト：https://video-learn.site
github：https://github.com/to-u-ko/video_learn
:::
-->


今回転職活動にあたってこのアプリをポートフォリオとして提出するため、ハッカソンと個人開発のそれぞれの開発記録を書きたいと思います。

この記事はハッカソンの開発記録になります。
個人開発の記録→https://qiita.com/ttookk/items/98ff4c30a2f5e8b42237



# ハッカソンの概要
スクール受講生の中から参加希望者を4~6名のチームに分け、各チームでWebアプリケーションの開発を行います。
初級コース(お題は決まっている/サンプルコードあり)と上級コース(お題・使用技術自由・全て自力)があり、私は初級コースに2回参加経験があっため今回は上級コースに挑戦しました。

- 期間は2ヶ月間
- メンバーは6人
- 全員社会人で実務の開発経験はなし(ハッカソンの参加経験は全員あり)
- お題、使用技術は自由
- 要件定義〜デプロイまですべて自分たちだけで実施

# アプリの概要と作成意図
スクールでは週2回/2時間のオンライン講義があります。講義は録画され終了後にスクールのポータルサイトにアップロードされるため、受講生はいつでも好きな時に視聴することが可能です。
しかし、ポータルサイトに掲載されるのは動画とタイトルのみ。
以下のような不便さがありました。
- 動画の一部の説明だけ聞きたいが自分の聞きたい説明がどこから始まるか分からない
- 講師の自己紹介や休憩時間などは飛ばしたい
- 動画を続きから見たいけどセッションが切れてどこまで見たか分からない
- 動画タイトルのみだと事前に講義の全体像を把握することができない

そこで、動画のチャプターがあればこれらの課題を解決できるのではないかということで、「動画チャプター自動生成アプリ」を作成することに決まりました。

**■ターゲット(使用者)**
スクールの講師
**■課題**
生徒はより効率的に講義動画で学習を行うために動画のチャプターを必要としている。しかし講師としては毎回チャプターを作成するのは大変
**■どのように解決するのか？**
動画チャプター自動生成アプリがあれば、動画をアップロードするだけでチャプターを自動生成してくれる。講師は生成されたチャプターをポータルサイトに貼り付けるだけでよいため負担が少なくてすみ、生徒はチャプターを使ってより効率的に動画の視聴ができる。

# 使用技術・ツール
- バックエンド：Python(Django)
- データベース：MySQL
- フロントエンド：HTML/CSS/JavaScript
- デザイン：figma
- インフラ：AWS/Docker
- エディタ：VScode
- コード管理：git/github
- 情報共有,進捗管理：Notion
- 連絡ツール：Mattermost
- ミーティング：ovice


# 機能
アプリの機能を一言で表すと「動画をアップロードするとチャプターを自動で生成してくれるアプリ」です。
以下が機能一覧で、○のついているものが私の担当した部分です。

||機能 |機能の説明 |
|---|---|---|
||ユーザー認証機能|ユーザーのログイン/ログアウトする機能|
|○|動画アップロード機能|動画をアップロードする機能|
|○|動画アップロード時の「アップロード中」表示機能|動画アップロード後、ページ遷移するまでの間「アップロード中」というメッセージを画面に表示する機能|
||動画再生機能|画面上で動画を再生する機能|
|○|動画の文字起こし機能|動画の文字起こしテキストをダウンロードできる機能|
|○|動画のチャプター生成機能|アップロードされた動画のチャプターを自動生成して表示する機能|
||動画のチャプター編集機能|自動生成されたチャプターを手動で編集・保存する機能|
|○|動画ジャンプ再生機能|各チャプターをクリックすることでそのチャプターの開始時点にジャンプして再生することができる機能|
||動画一覧表示機能|チャプター分けした動画情報を一覧表示する機能|
||チャプター生成の処理進捗の表示機能|チャプターの生成には時間がかかるため処理の進捗状況をステータスとして表示する機能|
||チャプター生成の処理進捗のメール通知機能|処理の進捗状況をメールで通知する機能|
||チャプター生成エラー時のメール通知機能|処理途中でエラーが発生した際にメールで通知する機能|
||管理画面でのデータベース管理機能(Django標準の管理画面)|管理画面でデータの追加・更新・削除ができる機能(Django標準の管理画面を使用)|

# 画面遷移
※映っている動画はデジタル庁のYoutubeの動画です。サンプルとして使用しています。
[デジタル庁｜年次活動報告　2023年9月](https://youtu.be/mkyBxjGb2RQ)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852685/ec769745-6e8f-4a23-c20f-5bcf822ab772.png)


# ER図
![ER図-chaptan.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852685/1b034bce-8972-d5cc-c935-01891ffd0da6.jpeg)

テーブル設計はとてもシンプルです。
UsersカラムはDjangoのカスタムユーザーを継承しているため本来はもっと沢山カラムがありますが、ここではアプリで使用するカラムのみ記載しています。

# チャプター生成処理
以下の図はチャプター生成処理の流れです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852685/67b412ab-c5e6-570d-c95a-be8516eddd61.png)




### ■Celeryを使った非同期タスク処理
通常の同期処理だと、動画アップロード後チャプター生成が終わるまでページ遷移ができないことになります。そのためpythonの非同期タスクキューライブラリであるCeleryを使いチャプター生成処理を非同期で実行するようにしました。

https://docs.celeryq.dev/en/stable/getting-started/introduction.html

### ■faster-whisperを使った文字起こし処理
「python　文字起こし」で調べると音声認識AIモデルの「whisper」が一番に出てきます。
whisperにはいくつか種類があって、APIとして利用するopenAIのwhisper API(有料)や、openAIがgithub上に公開しているオープンソースのwhisper、別の組織がopenAIのwhisperをもとにより高速に処理できるように改良したfaster-whisperなどがあります。お金をかけたくなかったため無料で使えるwhisperとfaster-whisperで検証を行い、より出力結果の良かったfaster-whisperを採用しました。

https://github.com/SYSTRAN/faster-whisper

https://zenn.dev/piment/articles/24269616aa9c04

### ■APサーバとしてGPU搭載のEC2を使用
faster-whisperを使った文字起こし処理はCPUで行うと動画と同等かそれ以上の時間がかかります。(2時間の動画だと2時間〜2時間半ぐらいかかる）
GPUを使うと6分の一ぐらいの時間(2時間の動画で20分ほど)ですみます。
そこでGPU搭載のEC2(g4dn.xlarge)を使用することとしましが、その分コストは大きくなります。

### ■chatGPT APIを使ったチャプター生成
チャプター生成処理にはChatGPT API（モデルはGPT-4）を利用しました。最大の課題は、GPT-4が扱えるトークンの数に限りがあることでした。GPT-4は入力と出力を合わせて最大32,000トークンまで処理できますが、スクールの講義動画を文字起こしすると約30,000から60,000文字になります。平仮名が1文字につき1〜2トークン、漢字が1文字につき2〜3トークンを消費するため、一回のリクエストで全てを処理することはできません。
この問題を解決するため、langchainという大規模言語モデルを扱うためのPythonライブラリを使用しました。langchainにはテキストを特定の文字数で分割し、それぞれに対して同じプロンプトを繰り返し実行し、最後に結果を一つにまとめる機能があります。これにより、大量のテキストに対するチャプター生成が可能となりました。

https://www.langchain.com/

# インフラ構成図
![インフラ構成図-Page-1のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852685/a207dc4d-174e-2d72-c85b-aa5558ef46d4.jpeg)

- パブリックサブネットが2つありますが、1つはALB設置のために用意したダミーのサブネットです。
- 文字起こし処理がCPUだとどうしても時間がかかりすぎるためGPU搭載のEC2(g4dn.xlarge)を利用しました。
- APサーバ上でデータベース(MySQL)も一緒に起動しています
- ドメイン取得、SSL化はしていません。



<!-- 
# 苦労した点
### GPUの使用
動画の文字起こしにはfaster-whisperを使用しましたが、処理に大体動画と同じだけの時間がかかります。
つまり2時間の講義動画だと2時間ぐらいかかります。
さすがに長過ぎる・・・ということでGPUの使用を検討しました。
しかしGPUの使用で気になるのはコストの問題・・・
なんとか安くGPUを使用する方法はないか？ということで、APサーバーと文字起こし処理のサーバーを分けて、文字起こしのみGPUマシンで実行する、機械学習用のGPUサービスであるAWS Sagemakerを使用するなどの案がでましたが、最終的にはAPサーバー自体をGPUのEC2にするという方法になりました。
(正直いうとデプロイに間に合わせるには一番シンプルな方法になりました)
なるべく安くということでスポットインスタンスを使用しました。


### 非同期処理の実装
動画アップロード機能〜チャプター生成までの処理を実装する中で気づいたのがページ遷移の問題。
GPUを使うにしろ、動画の文字起こし〜チャプター生成はどう頑張っても数分〜数十分はかかります。
それを普通にview関数の中に書いていてはその間ページ遷移できない！ということになってしまいます。
ということで文字起こし〜チャプター生成処理をバックグラウンドで実行し、ページ遷移は自由にできる方法を調べてCeleryを使った非同期処理にたどり着きました。
-->


# 総評
課題提起からアプリのデプロイまでサービス開発の一通りの工程を経験しとても勉強になりました。
正直、要件定義の段階では「これ本当に実装できるか？」と思っていましたが、とにかくやってみよう精神で色々試しす→みんなで結果を共有→次に活かすというサイクルを重ねアプリを完成させることができました。
講師からは、講義動画に関する課題を提起しその課題をちゃんと解決するアプリを作れている点、ページ遷移の問題に対して非同期処理という解決策を見つけそれを実装できている点を高く評価いただきました。一方、チャプターの精度や運用コストについては指摘されました。そのあたりは今後の課題だと感じています。