Google Apps ScriptでGeminiを叩いて音声から字幕生成【GAS】

2025年2月24日にGoogle Drive上の動画に対する自動字幕機能が公開と聞いてやってみたものの、どうやら対応してるのは英語のみで。日本語の自動字幕は未対応のようです。またYoutubeの動画を海外展開したいとなったら、自動生成ではない字幕を動画に追加して展開することで、アクセス数上昇が期待できます。

そこで、Gemini APIを使って動画の音声から字幕ファイルを作れないか?と思いつき、実際に研究してみました。

高価なPremiere ProなどはAIによる自動文字起こしとSRTファイル生成機能があります。さすが高いだけある。

今回利用するファイル等

動画編集ソフトでテロップを入れるのはなかなか大変ですが、英語やその他の外国語用の字幕ファイルを別に作るには、動画内の音声を文字起こしする必要があり、そこからさらに翻訳が必要です。またこの字幕ファイルはいくつか形式がありますが、Youtube上での字幕切替用の字幕の中に非公式ですがYTT形式という独特の形式もサポートしているようで、DVDなどの字幕や動画ファイル埋め込みで使われるSRT形式とは異なります。

しかも装飾が出来るこのYTT形式で組み込んでおけば、脚色のされた字幕で動きのある字幕が作成でき、動画上での文字テロップを減らすことに繋がります。そこでこれをGemini 1.5 Flashを使って作成するのが今回のミッションです。

Gemini APIはM4A形式に対応しておりそのままアップ出来るのですが、似たような専用のAPIサービスに「Google Speech-to-Text API」が存在するのですが、こちらはM4A形式に未対応で生のWAVファイルでなければなりません。GASは最大で50MBまでしか1度にデータ量を扱えないので、10分程度の動画でもWAVだと100MBを超えます。しかしM4Aならば10MB程度なので、字幕生成をするならGemini APIという選択肢になります。

Google WorkspaceでYoutubeチャンネルを運用するコツ - 後編

事前準備

Gemini APIのAPIキーを取得する

2024年5月15日、Googleが発表した最新のAIモデルであるGemini API。これは、Gemini Advancedのバックグラウンドで動いてるものになりますが、今回はそのAPIを直接利用します(2025年2月現在は、Gemini 2.0 Flashが公開されています)

以下の手順でGeminiのAPIキーを今回は取得してみます。

  1. Googleアカウントにログインした状態にしておく
  2. こちらのウェブサイトにアクセスする
  3. APIキーを作成をクリックする
  4. 1個だけはそのままAPIキーを作成で続行できます。2つ目は既存のGCPプロジェクトを選ぶよう指示が出ます。GCPプロジェクトを指定しなかった場合には新規にGCPプロジェクトが生成されます。
  5. APIキーが発行されるのでコピーする

このAPIキーは無料ですが、流出することの無いように大切に保管する必要があります。このキーは後でGAS側で利用します。

※何故か、2.0 Flashだと音声解析が対応していないのか?うまく動かずなので、1.5 Flashを使っています。

図:APIキーを発行してる画面

スクリプトプロパティに値を格納

前述までに取得しておいたGeminiのAPIキーおよび画像ファイルの出力先フォルダとしてスクリプトプロパティに値をセットします。

  • folderid:出力先フォルダのID
  • geminikey : Gemini APIのAPIキー

図:2つ値をセットしておく

音声の準備

Youtubeにアップする用の動画には動画と音声の2つが含まれており、動画と同じ長さの音声ファイルが入っています。この音声ファイルを取り出して、Geminiにて字幕ファイルを作成することになります。

macOSでの事例になりますが、標準で存在してるQuickTime Playerで簡単にM4A音源だけを抽出することが可能です。

  1. QuickTime PlayerでMP4動画を読み込ませる
  2. メニューからファイル→書き出す→オーディオのみを選択
  3. 保存場所を指定して完了
  4. このファイルをGoogle DriveにアップロードしてファイルIDを控えておく

これでM4Aファイルが生成されます。

BGM無しの音声のみの動画を用意して抽出したものならば、Geminiでの判定精度が上がるかもしれない。

図:オーディオのみに変換で一発

コードと結果

50MB以下の場合

ソースコード

変換するコードは意外とシンプルです。過去にGeminiでGoogleスライドの画像生成などのケースはなかなかのボリュームでしたが、こちらは10分で11MB程度の音源なのでGASのQuota範囲内であり、応答も6分の制限内で余裕で返ってきます

GeminiのAPIキーと出力先フォルダのIDはスクリプトプロパティから拾って作業をしています。最後にoutput.srtという形でSRT形式のファイルが出力されます。

