🎤

Web検索を組み合わせた文字起こしアプリを作ってみた

に公開

本アプリケーションは音声ファイルが長くなるほど字幕表示タイミングがズレるため、2025/06/29時点では製品としての利用できるものではありません。

作ったもの

動画の字幕用文字起こしアプリを作りました。
専門用語や固有名詞に対して精度の高い文字起こしを行うため、Web検索も利用するアプローチをとってみました。

https://github.com/yukyu30/gemini-str-app/

本記事では、作成したアプリの概要と、実装についてお話しします。

デモンストレーション

以下の文章を読み上げて、本ツールで字幕生成して、アプリ上でプレビューした動画です。

こんにちは!先日、オリジナルグッズ作成・販売サービスの「SUZURI」で『スリスリAIチャット(β)』を開発・リリースしました。LLMを活用してチャットベースのUIで好みのアイテムを探すことができる機能になります。また、LLMが自然な会話を得意としていることから、SUZURIキャラクターのスリスリくんと雑談をすることもできます。

今回は、開発の経緯や目指したユーザー体験、具体的な技術面に関してご紹介いたします!
AIチャットで商品検索 | GPT-3とLangChain活用より引用

「すずり」という単語を、書道で使う硯ではなく、サービスとしての「SUZURI」として文字起こしされていることが確認できます。一方で、「スリスリくん」を「スリスリ君」として認識しており、こちらは誤っています。

また、文字起こしをするだけではなく
冒頭の「えーと」っといったフィラーワードの除外、
「今回の、あっ、ごめんなさい」などの言い直した発言の除外なども行えています

https://youtu.be/7HaJjrirt_8

動機

動画の字幕を調整する時に、固有名詞や専門用語などがうまく文字起こしできなかったためです。
精度を上げる方法としてWeb検索してもらったらいいんじゃないかと思い作ってみました。

アプリの機能

音声ファイルをアップロードすると、字幕ファイルフォーマットであるであるSRTファイルが生成されます。

SRTファイルについて

SRTファイルの構造は以下の3つの要素から成り立っています。

  1. 通し番号
    各字幕ブロックの識別番号(1, 2, 3, …)
  2. タイムコード
    字幕の表示開始時刻と終了時刻(例: 00:00:01,000 –> 00:00:04,000)
  3. 字幕テキスト
    実際に表示される字幕の内容

各ブロックは空行で区切られ、複数の字幕を記述できます。

1
00:00:01,405 --> 00:00:02,325
こんにちは。

2
00:00:02,875 --> 00:00:04,875
先日、オリジナルグッズ作成

  1. 最大文字数/字幕
    1つの字幕に対する文字数の最大数を指定できます。字幕が2行で表示しないようにこのオプションを設定しました
  2. 話者識別
    話している人を字幕に入れるようにする機能です。字幕の先頭に女性、男性などとつける用になります。
  3. 処理モード
    高精度モードにするとWeb検索を用いて文字起こしをします。標準モードはGeminiで一回文字起こしをするだけです。

  1. SRTダウンロード
    SRTファイルのダウンロードを実行するボタン
  2. 辞書CSVダウンロード
    Web検索を用いて作成した辞書をダウンロードするボタン
  3. コピー
    出力された字幕をクリップボードにコピーするボタン

字幕プレビュー機能もあり、音声を再生しながら生成された字幕を確認できます。

問題点

音声ファイルが長くなると、字幕のタイミングがズレる

短い音声だったら問題ないのですが、音声ファイルが長くになるにつれて、字幕のタイミングがズレます。

お金がかかる

これを作る過程で、試していたら一日で9,000円ほど使いました。
日常的に文字起こしを行う人は、金銭面からもおすすめはできません


ここからはこのアプリケーションの技術について解説します。

技術構成

このアプリはTauriを使用したデスクトップアプリケーションとして開発しています。

フロントエンドは React(TypeScript)です。

https://tauri.app/

