トランスクリプトを議事録に変換するときの3つの前処理ポイント
文字起こしデータをそのまま議事録に変換しても品質が上がらない理由と、フィラー除去・タイムスタンプ活用・長文分割という3つの前処理ポイントを具体例・コードブロック付きで解説。
会議ツールが出力したトランスクリプトを、そのままAIに貼り付けて議事録を生成しようとしたとき、「思ったより精度が低い」「要約がぼんやりしている」と感じた経験はないだろうか。
原因のほとんどは、変換前の入力データにある。トランスクリプトは「素起こし」状態のデータであり、前処理なしにAIへ渡すと、ノイズに引きずられた精度の低い出力が返ってくる。本記事では、変換品質を左右する3つの前処理ポイントを、具体的な処理例とともに解説する。
トランスクリプトをそのまま議事録にできない理由
トランスクリプト(transcript)とは、会議音声をリアルタイムまたは録音データからテキスト化した一次データであり、発言者名・タイムスタンプ・発言内容がセットで記録されたものだ。詳細な定義と会議ツール別の取得方法についてはトランスクリプトとは?会議ツール別の取得方法と活用法を参照されたい。
この一次データには、議事録として不要な情報が多量に含まれている。主なものは以下の3種類だ。
| ノイズの種類 | 具体例 | 議事録への影響 |
|---|---|---|
| フィラー語 | 「えー」「あのー」「そのー」「えっと」 | AI要約が冗長になる。トークンを無駄に消費する |
| クロストーク・相槌 | 「はい」「なるほど」「そうですね」の連続 | 発言者の特定が困難になる。重要発言が埋もれる |
| 誤認識テキスト | 「KPI」→「ケーピーアイ」「田中」→「たなか」 | 固有名詞・数値の誤りが議事録に引き継がれる |
日本語のビジネス会議を対象にした調査では、1時間の会議トランスクリプトにおいてフィラー語が全発言量の**10〜20%**を占めるケースが報告されている。100,000文字のトランスクリプトであれば、最大2万文字がフィラー語だ。これをそのままAIに渡せば、出力の精度が下がるだけでなく、LLMのコンテキスト上限に達しやすくなるという実務上の問題も生じる。
前処理とは、この「素起こし状態」のデータをAI変換に適した状態に整える工程だ。以下では、実務で特に効果の高い3つの処理を順に解説する。
前処理①:フィラー語(えー・あの・そのー)の扱い
フィラー語とは何か
フィラー語(filler words)とは、発話の間を埋める意味を持たない音声表現のことだ。日本語のビジネス会議では次のような表現が代表的なフィラー語に該当する。
- 間投詞系:えー、えっと、あの、あのー、そのー、なんか、まあ
- 繰り返し系:「〜というか、〜というか」「〜ということで、〜ということで」
- 相槌系:はい、ええ、そうですね(単独で発話された場合)
- 文末の冗長語:「〜という形で」「〜みたいな感じで」「〜かなと思います」
これらは会話の流暢さを保つために自然に発せられる語であり、トランスクリプトには忠実に記録されるが、議事録としての情報価値はほぼゼロだ。
フィラー語がAI変換に与える影響
LLMはテキスト中の全トークンを処理して出力を生成する。フィラー語が多いトランスクリプトをそのまま渡した場合、以下の問題が発生しやすい。
- 要約が冗長になる:「えー、そのー、来期の予算についてなんですが、あのー、各部署から上がってきた要求を」という発言が、フィラー込みで要約に反映される
- 重要語の重みが下がる:キーワードの周囲をフィラーが囲むことで、AIが重要度を正確に評価しにくくなる
- コンテキスト上限を圧迫する:1時間の会議で2〜3万文字に上ることがあるトランスクリプトは、フィラーを除去するだけで10〜20%削減できる
前処理の実装例
最もシンプルな前処理は、正規表現によるフィラー語の一括置換だ。以下はPythonでの実装例だ。
import re
def remove_fillers(text: str) -> str:
"""
日本語トランスクリプトからフィラー語を除去する
"""
# 間投詞系フィラー(単独で出現するケース)
filler_patterns = [
r'えー+[、。\s]',
r'えっと[、。\s]',
r'あの+[、。\s]',
r'そのー+[、。\s]',
r'なんか[、。\s]',
r'まあ[、。\s]',
r'うーん[、。\s]',
]
# 文末の冗長表現
verbose_endings = [
r'という形で(す|した|ます)',
r'みたいな感じで(す|した|ます)',
r'かなと思(います|いました)',
r'ということで(す|した|ます|ございます)',
]
for pattern in filler_patterns + verbose_endings:
text = re.sub(pattern, '', text)
# 連続する句読点・空白を整理
text = re.sub(r'[、]{2,}', '、', text)
text = re.sub(r'\s{2,}', ' ', text)
return text.strip()
# 使用例
sample = "えー、来期の予算についてなんですが、あのー、各部署からの要求額を確認していきたいという形です。"
print(remove_fillers(sample))
# 出力:「来期の予算についてなんですが、各部署からの要求額を確認していきたい。」
ツールを使ったフィラー除去
コードを書かずに処理する場合は、以下の方法が現実的だ。
方法1:テキストエディタの一括置換
VS Code・サクラエディタ・秀丸エディタの正規表現検索(Ctrl+H)で、フィラー語のリストを一括置換する。少量のトランスクリプトであれば、10分以内に処理できる。
方法2:AIへのプロンプト指示
前処理をAI自身に委ねる方法もある。議事録生成の前段として、以下のようなプロンプトを使う。
以下のトランスクリプトを前処理してください。
処理内容:
1. フィラー語(えー、あのー、えっと、そのー、なんか、まあ)を除去する
2. 相槌のみの発言(「はい」「そうですね」「なるほど」単独)を削除する
3. 文末の冗長表現(「という形で」「みたいな感じで」「かなと思います」)を簡潔にする
4. 重複する発言の繰り返しを1回にまとめる
前処理後のテキストのみを出力してください。説明は不要です。
---
[トランスクリプトをここに貼り付け]
この前処理ステップを経てから議事録生成に進むことで、出力の具体性と精度が明確に向上する。
注意点:完全自動除去の落とし穴
フィラー除去は慎重に行う必要もある。「まあ」「なんか」といった語が感情的なニュアンスや消極的な同意を示す文脈(「まあ、それでもいいですが…」)では、除去すると発言の意図が変わることがある。完全自動除去よりも、「議事録化のための軽量化」を目的とした部分的な除去を推奨する。
前処理②:タイムスタンプ・発話者情報の活用
タイムスタンプが持つ情報価値
会議ツールが出力するトランスクリプトには、通常タイムスタンプと発話者名が付与されている。Teams の .docx 形式では次のような構造だ。
[00:01:23] 田中(営業部)
来期のターゲット顧客についてですが、中堅製造業を優先したいと考えています。
[00:01:45] 鈴木(マーケティング)
それは以前の方針から変わるということですか?
[00:01:52] 田中(営業部)
そうです。前回のQ3レビューで出た課題を踏まえた変更です。
このタイムスタンプと発話者情報は、前処理段階では「削除対象」ではなく「活用対象」だ。
タイムスタンプの前処理:構造化への変換
生のトランスクリプトをAIに渡す前に、タイムスタンプを活用して発言を「議題ブロック」に整理すると、AI出力の構造精度が上がる。
変換前(生のトランスクリプト):
[00:00:03] 山田(司会): 本日の議題は3点あります。まず来期予算、次に採用計画、最後に新製品ロードマップです。
[00:00:18] 田中: はい。
[00:00:20] 山田(司会): では予算から始めます。田中さん、現状共有をお願いします。
[00:00:28] 田中: えー、来期予算についてですが、あのー現在の要求総額は...
変換後(議題ブロック付き):
## 議題1:来期予算(00:00:20〜)
田中(財務): 来期予算の要求総額は前期比15%増の1.2億円。主な増加要因はシステム投資(+800万円)と採用費(+600万円)。
...
タイムスタンプを使って議題ブロックを手動で作る場合、以下の手順が有効だ。
- 議題の切り替わりが起きているタイムスタンプを確認する(司会者の「では次に」「続いて」などの発言が目印)
- そのタイムスタンプ以降の発言をまとめてブロック化する
- ブロックごとにAI変換を実行する(後述の分割処理と組み合わせる)
発話者情報の前処理:名前の正規化
会議ツールによっては、同一人物が「田中」「田中 花子」「TANAKA」「田中さん」と異なる表記で記録される場合がある。これを放置すると、AIが同一人物の発言を別人として処理し、アクションアイテムの担当者割り当てが不正確になる。
def normalize_speakers(text: str, speaker_map: dict) -> str:
"""
発話者名を正規化する
speaker_map例: {"田中 花子": "田中", "TANAKA": "田中", "田中さん": "田中"}
"""
for raw_name, normalized_name in speaker_map.items():
text = text.replace(raw_name, normalized_name)
return text
# 使用例
speaker_map = {
"田中 花子": "田中(営業)",
"TANAKA": "田中(営業)",
"田中さん": "田中(営業)",
"鈴木 一郎": "鈴木(マーケ)",
"Suzuki": "鈴木(マーケ)",
}
normalized = normalize_speakers(raw_transcript, speaker_map)
発話者名の正規化は、5〜10分の手作業でも対応できる。議事録に記載するアクションアイテムの担当者が正確になるだけで、会議後のフォローアップの質が大きく改善する。
タイムスタンプの削除が適切なケース
一方、長文の要約や「会議全体のサマリー」を生成する場合は、タイムスタンプをあえて削除した方が出力が自然になることがある。タイムスタンプはAIのコンテキストも消費するため、不要な場合は除去して構わない。
import re
def strip_timestamps(text: str) -> str:
"""
タイムスタンプを除去する(発話者名は維持)
対象形式: [00:01:23] または (00:01:23)
"""
text = re.sub(r'\[\d{2}:\d{2}:\d{2}\]\s*', '', text)
text = re.sub(r'\(\d{2}:\d{2}:\d{2}\)\s*', '', text)
return text
タイムスタンプの扱いは「削除か活用か」の二択ではなく、生成したい出力の種類によって選択する、というのが前処理設計の考え方だ。
前処理③:長時間トランスクリプトの分割処理
長文トランスクリプトが引き起こす問題
1時間の会議トランスクリプトは、日本語で50,000〜100,000文字に達することがある。これをそのままLLMに渡すと、以下の問題が生じる。
- コンテキスト上限を超える:GPT-4oのコンテキスト上限は128kトークン(日本語で概ね9〜10万文字相当)。議事録生成に必要な出力トークンを確保するには、入力を余裕を持って収める必要がある
- 後半の情報が軽視される:LLMは入力テキストの冒頭部分に比べて末尾部分の情報を相対的に軽視する傾向がある(「lost in the middle」問題)
- 出力品質が均一にならない:1時間分を一括処理すると、前半の議題は詳細に、後半の議題は簡略に要約されるという非対称な出力になりやすい
推奨する分割方法
方法1:議題単位での分割(推奨)
最も精度が高い分割方法は、議題の切り替わりを境界として分割する方法だ。前述のタイムスタンプを活用した議題ブロック化と組み合わせると効果的だ。
会議全体のトランスクリプト
↓ 議題ブロックに分割
┌──────────────────────┐
│ ブロック1:来期予算(00:00〜00:18) │ → AI変換 → 議事録セクション1
├──────────────────────┤
│ ブロック2:採用計画(00:18〜00:35) │ → AI変換 → 議事録セクション2
├──────────────────────┤
│ ブロック3:製品ロードマップ(00:35〜00:58)│ → AI変換 → 議事録セクション3
└──────────────────────┘
↓ セクションを統合
完成した議事録
方法2:時間単位での分割(議題が不明瞭な場合)
会議の議題構造が事前にわからない場合は、15〜20分単位でトランスクリプトを機械的に分割する方法を使う。ただし、発言の途中で切れないように、段落(改行2つ)を境界とすることが重要だ。
def split_transcript_by_time(
transcript_lines: list[dict],
chunk_minutes: int = 20
) -> list[list[dict]]:
"""
タイムスタンプを基準にトランスクリプトを分割する
transcript_lines: [{"timestamp": "00:01:23", "speaker": "田中", "text": "..."}, ...]
"""
chunks = []
current_chunk = []
chunk_start_seconds = 0
chunk_size_seconds = chunk_minutes * 60
for line in transcript_lines:
# タイムスタンプを秒に変換
h, m, s = map(int, line["timestamp"].split(":"))
current_seconds = h * 3600 + m * 60 + s
# チャンクの境界を超えたら新しいチャンクを開始
if current_seconds >= chunk_start_seconds + chunk_size_seconds:
if current_chunk:
chunks.append(current_chunk)
current_chunk = [line]
chunk_start_seconds = current_seconds
else:
current_chunk.append(line)
if current_chunk:
chunks.append(current_chunk)
return chunks
方法3:発話者の発言量による重み付け分割
長い会議で特定の参加者の発言量が突出している場合、その参加者の発言が複数チャンクに分断されることがある。発言単位を最小分割単位とすることで、この問題を回避できる。
def split_by_speaker_turns(
transcript: str,
max_chars: int = 15000
) -> list[str]:
"""
発話者交代を境界として最大文字数以内でチャンク化する
"""
# 発話者行のパターン(例:[00:01:23] 田中(営業):)
speaker_pattern = re.compile(r'(\[\d{2}:\d{2}:\d{2}\]\s*\S+[::])')
turns = speaker_pattern.split(transcript)
chunks = []
current_chunk = ""
for i in range(0, len(turns), 2):
header = turns[i] if i < len(turns) else ""
body = turns[i + 1] if i + 1 < len(turns) else ""
turn = header + body
if len(current_chunk) + len(turn) > max_chars and current_chunk:
chunks.append(current_chunk.strip())
current_chunk = turn
else:
current_chunk += turn
if current_chunk:
chunks.append(current_chunk.strip())
return chunks
分割後の統合処理
チャンクごとに生成した議事録セクションを統合する際には、以下のプロンプトを使うと重複や矛盾を整理できる。
以下は1回の会議の議事録を複数のセクションに分けて生成したものです。
これらを1つの議事録に統合してください。
統合のルール:
1. 決定事項・アクションアイテムは重複を排除してリスト化する
2. 各議題の要約は簡潔にまとめる(1議題につき3〜5文)
3. 全体の会議概要を冒頭に追加する(3文以内)
4. アクションアイテムは担当者・期日・内容の形式で統一する
---
[セクション1の議事録]
...
[セクション2の議事録]
...
📝 Minutoを無料で試す
前処理済みのトランスクリプトを貼り付けるだけで、AIが議事録を30秒で仕上げます。 フィラー除去・長文分割もツール内で自動対応。Freeプランは月5回まで無料。クレジットカード不要。
👉 今すぐ試す
AI変換での自動前処理の仕組み
ここまで手動・コードによる前処理を解説してきたが、Minutoのような専用AIツールでは、これらの前処理が自動で実行される。仕組みを簡単に説明する。
入力時の自動クリーニング
Minutoにトランスクリプトを貼り付けると、バックエンドで以下の処理が自動的に行われる。
- フィラー語の統計的検出と除去:日本語フィラーのパターンデータベースを用いて、議事録生成に不要な語を除去する
- 発話者名の正規化:同一会議内で表記が揺れている発話者名をクラスタリングし、統一する
- タイムスタンプの構造化:タイムスタンプを議題ブロックの境界検出に活用し、議事録の章立てに反映させる
長文トランスクリプトの自動チャンキング
コンテキスト長を超えるトランスクリプトが入力された場合、自動で議題単位のチャンキングが行われ、各チャンクを独立処理した後に統合する。ユーザーは分割処理を意識する必要がない。
前処理の透明性
手動前処理と比較したときの自動前処理の弱点は「ブラックボックス化」だ。処理の内容が見えないため、前処理によって重要な発言が誤って除去されても気づきにくい。
このリスクに対応するため、Minutoでは生成後の確認ステップで元のトランスクリプトとの突き合わせ機能を提供している。自動前処理の利便性と、出力の検証可能性を両立させる設計だ。
汎用AIツールとの比較
ChatGPTやClaudeなど汎用AIに直接トランスクリプトを貼り付ける場合、前処理は手動で行う必要がある。専用ツールとの使い分けの目安は以下の通りだ。
| ケース | 推奨 |
|---|---|
| 月に数回・フォーマットは毎回変える | 汎用AI(プロンプト調整) |
| 週3回以上・フォーマットは固定 | 専用ツール(Minuto) |
| 機密情報を含む会議 | 社内LLMまたはセキュリティ基準を確認した専用ツール |
| 長時間会議(1時間超)が多い | 自動チャンキング対応の専用ツール |
Teams・Zoom連携を活用した具体的な議事録自動化の手順については、Teamsの議事録を自動作成する方法およびZoomの議事録を自動化する手順も参照されたい。
まとめ
トランスクリプトを高品質な議事録に変換するためには、AI変換の前に3つの前処理を行う必要がある。
前処理①:フィラー語の除去
- 「えー」「あのー」「えっと」などのフィラー語はトランスクリプト全体の10〜20%を占める
- 正規表現による自動除去、またはAIへの前処理プロンプトで効率的に対応できる
- 意味を持つ「まあ」「なんか」の文脈は慎重に扱う
前処理②:タイムスタンプ・発話者情報の活用
- タイムスタンプを用いて議題ブロックを作成するとAI出力の構造精度が上がる
- 発話者名の正規化により、アクションアイテムの担当者割り当て精度が向上する
- 全体要約が目的の場合はタイムスタンプを除去した方が自然な出力になる
前処理③:長文トランスクリプトの分割処理
- 1時間会議は50,000〜100,000文字に達し、LLMのコンテキスト上限に抵触しうる
- 議題単位、時間単位、発話者交代単位の3つの分割方法を状況に応じて選択する
- 分割後の統合プロンプトを用いて一貫性のある議事録を生成する
これら3つの前処理を習慣化するだけで、AI変換による議事録の精度は大幅に改善する。専用ツールを使えば前処理は自動化できるが、仕組みを理解した上でツールを選ぶことが、長期的な運用の質を左右する。
📝 Minutoを無料で試す
前処理済みのトランスクリプトを貼り付けるだけで、AIが議事録を30秒で仕上げます。 Freeプランは月5回まで無料。クレジットカード不要。
👉 今すぐ試す
よくある質問
Q. フィラー語を除去しすぎると発言の意味が変わることはあるか?
ある。「まあ、その方向で進めましょう」の「まあ」は消極的な同意・留保を示しており、除去すると「積極的な合意」と誤読されうる。自動除去ルールは「単独で文を構成するフィラー」に限定し、意味を持ちうる文脈では手動確認を挟むことを推奨する。
Q. Teams・Zoomのトランスクリプトはどちらが前処理しやすいか?
Teamsの.docx形式は発話者・タイムスタンプ・本文が表形式で整理されており、Pythonのpython-docxライブラリで構造データとして直接取得できるため、プログラム処理との親和性が高い。Zoomの.vtt形式はWebVTT規格に準拠したテキストファイルであり、正規表現で容易にパース可能だ。どちらも前処理のしやすさに大きな差はなく、利用している会議ツールの形式をそのまま使えばよい。
Q. 前処理にはどの程度の時間がかかるか?
手動の場合、1時間の会議トランスクリプトに対してフィラー除去・発話者正規化・議題ブロック化を行うと15〜30分程度かかる。コードスクリプトを整備済みであれば5分以内に短縮できる。Minutoなどの専用ツールを使えば自動処理されるため、前処理の所要時間はほぼゼロになる。
Q. 前処理をせずにAI変換した議事録と、前処理後の議事録では品質にどれほど差が出るか?
定量的な差はトランスクリプトの質と会議の性質によって変わるが、実務的な経験則として「決定事項の抽出精度が15〜25%向上する」「アクションアイテムの担当者誤帰属が大幅に減る」という傾向がある。特に1時間を超える会議や、技術的な専門用語が多い会議では前処理の効果が顕著だ。フィラー語が多い担当者の発言が多い会議ほど、除去前後の差が大きい。
関連サービス
| サービス | 特徴 | リンク |
|---|---|---|
| Minuto | トランスクリプト貼り付け→AI議事録生成、前処理自動対応、月5回無料 | サービスページ |
| WhyTrace | 会議の背景・意思決定の文脈をAIで可視化 | 詳細はこちら |
| AnzenAI | 社内文書のAI活用を安全に運用するガバナンス支援 | 詳細はこちら |
| SysDoc | 業務フロー・システム仕様をAIで自動ドキュメント化 | 詳細はこちら |