プロンプト内容が肝で今回色々実験しましたが、このプロンプト内容でかなり内容が変わってしまい、苦戦しました。主に苦戦した内容は

  • 9分ちょっとの音源なのに字幕の時間のトータルが1時間にもなるコードが出てきた
  • 逆に短すぎて尺のおかしい字幕ファイルが出てくることもあった
  • 字幕の発言内容が変に改行されたり、やたらと1行の長いものが出力されたり。

ただし、出力結果は音源とぴったりの開始時間と終了時間には頑張っても一致しませんでした。このあたりはまだ進化の途中なのかもしれません。日本語の文字起こし精度はなかなか良いのですが、正確な時間の一致は現時点では厳しい。以下のコード内のプロンプトで可能な限り近づける事はできましたが、次項の変換後の作業で微修正が必要です。

公式サイトでは、generation_configにてaudio_timestampをセットしないと正確じゃないようですが、セットしてみるとエラーになります。generationConfig": {"audio_timestamp": true }としてpayloadに追加しているのですが。。。と思ってみたら、Vertex AIではサポートしてるけれど、Gemini APIではサポートしていないよっていう回答がありました

出力結果

以下はSRTファイル出力内容の一部。一部分おかしな部分はあるものの、概ね動画内の機械音声(Voiceroidを使用しています)の発音を拾えていると思います。今回の音声で言えば75ブロック出力され9:01で収まってる状況なので、今のところ最善の結果。これがピッタリだとGemini一本でここから英語に翻訳まで行けて、専用のソフトが不要になるのですが。

実際のYoutube動画用に海外向け字幕をつける場合はこのSRTを読み込ませて翻訳させるだけなので、こちらは簡単だと思います。そうなるとだいぶ動画作成の負荷が下がるので、海外向けに展開する上での大きな差別化になるかと思います。

50MB以上の場合にチャレンジ

概要

GASが一度に扱えるファイルサイズは50MBというUrlfetchAppのQuotaが存在します。よって前述のコードの場合、ドライブ上のデータを取得してUrlfetchAppで送ろうとした所で、50MB超過したサイズのデータの場合エラーとなってしまいます。

そうなると50MB以下なのでせいぜい40分程度の音声ファイルしかGeminiに送れないことになります(通常のファイルはGemini側も50MBの制限がありますが、音声については無いようです)。

そこで、UploadAppGeminiWithFilesという2つのライブラリを使ってとりあえずチャレンジしてみました。

事前準備

以下の手順でライブラリの追加とサービスの有効化が必要です。

  1. サービスよりDrive APIサービスを有効化する必要があります。
  2. 新しいスクリプトを作って、こちらのコードをコピペして保存します(UploadAppがこれで使えるようになります)
  3. ライブラリより、以下のスクリプトIDを持ってライブラリとして追加を行います。
  4. 追加をクリックする

これで各種ライブラリを使う準備が整いました。

図:サービスとライブラリを追加

ソースコード

前述のライブラリとサービスを持って50MB超過のファイルを指定してアップロードしリクエストを投げてみます。ログ欄に今回のファイルだと4分割されてデータのアップロードが繰り返されています。これはuploadType=resumableという部分で分割してレジュームアップロードを実現出来るようです。

そしてライブラリ側でアップロードが完了したものに対してpromptを投げてSRTファイルを生成してもらっています。

出力結果

確かに分割アップロードは出来ました。サイトによると200MBくらいのファイルならば6分以内に処理が完了できたようです。しかし、実際に問い合わせ結果に対する結果は、途中で切れていました。出力トークン制限にでも引っかかってしまったみたい。失敗してしまいました(SRTのファイルサイズは17KBなんですけれど)。

となると、アップロードは出来るけれども出力トークンがどうしてもボトルネックになるので文字起こしでGeminiを使う場合あまり大きなファイルは使えないようです。

図:SRT抽出が途中で切れていた。

Gemini 2.5 Proを使ってみた

前述のように、Gemini 1.5 Flashの事例だと以下のような問題点がありました。

  • 字幕の音声認識に日本語の揺らぎや関数名・カタカナの認識におかしな点が結構あった。
  • 出力トークンが最大8192トークンであるため、尺の長い動画だと出力が途切れる
  • 何よりも、認識してるタイムスタンプの時間のズレが多く、後述のSRTファイルの編集で膨大な手修正が必要だった。