文字起こしのフロー

  1. 音声ファイルのアップロード
  2. 初回文字起こし(gemini-2.5-pro)
  3. 話題抽出(gemini-2.0-flash)
  4. キーワードや話題に関するWeb検索を行い、辞書作成
  5. 最終文字起こし(gemini-2.5-pro)

文字起こしの簡単な実装は音声の理解|Gemini APIに書かれています。

1. 音声ファイルのアップロード

今回は音声ファイルをFiles APIを使ってアップロードします。
インラインでも送信はできますが、Files APIを使うことで20MBを超えたファイルのアップロードもできます。
https://ai.google.dev/gemini-api/docs/audio?hl=ja#upload-audio

2. 初回文字起こし結果

Gemini 2.5 Proで最初の文字起こし行います。

プロンプト

音声ファイルの長さも解析して、プロンプトに付与しています。

文字起こしの基本プロンプト
# 1. SRTファイルの基本構造について

まず、納品していただくSRTファイルの構造について共通認識を持つために、基本的なルールを説明します。SRTファイルは、以下の4つの要素が1セットとなって構成されるテキストファイルです。

1.  **通し番号:** `1`から始まる字幕の連番です。
2.  **タイムスタンプ:** `時:分:秒,ミリ秒 --> 時:分:秒,ミリ秒` の形式で、字幕の表示開始時間と終了時間を指定します。(例: `00:01:23,456 --> 00:01:28,912`)
3.  **字幕テキスト:** 画面に表示する文章です。改行を含めず、インラインで記述してください
4.  **空行:** 各字幕ブロックを区切るための、何も書かれていない行です。必ず必要です

**【具体例】**
1
00:00:05,520 --> 00:00:08,910
これは1番目の字幕の
テキストです。

2
00:00:09,150 --> 00:00:11,300
そして、これが2番目の字幕です。

この構造を厳密に守ってファイルを作成してください。.srtファイルとして納品してください

# 2. 文字起こしの詳細なルール

上記の基本構造を踏まえ、以下の詳細なルールに従って作業を進めてください。

1.  **タイムスタンプの精度**
    - `hh:mm:ss,ms` の形式を厳守し、ミリ秒は3桁で記述してください。
    - 音声の発話タイミングと字幕の表示タイミングを正確に一致させてください。

2.  **字幕テキストの編集ルール**
    - **文字数制限:** 1つの字幕ブロック(通し番号1つにつき)のテキストは、**{}文字以内**を目安にしてください。長くなる場合は、意味の区切りが良い箇所で改行するなど、読みやすさを最優先してください。
    - **フィラーワードの削除:** 会話中の「えーっと」「あのー」「なんか」といった、意味を持たないフィラーワードはすべて削除し、自然で聞き取りやすい文章にしてください。{}

3.  **品質要求**
    - 字幕として読みやすく、視聴者にとって理解しやすい文章にしてください。
    - 音声が不明瞭な部分は [不明瞭] として記録してください。
    - 無音部分や間は適切に反映し、字幕の切り替えタイミングを自然にしてください。

**時間の精度が重要です。時間が合っているか確認をしたのち、最終的にSRT形式のテキストのみを出力してください。説明や前置きは不要です。**

**音声ファイルの長さ: {}分{}秒 ({}ms)**
音声の長さを考慮して、適切な字幕の分割と表示タイミングを決定してください。

生成結果

1
00:01.405 → 00:02.325
こんにちは。

2
00:02.875 → 00:06.075
先日、オリジナルグッズ作成販売サービスのすずりで

3
00:06.325 → 00:09.915
スリスリAIチャット、βを開発リリースしました。
生成されたテキスト全文
1
00:01.405 --> 00:02.325
こんにちは。

2
00:02.875 --> 00:06.075
先日、オリジナルグッズ作成販売サービスのすずりで

3
00:06.325 --> 00:09.915
スリスリAIチャット、βを開発リリースしました。

