AppSheet と Gemini で録音状態の悪い音声ファイルから自然な文字起こしをするアプリ
(心の声) 議事録を作成する必要のある会議を録音するときはマイクの配置に気を遣ってください。 お願いです。 遠くの方でだれかがボソボソ言ってる音声ファイルを持ってきて、 文字起こしアプリって全然あかんやーん。日本語になってへんやーん。 とか言うの勘弁してください… AppSheet でサクッと簡易アプリつくって、何とかそれらしい文字起こしできるようにするわ…
会議や取材記録の文字起こし、便利ですよね。でも収録した場所が騒がしかったり、専門用語が多かったりすると何だかぎこちない文章になってしまいがちじゃないですか?今回は AppSheet と Gemini を使って読みやすく自然な文章で文字起こししてくれるアプリを(なるべく)コードを書かずにサクッと作ってみました。と言いたいところですがサクッといかず色々困ったあれこれの備忘録です。
やろうとしたこと
- 音声ファイルを Google ドライブに保存(手動)
- AppSheet で文字起こしする音声ファイルを選択
- Automation で Google Apps Script(以下GAS)の関数を呼び出す
- GAS から Gemini API を叩いて、音声ファイルをいい具合に文字起こし
- API で取得したトランスクリプトを AppSheet に返す
Automation : 定型的なタスクやワークフローを自動化する機能。データの変更などをトリガーに実行できる。
この流れはすでに画像の解析用途で実績がありました。ほぼ流用で文字起こしアプリが実現できました。10秒のサンプル音声ファイルであれば…。
30分尺の本番用音声ファイルを入れると、ダメです。途中でエラーが発生します。
手直し
その1 Gemini API への音声ファイル送信
画像ファイルやサンプルの短い音声ファイルでは問題なく取り扱えましたが、30分の音声ファイルだと送信できません。GAS から画像などを API リクエストに追加するには Base64 エンコードするのが楽ちんです。リクエストのオプションの " inlineData " にそのままデータを渡すだけです。ただし Base64 エンコードして送れるのは 7MB までです。30分の音声ファイル、無理ですね。そういう場合は 一度Google Cloud Sotrage( 以下 GCS )にアップロードして、その URI を指定します。
var parts = [ { "fileData": { "fileUri": uri, "mimeType": mimeType } }, { "text": prompt } ];
Generative AI on Vertex AI > ドキュメント > モデル情報 > 基盤モデル API > Gemini API モデル
https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models?hl=ja
アプリユーザーの前準備は Google ドライブに音声ファイルを入れるだけにしたいので、AppSheet から呼び出される GAS で Google ドライブから GCS へ音声ファイルをアップロードしてやる必要があります。Google ドライブ → GCS を簡単にできるライブラリどこかに無いかなと探した結果が以前に書いたブログになります。
Tech Nexus Blog
Google Drive から Google Cloud Storage にファイルを簡単にアップロードできるライブラリを探していたら結局自作していた件
その2 AppSheet の Automation 実行時間制限
Gemini による文字起こしも30分の長尺音声ファイルになるとそこそこ時間を要します。GAS から Gemini API を直接呼び出すと 5〜6分間はかかるもののちゃんと実行可能でなかなか良い結果が返ってきます。ところが AppSheet から同じ関数を呼び出すと…2分間で「キャンセル」されてしまうのです。
「自動化の制限」として「アプリのイベントの最大実行時間 2分」とマニュアルにもありました。(なかなか見つけられず苦労しました。)
AppSheet ヘルプ > 自動化を構築する > 自動化の制限
https://support.google.com/appsheet/answer/11828262?hl=ja&ref_topic=11998887
2分間では GAS の関数が終わらないので、Automation の スクリプトの設定で" Run asynchronously " をオンにすることで、非同期で実行させるようにしました。元の作りでは " Return Value " をオンにして戻り値(トランスクリプト)を AppSheet のデータにインサートしていましたが、非同期で実行すると AppSheet で戻り値を処理できないので、 GAS によって AppSheet API で外部から AppSheet のデータを編集するように書き換えました。
AppSheet ヘルプ > 統合 > AppSheet API を使用する > テーブル内のレコードを更新する
https://support.google.com/appsheet/answer/10105002?sjid=7560193196829557429-AP
その3 トランスクリプトが長すぎる
テストの段階では文字起こしされたトランスクリプトも長いものではなく、そのまま AppSheet データベースのセルに放り込んでも問題なかったのですが、30分の音声だとちょっとした文字数になります。「セルあたりの文字数: 2,000」という制限に引っかかってしまいます。そこで、トランスクリプトをテキストファイルにして Google ドライブに保存、そのファイル ID を AppSheet には返すことにしました。
改修後
テスト
音声ファイルを指定して、ロボットアイコンをクリックすると…
- GCS に音声ファイルがアップロードされました
- Gemini API が文字起こしをして、テキストファイルが Google ドライブに保存されました
- AppSheet データベースにテキストファイルの ID が書き込まれました。
- AppSheet のビューからテキストファイルへアクセスし、無事トランスクリプトを表示することができました
最後に
(ほぼ)ノーコードで実現したかった AppSheet + Gemini 文字起こしですが、結局ちょっとコードを書くことになってしまいました。でも前回の Google ドライブ→ GCS ライブラリや今回のノウハウがあれば今後は PoC など色々な用途で AppSheet をフロントエンドにして Gemini を利用することができますね。
肝心の「読みやすい自然な文字起こし」ですが、概ね好評です。プロンプト次第で名前や専門用語もそれなりに正しく解釈されて文章のぎこちなさもかなり緩和されています。ただ意訳の趣があるので、正確性についてはやはり読む側のリテラシーが重要ということになりますが、大体の話の流れが読み取れたらいい場合や、最終的には人手で仕上げる場合にも参考として十分役立つものであることは間違い無いと思います。