取り組みの背景 — Gemini API で音声を「読む」時代へ
音声データの活用は、ビジネスでもクリエイティブの現場でも大きなテーマになっています。会議の録音、インタビュー、ポッドキャストなど、音声として記録された情報をテキスト化し、さらに要約まで自動化できたら、どれほど生産性が上がるでしょうか。
Gemini API はテキストだけでなく、画像・動画・音声といったマルチモーダル入力に対応しています。つまり、音声ファイルを直接 Gemini に渡して「この音声の内容を文字起こしして」「要点をまとめて」と指示することが可能です。従来の音声認識サービスとは異なり、Gemini は文脈を深く理解したうえで自然な文章として出力してくれるため、単なる文字起こしを超えた「知的な要約」を実現できます。
ここではPython と Gemini API を使って音声ファイルの文字起こしと自動要約を行うアプリをゼロから構築する方法を、実際に動作するコード付きで解説します。
前提条件と環境準備
必要なもの
- Python 3.10 以上
- Google AI Studio で取得した Gemini API キー(Gemini API クイックスタート を参照)
- 文字起こししたい音声ファイル(MP3, WAV, M4A, OGG など)
ライブラリのインストール
pip install google-genaigoogle-genai は Google が提供する公式の Python SDK で、Gemini API へのアクセスを簡潔に記述できます。
API キーの設定
セキュリティのため、API キーは環境変数として設定します。
export GEMINI_API_KEY="YOUR_API_KEY"Gemini の音声理解の仕組み
Gemini はマルチモーダルモデルとして設計されており、音声データをネイティブに処理できます。具体的には、以下のような流れで音声を理解します。
- 音声の直接入力: 音声ファイルをバイナリデータとしてAPIに送信
- コンテキスト理解: 話者の意図、トピックの切り替え、強調ポイントを認識
- 自然言語生成: 認識結果を自然な文章として整形して出力
対応している音声形式は MP3、WAV、AIFF、AAC、OGG、FLAC など幅広く、最大で約 9.5 時間(Gemini 3.1 Pro の場合)の音声を一度に処理できます。
音声のマルチモーダル処理について、より幅広い活用法を知りたい方は Gemini API 音声理解ガイド もあわせてご覧ください。
ステップ 1 — 基本的な音声文字起こし
まずは最もシンプルな形で、音声ファイルを Gemini に渡して文字起こしを行うコードを書いてみましょう。
import os
from google import genai
# クライアントの初期化
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
# 音声ファイルのアップロード
audio_file = client.files.upload(file="meeting_recording.mp3")
# 文字起こしリクエスト
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[
audio_file,
"この音声ファイルの内容を正確に文字起こししてください。"
"話者が複数いる場合は、話者を区別して記載してください。"
],
)
print(response.text)期待される出力例:
話者A: 本日の議題は、新しいプロダクトのローンチスケジュールについてです。
話者B: はい。現在の進捗状況を共有させてください。開発チームは予定通り...
話者A: ありがとうございます。マーケティング側の準備状況はいかがですか?
話者C: LP の制作は完了しており、広告配信の設定も...
このコードのポイントは、client.files.upload() で音声ファイルを Gemini にアップロードし、テキストプロンプトと組み合わせて送信している点です。Gemini は音声の内容を認識し、話者の区別まで行ってくれます。
ステップ 2 — 要約機能の追加
文字起こしだけでなく、内容の要約も同時に行いたい場合は、プロンプトを工夫するだけで対応できます。
import os
import json
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
audio_file = client.files.upload(file="meeting_recording.mp3")
# 構造化された出力を要求するプロンプト
prompt = """
この音声ファイルを分析して、以下の形式でJSON出力してください。
{
"transcript": "全文の文字起こし(話者を区別)",
"summary": "内容の要約(200文字以内)",
"key_points": ["要点1", "要点2", "要点3"],
"action_items": ["アクションアイテム1", "アクションアイテム2"],
"duration_estimate": "推定の音声の長さ"
}
"""
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[audio_file, prompt],
config=types.GenerateContentConfig(
response_mime_type="application/json",
),
)
# JSONとしてパース
result = json.loads(response.text)
print("=== 要約 ===")
print(result["summary"])
print("\n=== 要点 ===")
for point in result["key_points"]:
print(f"・{point}")
print("\n=== アクションアイテム ===")
for item in result["action_items"]:
print(f"☐ {item}")期待される出力例:
=== 要約 ===
新プロダクトのローンチスケジュールについて議論。開発は予定通り進行中で、
マーケティング側のLP・広告も準備完了。4月15日のローンチに向けて最終確認を
実施する方針で合意した。
=== 要点 ===
・開発チームの進捗は予定通り
・LPと広告配信の設定が完了
・4月15日がローンチ目標日
=== アクションアイテム ===
☐ QAチームによる最終テスト(4月1日まで)
☐ プレスリリースの準備(田中さん担当)
☐ カスタマーサポート体制の確認(鈴木さん担当)
response_mime_type="application/json" を指定することで、Gemini に JSON 形式での出力を強制でき、後続の処理でパースしやすくなります。
ステップ 3 — 長時間音声の分割処理
長時間の音声ファイルを効率的に処理するためのテクニックを紹介します。Gemini 3.1 Pro は最大約 9.5 時間の音声に対応していますが、非常に長い音声の場合はレスポンスの精度を高めるために分割して処理する方法も有効です。
import os
import json
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
def transcribe_with_timestamps(file_path: str) -> dict:
"""音声ファイルをタイムスタンプ付きで文字起こしする"""
audio_file = client.files.upload(file=file_path)
prompt = """
この音声を分析し、以下の形式でJSON出力してください。
タイムスタンプは可能な範囲で推定してください。
{
"segments": [
{
"timestamp": "00:00 - 00:30",
"speaker": "話者名または話者A等",
"text": "発言内容"
}
],
"total_speakers": 話者の人数,
"language": "検出された言語",
"topics": ["議題1", "議題2"]
}
"""
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[audio_file, prompt],
config=types.GenerateContentConfig(
response_mime_type="application/json",
),
)
return json.loads(response.text)
def summarize_by_topic(transcript_data: dict) -> str:
"""トピックごとに要約する"""
topics = transcript_data.get("topics", [])
segments_text = "\n".join(
f"[{s['timestamp']}] {s['speaker']}: {s['text']}"
for s in transcript_data["segments"]
)
prompt = f"""
以下は会議の文字起こしです。
検出されたトピック: {', '.join(topics)}
{segments_text}
各トピックごとに要点をまとめ、全体の結論とアクションアイテムを
整理してください。
"""
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[prompt],
)
return response.text
# 実行
result = transcribe_with_timestamps("long_meeting.mp3")
print(f"話者数: {result['total_speakers']}")
print(f"言語: {result['language']}")
print(f"議題: {', '.join(result['topics'])}")
summary = summarize_by_topic(result)
print("\n=== トピック別要約 ===")
print(summary)このアプローチでは、まず音声全体をタイムスタンプ付きで文字起こしし、次にテキストデータを使ってトピック別に要約しています。2段階に分けることで、それぞれの処理で最適なプロンプトを設計できます。
ステップ 4 — 複数ファイルの一括処理
複数の音声ファイルを効率的にバッチ処理する実装です。
import os
import json
import glob
from concurrent.futures import ThreadPoolExecutor, as_completed
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
SUPPORTED_FORMATS = {".mp3", ".wav", ".m4a", ".ogg", ".flac", ".aac"}
def process_single_audio(file_path: str) -> dict:
"""1つの音声ファイルを処理する"""
try:
audio_file = client.files.upload(file=file_path)
prompt = """
この音声を分析し、以下のJSON形式で出力してください。
{
"file": "ファイル名",
"summary": "200文字以内の要約",
"key_points": ["要点1", "要点2", "要点3"],
"language": "検出された言語",
"sentiment": "全体的なトーン(ポジティブ/ニュートラル/ネガティブ)"
}
"""
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[audio_file, prompt],
config=types.GenerateContentConfig(
response_mime_type="application/json",
),
)
result = json.loads(response.text)
result["file"] = os.path.basename(file_path)
result["status"] = "success"
return result
except Exception as e:
return {
"file": os.path.basename(file_path),
"status": "error",
"error": str(e),
}
def batch_process(directory: str, max_workers: int = 3) -> list[dict]:
"""ディレクトリ内の音声ファイルを一括処理する"""
audio_files = [
f for f in glob.glob(os.path.join(directory, "*"))
if os.path.splitext(f)[1].lower() in SUPPORTED_FORMATS
]
print(f"処理対象: {len(audio_files)} ファイル")
results = []
# 並列処理(APIレート制限を考慮して max_workers を制限)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {
executor.submit(process_single_audio, f): f
for f in audio_files
}
for future in as_completed(futures):
result = future.result()
results.append(result)
status = "✅" if result["status"] == "success" else "❌"
print(f" {status} {result['file']}")
return results
# 実行
results = batch_process("./audio_files/")
# レポート出力
success = [r for r in results if r["status"] == "success"]
print(f"\n処理完了: {len(success)}/{len(results)} 成功")
for r in success:
print(f"\n--- {r['file']} ---")
print(f"要約: {r['summary']}")ThreadPoolExecutor を使って並列処理することで、複数ファイルの処理時間を短縮できます。ただし、API のレート制限に配慮して max_workers は控えめに設定しましょう。非同期処理を使ったさらに高度なパターンについては Gemini API × Python 非同期処理ガイド で詳しく解説しています。
ステップ 5 — Markdown レポートの自動生成
文字起こしと要約の結果を Markdown 形式のレポートとして自動出力する仕上げの実装です。
import os
import json
from datetime import datetime
from google import genai
from google.genai import types
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
def generate_meeting_report(file_path: str, output_dir: str = "./reports") -> str:
"""音声ファイルから会議レポートを自動生成する"""
os.makedirs(output_dir, exist_ok=True)
audio_file = client.files.upload(file=file_path)
# 詳細な分析をリクエスト
prompt = """
この音声は会議の録音です。以下の情報をJSON形式で出力してください。
{
"title": "会議のタイトル(内容から推測)",
"date_mentioned": "言及された日付があれば",
"participants_count": 推定参加者数,
"transcript": "全文の文字起こし",
"summary": "300文字以内の要約",
"decisions": ["決定事項1", "決定事項2"],
"action_items": [
{"task": "タスク内容", "assignee": "担当者", "deadline": "期限"}
],
"next_steps": ["次のステップ1", "次のステップ2"]
}
"""
response = client.models.generate_content(
model="gemini-3.1-pro",
contents=[audio_file, prompt],
config=types.GenerateContentConfig(
response_mime_type="application/json",
),
)
data = json.loads(response.text)
# Markdownレポートの生成
now = datetime.now().strftime("%Y-%m-%d %H:%M")
filename = os.path.basename(file_path).rsplit(".", 1)[0]
report = f"""# {data['title']}
**生成日時**: {now}
**元ファイル**: {os.path.basename(file_path)}
**推定参加者数**: {data['participants_count']}名
## 要約
{data['summary']}
## 決定事項
"""
for decision in data.get("decisions", []):
report += f"- {decision}\n"
report += "\n## アクションアイテム\n\n"
report += "| タスク | 担当者 | 期限 |\n|---|---|---|\n"
for item in data.get("action_items", []):
report += f"| {item['task']} | {item['assignee']} | {item['deadline']} |\n"
report += "\n## 次のステップ\n\n"
for step in data.get("next_steps", []):
report += f"1. {step}\n"
report += f"\n## 全文文字起こし\n\n{data['transcript']}\n"
# ファイルに保存
output_path = os.path.join(output_dir, f"{filename}_report.md")
with open(output_path, "w", encoding="utf-8") as f:
f.write(report)
print(f"レポートを保存しました: {output_path}")
return output_path
# 実行
report_path = generate_meeting_report("weekly_standup.m4a")このスクリプトを使えば、会議の録音ファイルを渡すだけで、タイトル、要約、決定事項、アクションアイテムまで整理されたレポートが自動生成されます。
さらに高度なマルチモーダル処理テクニックに興味がある方は、Gemini API マルチモーダル実践テクニック集 で画像・動画・PDFを組み合わせた応用パターンも解説していますので、ぜひご覧ください。
まとめ
ここではGemini API と Python を使って音声ファイルの文字起こし・要約を自動化するアプリの作り方を解説しました。基本的な文字起こしから、構造化された要約の出力、バッチ処理、Markdown レポートの自動生成まで、段階的に実装を進めてきましました。
Gemini のマルチモーダル機能を活用すれば、音声データの処理がこれまでとは比較にならないほど簡単になります。会議の議事録作成、ポッドキャストの要約、インタビューの分析など、様々な場面でこの技術を応用してみてください。