4
00:10.295 --> 00:13.235
LLMを活用してチャットベースのUIで

5
00:13.235 --> 00:15.335
好みのアイテムを探すことができる機能になります。

6
00:15.895 --> 00:19.415
また、LLMが自然な会話を得意としていることから

7
00:20.925 --> 00:23.515
すずりキャラクターのスリスリ君と

8
00:23.515 --> 00:24.755
雑談をすることもできます。

9
00:25.105 --> 00:25.865
今回の

10
00:26.685 --> 00:27.355
ごめんなさい。

11
00:27.565 --> 00:30.015
今回は開発した経緯や目指したユーザー体験、

12
00:30.015 --> 00:32.605
具体的な技術面に関してご紹介いたします。

3. 話題抽出

Gemini 2.0 Flashで音声から重要なキーワードを抽出します。
今回では以下のような結果になりました。

生成結果

キーワード: すずり, スリスリAIチャット, LLM, スリスリ君

4. Web検索による辞書作成

抽出されたキーワードをもとにweb検索を行い、話題に関する情報を調査し、文字起こし用の辞書を作成します。
GeminiにWeb検索行わせる指定方法は以下のドキュメントに書いてあります。

https://ai.google.dev/gemini-api/docs/google-search?hl=ja#javascript

プロンプト

{}に出てくる用語の辞書を構築して。
表記、ふりがなのみをセットでcsv形式で記載してください。
topic自体に誤字脱字がないか確認してから、辞書を作成してください。
日本語話者がわかるような辞書にしてください。固有名詞は正式な表記が何か調べてください。
「自己紹介と職務経歴に関するIT分野の用語集ですね。..に関する用語を調べ、CSV形式で出力します」といった説明や補足、コードブロックの囲いなどCSVと関係ないものは一切禁止されています。CSVデータのみを出力してください。

ログと生成結果

検索クエリ

 "webSearchQueries": [
        "すずり IT用語",
        "スリスリAIチャットとは",
        "LLM 正式名称 読み方",
        "大規模言語モデルとは",
        "スリスリ君とは"
      ]

生成された辞書

表記,ふりがな
,すずり
SUZURI,すずり
スリスリAIチャット,すりすりえーあいちゃっと
LLM,えるえるえむ
大規模言語モデル,だいきぼげんごもでる
スリスリ君,すりすりくん

5. 辞書を活用した最終文字起こし

作成した辞書を参照して、より正確な字幕を生成します

生成結果

1
00:00:01,405 --> 00:00:02,325
こんにちは。

2
00:00:02,875 --> 00:00:04,875
先日、オリジナルグッズ作成

3
00:00:04,875 --> 00:00:06,075
販売サービスのSUZURIで

4
00:00:06,325 --> 00:00:08,515
スリスリAIチャットβを

5
00:00:08,515 --> 00:00:09,915
開発リリースしました。

6
00:00:10,295 --> 00:00:11,535
LLMを活用して

7
00:00:11,535 --> 00:00:13,235
チャットベースのUIで

8
00:00:13,235 --> 00:00:14,635
好みのアイテムを探すことが

9
00:00:14,635 --> 00:00:15,335
できる機能になります。

10
00:00:15,895 --> 00:00:18,015
また、LLMが自然な会話を

11
00:00:18,015 --> 00:00:19,415
得意としていることから

12
00:00:20,925 --> 00:00:22,515
SUZURIキャラクターの

13
00:00:22,515 --> 00:00:23,515
スリスリ君と

14
00:00:23,515 --> 00:00:24,755
雑談をすることもできます。

15
00:00:27,565 --> 00:00:28,915
今回は開発した経緯や

16
00:00:28,915 --> 00:00:30,015
目指したユーザー体験、

17
00:00:30,015 --> 00:00:31,505
具体的な技術面に関して

18
00:00:31,505 --> 00:00:32,605
ご紹介いたします。
GMOペパボ株式会社

Discussion