Google Apps ScriptでGeminiを叩いて音声から字幕生成【GAS】
2025年2月24日にGoogle Drive上の動画に対する自動字幕機能が公開と聞いてやってみたものの、どうやら対応してるのは英語のみで。日本語の自動字幕は未対応のようです。またYoutubeの動画を海外展開したいとなったら、自動生成ではない字幕を動画に追加して展開することで、アクセス数上昇が期待できます。
そこで、Gemini APIを使って動画の音声から字幕ファイルを作れないか?と思いつき、実際に研究してみました。
※高価なPremiere ProなどはAIによる自動文字起こしとSRTファイル生成機能があります。さすが高いだけある。
目次
今回利用するファイル等
- 音声からSRT生成 with Gemini - Google Spreadsheet
- サンプル音声ファイル
- 出力結果字幕ファイル
- Aegisub
- QuickTime Player
- YTSubConverter
- Youtubeでサポートされる字幕ファイル
動画編集ソフトでテロップを入れるのはなかなか大変ですが、英語やその他の外国語用の字幕ファイルを別に作るには、動画内の音声を文字起こしする必要があり、そこからさらに翻訳が必要です。またこの字幕ファイルはいくつか形式がありますが、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という選択肢になります。
事前準備
Gemini 1.5 FlashのAPIキーを取得する
2024年5月15日、Googleが発表した最新のAIモデルであるGemini 1.5 Flash。これは、Gemini Advancedのバックグラウンドで動いてるものになりますが、今回はそのAPIを直接利用します(2025年2月現在は、Gemini 2.0 Flashが公開されています)
以下の手順でGemini 1.5 FlashのAPIキーを今回は取得してみます。
- Googleアカウントにログインした状態にしておく
- こちらのウェブサイトにアクセスする
- APIキーを作成をクリックする
- 1個だけはそのままAPIキーを作成で続行できます。2つ目は既存のGCPプロジェクトを選ぶよう指示が出ます。GCPプロジェクトを指定しなかった場合には新規にGCPプロジェクトが生成されます。
- 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音源だけを抽出することが可能です。
- QuickTime PlayerでMP4動画を読み込ませる
- メニューからファイル→書き出す→オーディオのみを選択
- 保存場所を指定して完了
- このファイルをGoogle DriveにアップロードしてファイルIDを控えておく
これでM4Aファイルが生成されます。
※BGM無しの音声のみの動画を用意して抽出したものならば、Geminiでの判定精度が上がるかもしれない。
図:オーディオのみに変換で一発
コードと結果
ソースコード
変換するコードは意外とシンプルです。過去にGeminiでGoogleスライドの画像生成などのケースはなかなかのボリュームでしたが、こちらは10分で11MB程度の音源なのでGASのQuota範囲内であり、応答も6分の制限内で余裕で返ってきます。
GeminiのAPIキーと出力先フォルダのIDはスクリプトプロパティから拾って作業をしています。最後にoutput.srtという形でSRT形式のファイルが出力されます。
プロンプト内容が肝で今回色々実験しましたが、このプロンプト内容でかなり内容が変わってしまい、苦戦しました。主に苦戦した内容は
- 9分ちょっとの音源なのに字幕の時間のトータルが1時間にもなるコードが出てきた
- 逆に短すぎて尺のおかしい字幕ファイルが出てくることもあった
- 字幕の発言内容が変に改行されたり、やたらと1行の長いものが出力されたり。
ただし、出力結果は音源とぴったりの開始時間と終了時間には頑張っても一致しませんでした。このあたりはまだ進化の途中なのかもしれません。日本語の文字起こし精度はなかなか良いのですが、正確な時間の一致は現時点では厳しい。以下のコード内のプロンプトで可能な限り近づける事はできましたが、次項の変換後の作業で微修正が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
function generateSRTFromM4A() { //音声ファイル var fileId = "ここにm4aファイルのIDを入れる" //APIキーと出力先を取得する let prop = PropertiesService.getScriptProperties(); let apiKey = prop.getProperty("geminikey"); let targetdir = prop.getProperty("folderid"); //出力先を取得する let target = DriveApp.getFolderById(targetdir); //Google DriveからM4Aファイルを取得 const file = DriveApp.getFileById(fileId); const blob = file.getBlob(); const base64Audio = Utilities.base64Encode(blob.getBytes()); //Gemini API にリクエスト const transcript = transcribeAudio(base64Audio, apiKey); console.log(transcript) if (!transcript) { console.log("音声認識に失敗しました"); return; } //SRTファイルをGoogle Driveに保存 const srtFile = target.createFile('output.srt', transcript, MimeType.PLAIN_TEXT); } // 音声認識(Gemini API 1.5 Flash) function transcribeAudio(audioBase64, apiKey) { //プロンプトを記述する let prompt = `アップロードされた音声ファイルを文字起こしし、SRT形式の字幕ファイルを作成してください。 音声ファイルの言語: 日本語 話者: A, B (対話形式) 音声ファイルの形式: m4a SRT形式のフォーマットは以下の通りです。 1 00:00:00,000 --> 00:00:02,500 (発言内容) 2 00:00:02,500 --> 00:00:05,000 (発言内容) ... タイムレコードはミリ秒単位で正確に出力してください。 1つの発言内容の文字数は可能な限り30文字以内にしてください。また発言内容の中身は改行しないでください。 文字起こし内容は一度文章校正してから出力してください。 ` //リクエストエンドポイントの構築 const url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=' + apiKey; //リクエストのpayloadを構築 const payload = { contents: [{ role: "user", parts: [{ inlineData: { mimeType: "audio/m4a", data: audioBase64 } }] }], "systemInstruction": { "parts": [ { "text": prompt } ] }, }; //リクエストオプションを指定 const options = { method: 'post', contentType: 'application/json', payload: JSON.stringify(payload) }; //Geminiにリクエストと解答を取得 const response = UrlFetchApp.fetch(url, options); const json = JSON.parse(response.getContentText()); //結果を返す return json.candidates && json.candidates[0] ? json.candidates[0].content.parts[0].text : null; } |
出力結果
以下はSRTファイル出力内容の一部。一部分おかしな部分はあるものの、概ね動画内の機械音声(Voiceroidを使用しています)の発音を拾えていると思います。今回の音声で言えば75ブロック出力され9:01で収まってる状況なので、今のところ最善の結果。これがピッタリだとGemini一本でここから英語に翻訳まで行けて、専用のソフトが不要になるのですが。
実際のYoutube動画用に海外向け字幕をつける場合はこのSRTを読み込ませて翻訳させるだけなので、こちらは簡単だと思います。そうなるとだいぶ動画作成の負荷が下がるので、海外向けに展開する上での大きな差別化になるかと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
1 00:00:00,000 --> 00:00:05,000 Microsoft365で利用できるExcelは、一般的なExcelと違い、特別な関数を活用できます。 2 00:00:05,000 --> 00:00:11,000 Googleスプレッドシートで先行装備されていた関数が主になりますが、これまで苦労していた作業が、これらの新関数ののおかげで一気に解決します。 3 00:00:11,000 --> 00:00:16,667 今回は、これら新関数を活用するとどうなるかまとめてみました。 4 00:00:16,667 --> 00:00:20,000 併せて、Spillについても取り上げています。 5 00:00:22,500 --> 00:00:25,333 チャプター1 Spill 6 00:00:25,333 --> 00:00:32,000 Spillとは、これまでのExcelではできなかった数式や関数で、一度に複数の結果を返す配列数式と呼ばれていた機能の拡張機能です。 |
変換後の作業
これでSRT形式は用意できました。しかしYoutubeではSRT形式は使えません。開始時間と終了時間が一致していないので、編集ソフト上で微修正をしてあげる必要があります。この作業が結構たいへんかもしれません。
よって、2本のアプリを使って編集→YTT形式への変換が必要です。
SRTファイルの編集
SRTファイルの開始時間・終了時間の調整は実際の動画を見ながらになりますが、専用のフリーの編集ソフトがあります。それがAegisub。日本語対応で扱いやすいので、スライダーを駆使して時間を修正しつつ最終的に時間修正したSRTファイルとして出力します(Windows版もあります)。
Aegisubではただ字幕を表示するだけじゃなく色が変わるであったり動きをつけたりといったことがタグ付けをする事でできたりもするのでただの機械翻訳字幕とは大きな差別化になります。ここでは基本的な使い方のみを掲示します。macOSの場合初回実行がGateKeeperにブロックされますので注意。初回起動はちょっと時間が掛かります。
- Aegisubを起動する
- メニューのファイル→オープンで開こうとすると開けないので、ドラッグ&ドロップでMP4ファイルを投げ込む
- 動画表示倍率が25%なので75%くらいに変更しておく
- 前述で生成したSRTファイルを同様にドラッグ&ドロップで投げ込む。
- 関連ファイルを読み込むか?では「いいえ」をクリックします。
- 下の字幕リストにドバッと内容が出てきます。
- 対象の字幕データをクリックして、右上のパネルで範囲指定を変更して開始時間と終了時間を調整する
- 編集ボタンをクリックするとフォントサイズや色等を変更することが可能です。
- 下の字幕文字の欄はShift+Enterで途中改行が可能です。
- 字幕の欄が赤字のものは文字数に対して尺が短すぎるであったり、文字数が多すぎるといったケースなので尺の範囲を伸ばしたり、途中分割して別のタイムラインで表示などが可能です。分割は字幕文字欄で右クリック→カーソル位置で分割を実行。
- 編集し終わったら、✔のアイコンをクリックして確定します。
- これを繰り返して最終的に上部メニューの上書き保存ボタンをクリックするとSRTファイルが更新されます。
- 最後にメニューから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形式のままでも適用可能です。
- Youtube Studioを開く
- コンテンツで適用する対象の動画を見つけて開く
- 左サイドバーの「字幕」をクリックする
- 言語を追加をクリック
- 例えば英語を追加します。
- 英語のフィールドの字幕あたりにカーソルを持っていくと鉛筆マークが出るのでクリックする
- ファイルをアップロードをクリックする
- タイムコードありのまま続行をクリックする
- YTT形式のファイルを選択する
- 最後に公開をクリックすると英語字幕が選べるようになります。
Youtube Studio上でもこの字幕の時間は調整が可能です。
図:字幕ファイル追加画面
図:字幕ファイルを取り込んだ様子
字幕を入れてる事例
図:虹色の字幕が各言語毎に用意されて動いてる様子
関連リンク
- 動画・映像を文字起こしするには?おすすめサービスから字幕作成方法まで徹底解説
- OpenAI Whisper:無料で音声をテキスト化する方法 (SRT/VTTを使用)
- Gemini API を使用した音声機能の詳細
- 長尺講座動画を編集するときのAI活用法【chatGPT+CLOVA Note】
- Gemini & Google Apps Script & Google Driveで音声ファイルを解析する
- WebVTT と SRT の字幕を生成する - Speech-to-Text V2 API
- Apps script and Google Text to Speech API
- Macで動画ファイルmovから音声ファイルm4aに変換する方法
- Gemini 1.5 Pro で音声ファイルの文字起こしを行う
- AIで音声ファイルから歌詞のSRTファイルを生成する
- Use case for multimodal Gemini 2.0: Upload a video and ask it to write subtitles for it in a .srt file format
- SRTファイルとは?SRTファイルを作成する方法も紹介
- Aegisub & YTSubConverterで作るYouTube用字幕作成のコツ - 1. 作成編
- 動画に字幕を付けたり、ズレてる字幕を修正したりするのに便利な「Subtitle Edit」「Subtitle Workshop」
- Google Gemini APIにリポジトリのソースコードごと送って質問する
- 字幕翻訳に挑戦!AegiSubと仲良くなろう編
- AppSheet と Gemini で録音状態の悪い音声ファイルから自然な文字起こしをするアプリ