今週、技術カンファレンスの動画を何本「積んで」いますか?あるいは、チャットツールに流れてきた「必読」のPDF資料を、いつか読むつもりで放置していませんか。
私たちエンジニアにとって、新しい情報のキャッチアップは呼吸と同じくらい重要です。しかし、情報の洪水を前にして、まともにすべてを目で追い、耳で聞こうとするのは、もはや「時間の浪費」と言っても過言ではありません。特に、1時間の動画の中に自分が必要とする情報が5分しかない場合、残りの55分は人生の損失です。
世の中にはAI要約ツールが溢れていますが、あえて「既存のSaaSツールには頼るな」と警告します。月額数千円のサブスクリプションを積み重ね、機密性の高い会議音声をブラックボックスなクラウドにアップロードするのは、リスク管理の観点からも、エンジニアのプライドとしても推奨できません。
今回は、GoogleのGeminiモデル APIを活用し、動画・音声・テキストを問わず、あらゆるインプットを自分好みのフォーマットに「蒸留」するパイプラインを自作します。これは単なる要約ツールの作成ではありません。あなたの脳の処理能力を拡張する、エンジニアリングの実践です。まずは動くプロトタイプを作り、仮説を即座に形にして検証していきましょう。
1. なぜ「自作」マルチモーダルパイプラインなのか
「便利なツールがあるのに、なぜわざわざコードを書くのか?」
そう思うかもしれません。しかし、実務の現場から見れば、汎用的なSaaSツールは「帯に短し襷に長し」です。
SaaS課金の壁とセキュリティの懸念を突破する
多くのAI要約サービスは、処理分数やファイルサイズに厳しい制限を設けています。「月間10時間まで」といった制限は、ヘビーな情報収集を行う私たちにはあまりに少なすぎます。また、従量課金ではなく定額制の場合、使わなくてもコストが発生します。経営者視点で見ても、無駄な固定費は避けるべきです。
さらに深刻なのがデータプライバシーです。社外秘の会議音声や、未公開の技術仕様書が含まれるPDFを、利用規約が頻繁に変わるサードパーティのWebサービスにアップロードするのは、セキュリティの観点から非常に危険な行為です。
APIを直接叩いて自作すれば、データフローを完全に制御できます。エンタープライズ基準でデータを管理し、必要な時に必要な分だけ、極めて安価なAPI料金で処理する。これがビジネスと技術の両面から見た最適解です。
Geminiモデルの長大なコンテキストウィンドウが変える世界
今回、Geminiモデルを選択する理由は明確です。それは200万トークンを超える圧倒的なコンテキストウィンドウと、ネイティブなマルチモーダル処理能力です。
従来のLLMでは、長時間の動画や大量のPDFを扱う際、テキストを分割して処理するRAG(検索拡張生成)などの工夫が不可欠でした。もちろん、RAG技術自体も進化を続けていますが、文脈の連続性が重要となる要約タスクにおいては、データを分割することによる情報の欠落が課題となります。
Geminiモデルの最新モデルであれば、1時間の動画ファイルや数百ページのPDFを「そのまま」プロンプトに放り込むことが可能です。これにより、文脈の分断が起きず、全体の流れを踏まえた極めて精度の高い解析が実現します。特に、最新の安定版モデルでは推論能力とコストパフォーマンスが最適化されており、個人開発レベルでもエンタープライズ級のパイプラインを構築できる環境が整っています。
2. 開発環境とAPIの準備
それでは、手を動かしていきましょう。まずは環境構築です。Python 3.10以上を推奨します。
Google AI StudioでのAPIキー取得
まだAPIキーを持っていない場合は、Google AI Studioにアクセスし、APIキーを取得してください。無料枠(Free Tier)でも十分な実験が可能ですが、実運用の際はレートリミットに注意が必要です。
Python環境と必須ライブラリのインストール
プロジェクト用のディレクトリを作成し、仮想環境をセットアップします。
# プロジェクトディレクトリの作成
mkdir my-intel-agent
cd my-intel-agent
# 仮想環境の作成と有効化
python -m venv venv
source venv/bin/activate # Windowsの場合は venv\Scripts\activate
# 必須ライブラリのインストール
pip install google-generativeai youtube-transcript-api python-dotenv
google-generativeai: Gemini APIを扱う公式SDKyoutube-transcript-api: YouTubeの字幕データを取得する軽量ライブラリpython-dotenv: 環境変数を管理するためのライブラリ
プロジェクトルートに .env ファイルを作成し、APIキーを保存します。このファイルは .gitignore に追加し、絶対にGitリポジトリにコミットしないでください。
# .env
GOOGLE_API_KEY=your_api_key_here
3. 実装A:YouTube動画の「超速」要約モジュール
動画コンテンツの消化には2つのアプローチがあります。
- 字幕テキストベース: 処理が爆速。映像は見ない。トークン消費も少ない。
- 動画ファイルベース: 映像内のスライドやデモ画面も解析対象にする。処理は重いが情報量は多い。
ここでは、状況に応じて使い分けられるよう、両方のアプローチを実装します。まずは動くものを作って試すことが重要です。
字幕データ(Transcript)の取得ロジック
まずは、youtube-transcript-api を使って字幕を取得し、テキストとしてGeminiに投げる軽量な実装です。
import os
import google.generativeai as genai
from youtube_transcript_api import YouTubeTranscriptApi
from dotenv import load_dotenv
# 環境設定
load_dotenv()
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
def get_video_id(url):
"""URLから動画IDを抽出する簡易関数"""
if "v=" in url:
return url.split("v=")[1].split("&")[0]
elif "youtu.be/" in url:
return url.split("youtu.be/")[1]
return url
def summarize_youtube_text(video_url):
video_id = get_video_id(video_url)
try:
# 字幕の取得(日本語優先、無ければ英語)
transcript_list = YouTubeTranscriptApi.get_transcript(video_id, languages=['ja', 'en'])
full_text = " ".join([t['text'] for t in transcript_list])
# 字幕が長すぎる場合の簡易カット(必要に応じて調整)
print(f"取得した文字数: {len(full_text)}")
# Geminiモデルの準備
model = genai.GenerativeModel('gemini-1.5-pro')
prompt = f"""
以下のYouTube動画の字幕テキストを読み、エンジニア向けに要約してください。
単なる感想ではなく、技術的なキーワード、ツール名、解決手法に焦点を当てて構造化してください。
出力フォーマット:
- 概要: 3行で
- 主要な技術/ツール: リスト形式
- 重要なポイント:
- アクションアイテム/コード例: あれば記述
--- 字幕テキスト ---
{full_text}
"""
response = model.generate_content(prompt)
return response.text
except Exception as e:
return f"エラーが発生しました: {e}"
# 実行テスト
if __name__ == "__main__":
url = "https://www.youtube.com/watch?v=example" # 任意の技術動画URL
print(summarize_youtube_text(url))
動画そのものをAPIに処理させるマルチモーダルアプローチ
次に、動画ファイルそのもの(mp4など)をGeminiに見せる方法です。これは、スライドに書かれたコードや図表を読み取らせたい場合に威力を発揮します。
※注意: ローカルに動画ファイルがある前提のコードです。
import time
def summarize_video_file(file_path):
print(f"動画ファイル {file_path} をアップロード中...")
# File APIを使って動画をアップロード
video_file = genai.upload_file(path=file_path)
# 処理完了を待機(動画のエンコード処理待ち)
while video_file.state.name == "PROCESSING":
print("処理中...", end=".", flush=True)
time.sleep(5)
video_file = genai.get_file(video_file.name)
if video_file.state.name == "FAILED":
raise ValueError("動画の処理に失敗しました。")
print("\n動画処理完了。解析を開始します。")
model = genai.GenerativeModel('gemini-1.5-pro')
prompt = """
この動画は技術カンファレンスのセッションです。
映像内のスライドやデモ画面の情報を考慮して、詳細なレポートを作成してください。
特に、画面に映っているアーキテクチャ図やコードスニペットの内容を言語化して含めてください。
"""
# 動画ファイルオブジェクトとプロンプトを同時に渡す
response = model.generate_content([video_file, prompt])
# 処理後にファイルを削除する場合(ストレージ節約)
# genai.delete_file(video_file.name)
return response.text
この2つを使い分けることで、「まずは字幕でサクッと概要把握(30秒)」→「重要そうなら動画ファイルを食わせて詳細解析(3分)」という階層的なインプットが可能になります。
4. 実装B:会議音声とPDF資料のクロスリファレンス
エンジニアの業務で最も厄介なのが、「仕様書(PDF)」と「定例会議(音声)」の乖離です。「あの会議で仕様変更の話したよね?」という言った言わない問題を、AIで解決しましょう。
ここでは、会議の録音データ(mp3/wav)と、配布資料(pdf)を同時にGeminiに読み込ませ、クロスリファレンス(相互参照)させます。
長時間の音声ファイルと関連資料を同時に処理する
def analyze_meeting(audio_path, pdf_path):
print("メディアファイルをアップロード中...")
# 音声とPDFをアップロード
audio_file = genai.upload_file(path=audio_path)
pdf_file = genai.upload_file(path=pdf_path)
# 待機処理(簡略化のため関数化推奨)
# ... (前述のwait処理と同様の実装を入れてください)
print("解析開始...")
model = genai.GenerativeModel('gemini-1.5-pro')
prompt = """
あなたは優秀なテクニカルライターです。
添付の「会議音声」と「配布資料(PDF)」を突き合わせて、以下のタスクを行ってください。
1. 議事録の作成: 会議での決定事項をまとめてください。
2. 差分検出: 資料(PDF)に記載されている内容と、口頭での発言に矛盾や変更点があれば指摘してください。
例: 「資料ではAPI v1を使うとあるが、音声ではv2への移行が決定されている」
3. TODOリスト: 誰がいつまでに何をするか抽出してください。
"""
# マルチモーダル入力:プロンプト + 音声 + PDF
response = model.generate_content([prompt, audio_file, pdf_file])
return response.text
このスクリプトの強力な点は、「資料には書いてあるが、会議では触れられなかった重要なリスク」や「会議の場のノリで変更された仕様」を炙り出せることです。これは単一モダリティの処理では不可能です。
5. パイプラインの統合と自動化(CLIツール化)
個別のパーツができたら、実用的なCLIツールとして統合しましょう。これこそがDIYの醍醐味であり、システム思考に基づくエンジニアリングの第一歩です。
入力を自動判別するメイン関数の作成
argparse を使い、URLが渡されたらYouTube処理、ファイルパスなら拡張子を見て処理を分岐させます。また、実運用を見据えてエラーハンドリングを強化します。特にGemini APIなどのクラウドAIサービスを利用する場合、レートリミット(429エラー)や一時的なサーバーエラーへの対策は必須です。
import argparse
import sys
import os
import time
# google.api_core.exceptionsなどのインポートが必要な場合があります
# from google.api_core import exceptions
# ... (これまでの関数定義をここに含めるか、モジュールとしてimport)
def main():
parser = argparse.ArgumentParser(description="My Intel Agent: AI駆動情報収集ツール")
parser.add_argument("input", help="YouTube URL または ファイルパス")
parser.add_argument("--pdf", help="会議音声解析時の補助PDFファイルパス", default=None)
# モデルバージョンを引数で指定可能にするとテストが容易になります
parser.add_argument("--model", help="使用するGeminiモデルバージョン", default="gemini-1.5-pro-latest")
args = parser.parse_args()
target = args.input
result = ""
print(f"Processing: {target} with {args.model}...")
try:
if target.startswith("http"):
# YouTube URLとして処理
result = summarize_youtube_text(target)
elif target.endswith((".mp4", ".mov", ".avi")):
# 動画ファイルとして処理
# 注意: 大きな動画ファイルはアップロードに時間がかかる場合があります
result = summarize_video_file(target)
elif target.endswith((".mp3", ".wav", ".m4a")):
# 音声ファイルとして処理
if args.pdf:
result = analyze_meeting(target, args.pdf)
else:
# PDFなしの音声単体処理ロジック(省略)
# 必要に応じて実装してください
pass
else:
print("未対応のフォーマットです。")
sys.exit(1)
# 結果の出力(標準出力 または ファイル保存)
print("\n=== ANALYSIS RESULT ===\n")
print(result)
# ここにNotion APIやSlack Webhookへの送信処理を追加するとさらに便利です
# 例: send_to_notion(result)
except Exception as e:
# 実運用では、APIのレートリミット(ResourceExhausted)などを個別に捕捉し、
# 指数バックオフ(Exponential Backoff)でリトライするロジックの実装を推奨します。
print(f"Fatal Error: {e}")
# 詳細なログを出力する場合は traceback モジュールを使用してください
sys.exit(1)
if __name__ == "__main__":
main()
使い方
ターミナルから以下のように実行します。
# YouTube動画の要約
python agent.py https://www.youtube.com/watch?v=xxxxx
# 会議音声と資料のクロスチェック(モデルを指定する場合)
python agent.py meeting_audio.mp3 --pdf spec_v1.pdf --model gemini-1.5-pro-002
※ モデル指定について: Gemini APIは頻繁にアップデートされます。安定した出力を得るためには、gemini-1.5-pro-002 のように特定の安定版バージョンを指定することをお勧めします。最新情報は公式ドキュメントのChangelogを確認してください。
これで、手元には、動画・音声・テキストなど、あらゆる入力を瞬時に構造化データへ変換する「万能ナイフ」が備わりました。
まとめ
AI時代のエンジニアにとって、情報収集能力の差は、そのまま生産性と意思決定の質に直結します。
既存のSaaSツールに依存し、データの安全性やコスト、機能制限に悩まされながら情報収集をするのか。それとも、APIを駆使して自らの手で最適なパイプラインを構築し、情報の波を乗りこなすのか。Geminiモデルのようなロングコンテキスト対応モデルの登場により、後者のハードルは劇的に下がりました。
今回作成したスクリプトは、まだ最小限のプロトタイプに過ぎません。ここに出力結果をNotionデータベースに自動登録する機能や、特定キーワードが含まれていた場合のみSlackに通知する機能を追加することで、あなただけの「インテリジェンス・エージェント」へと進化させることができます。
まずは今週末、積読になっているあの技術動画や、長時間の会議録音を、このスクリプトに投げてみてください。AIが処理している間の空いた時間は、次の革新的なコードを書くか、あるいはゆっくりコーヒーを飲む時間に充てましょう。皆さんはどのような機能をこのエージェントに追加してみたいですか?ぜひ手を動かして、自分だけのツールを作り上げてください。
次回は、こうして集めた構造化データを活用し、ローカルLLMで「自分専用のセキュアな検索エンジン」を構築する方法について深掘りしたいと思います。
コメント