そこで、2025年3月25日にリリースされたGemini 2.5 Proを使ったらどうなるのか?リファレンスに従ってエンドポイントURLのみを変更して再挑戦してみました。Gemini 2.5 ProのエンドポイントURLは以下の通りです。keyの後ろにAPIキーをつなげます。

Gemini 2.5 Proに変更した結果、以下のような結果を得ることができました。

  • 入力トークンが100万、出力トークンが64000にアップしてるのでSRT出力が途中で途切れなくなりました
  • 日本語の認識能力が格段に向上していて、揺らぎや関数名、カナの認識がバッチリになりました。
  • 問題のタイムスタンプですが非常に正確に認識するようになり、SRTファイルの時間のズレの手修正は不要になりました。

エンドポイントを変えた以外は変えていないのでモデルが変わっただけでここまで大きな変化を得るに至りました。ここから英訳を掛けてあげれば、Youtube動画の多言語展開が容易になります。

図:これでWhisper API使わなくてもイケる

Microsoft365専用関数で変わる世界

動画:日本語で字幕を1つ追加しています。

変換後の作業

これでSRT形式は用意できました。しかしこのままではYoutubeでは使えません(SRT形式のままアップは出来ます)。開始時間と終了時間が一致していないので、編集ソフト上で微修正をしてあげる必要があります。この作業が結構たいへんかもしれません。

よって、2本のアプリを使って編集→YTT形式への変換を行ってみます

SRTファイルの編集

SRTファイルの開始時間・終了時間の調整は実際の動画を見ながらになりますが、専用のフリーの編集ソフトがあります。それがAegisub。日本語対応で扱いやすいので、スライダーを駆使して時間を修正しつつ最終的に時間修正したSRTファイルとして出力します(Windows版もあります)。

Aegisubではただ字幕を表示するだけじゃなく色が変わるであったり動きをつけたりといったことがタグ付けをする事でできたりもするのでただの機械翻訳字幕とは大きな差別化になります。ここでは基本的な使い方のみを掲示します。macOSの場合初回実行がGateKeeperにブロックされますので注意。初回起動はちょっと時間が掛かります。

  1. Aegisubを起動する
  2. メニューのファイル→オープンで開こうとすると開けないので、ドラッグ&ドロップでMP4ファイルを投げ込む
  3. 動画表示倍率が25%なので75%くらいに変更しておく
  4. 前述で生成したSRTファイルを同様にドラッグ&ドロップで投げ込む
  5. 関連ファイルを読み込むか?では「いいえ」をクリックします。
  6. 下の字幕リストにドバッと内容が出てきます。
  7. 対象の字幕データをクリックして、右上のパネルで範囲指定を変更して開始時間と終了時間を調整する
  8. 編集ボタンをクリックするとフォントサイズや色等を変更することが可能です。
  9. 下の字幕文字の欄はShift+Enterで途中改行が可能です。
  10. 字幕の欄が赤字のものは文字数に対して尺が短すぎるであったり、文字数が多すぎるといったケースなので尺の範囲を伸ばしたり、途中分割して別のタイムラインで表示などが可能です。分割は字幕文字欄で右クリック→カーソル位置で分割を実行
  11. 編集し終わったら、のアイコンをクリックして確定します。
  12. これを繰り返して最終的に上部メニューの上書き保存ボタンをクリックするとSRTファイルが更新されます。
  13. 最後にメニューからExport Asをクリック→エクスポート→File TypeをSRT形式として保存します。

このSRT形式を次の行程のコンバータで変換するとYoutubeで適用できるようになります。ただこのアプリ日本語の入力にちょっと問題があったりするので若干そこが癖があって使いにくい面があります。時間調整をGeminiがバッチリやってくれるとこの調整作業が大幅に削減されるので有り難いのですが・・・

変換後の日本語字幕ファイルを再度、Geminiなどで英訳してもらいそのファイルを次項のYTT形式に変換します。日本語と英語とでは文字の尺が違うのでそれを考慮して1ブロックあたり30文字以内にしてるのは、変換後の事を考慮してです(でないと目で追ってる内に字幕が先に尺の関係で消えちゃうなどになりかねないため)。

※他のサイトでASS形式にしてからYTSubConverterで変換しろという話題がでますが、何故か二重で変換されてしまい同じ字幕が同じ時間で出る・・ので自分はSRT形式にしてから変換しています(ただSRT形式だと脚色は消えてしまう)。

※正直、右上画面のスライダーで調整するより聞きながら、時刻の値を直打ちしたほうが楽です。

※ちなみにYoutubeはSRT形式をサポートしているので脚色なしならば、このままアップして適用が可能です。

図:初回起動時にブロックされた

図:字幕を丁寧に時間調整を手動で行う

YTT形式への変換

前述まででASS形式に変換されて、場合によっては翻訳済みであるかと思います。そのSRTファイルをYTT形式に変換するツールYTSubConverterです。

起動すると初回はGateKeeperにブロックされるので解除し、無事に起動したらSRTファイルをドラッグアンドドロップで投げ入れて、そのまま変換をクリックするだけ。

YTT形式は中身はXMLそのもので、いろいろなタグで脚色や動きを実現しているようです。

※ASSファイルだと脚色が生かされるのですが、前述のように二重で変換されてYoutube側で二重に字幕が表示されてしまう問題。何か良い方法が無いか?XMLなので該当の重複したものをVSCodeなどで編集して削除すればそれでオッケーなのですが。

図:コンバータでYTT形式で変換

Youtube動画への適用

完成したYTT形式の字幕ファイルを次にYoutube動画に適用します。SRT形式のままでも適用可能です。

  1. Youtube Studioを開く
  2. コンテンツで適用する対象の動画を見つけて開く
  3. 左サイドバーの「字幕」をクリックする
  4. 言語を追加をクリック
  5. 例えば英語を追加します。
  6. 英語のフィールドの字幕あたりにカーソルを持っていくと鉛筆マークが出るのでクリックする
  7. ファイルをアップロードをクリックする
  8. タイムコードありのまま続行をクリックする
  9. YTT形式のファイルを選択する
  10. 最後に公開をクリックすると英語字幕が選べるようになります。

Youtube Studio上でもこの字幕の時間は調整が可能です。

図:字幕ファイル追加画面

図:字幕ファイルを取り込んだ様子

字幕を入れてる事例

にじさんじ - Virtual to LIVE [Official Music Video]

図:虹色の字幕が各言語毎に用意されて動いてる様子

その他の方法

OpenAIのWhisper APIを使う

OpenAIの音声処理用の生成AIであるWhisper APIをGASから使って同様に処理をしてみました。ファイルサイズ上限が25MBまでと低いのですが、出力トークンはGeminiの2倍なので、今回と同じファイルを読み込ませてみましたが

  • ダイレクトにSRTファイルを生成してくれます
  • 10分の内容でしたが途中で途切れることなく最後まで出力することが出来ました
  • タイムスタンプがほぼ完璧でした。きっちり発言時間が記録出来ています。

ということで、現時点ではWhisper APIを使うのが正解といった感じです。続けて英訳まで生成AIで実現できれば、言うこと無し。こちらは以下のように別エントリーで作成方法をまとめました。

図:こちらはほぼ完璧に字幕が作れた

Google Apps ScriptでWhisper APIを使い字幕を作成する【GAS】

Google AI Studioでも作れるらしい

Gemini APIを使った手法でのSRTファイル作成は今現在は前述の通り、時間と内容がズレすぎていてちょっとそのままでは使い物にならない。しかし、X上で「Google AI Studio上ならば簡単に作れるよ」という情報があり、試してみることにしました(同様に概要欄のタイムスタンプも生成できるようだ)。

実際に、以下の手順でGoogle AI Studioに問い合わせをしてみました。

  1. Google AI Studioを開いてみる
  2. 対象の動画のYoutubeのURLをコピーしておく
  3. プロンプト欄に2.のURLを貼り付けて、「この動画のSRTファイルを作成して」と入力してRUNを実行する
  4. すると動画解析が始まり、返答にSRTの形式で返ってくる
  5. 返答内容をテキストエディタにコピペしてtranslate.srtとして保存する

但し、1度の出力トークンが8192トークンに限られているので長尺の動画だとSRT出力は難しい。続けてたとえば、「35の続きを出して」と問い合わせれば続きのSRTを出力することは可能です。但し3.のプロンプトだと1ブロック毎に空行が入っていないのでNG。よって、プロンプトにきちんと1ブロック毎に空行を入れてと追加が必要です(でないと巨大な1個の字幕が表示されてしまいます)

18分の動画で31万Tokenを消費するというなかなかのボリュームですが、果たして時間は正確なのか?

冒頭出力結果は以下の通り

確かに日本語の文字起こしは完璧に出来てると言えます。問題は時間。やはり正確じゃありません。期待したのですが、00:01:21,630から始まっていますが、もちろん0:00:00から始まっています。というか最初の1個目が1分21秒630からってオカシイ・・・故に前述のGemini APIの事例同様にまだまだですね・・・・

図:AI Studioに簡単に問い合わせしてみた

図:途切れても続きの出力も可能です

図:動画にSRTファイルを追加してみた

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)