ClassLab Engineering の Dev チームメンバーが執筆しました。
コールセンターのQA(品質管理)で、こんな課題を抱えていませんか?
- 通話録音を1件ずつ人が聴いて品質チェックしている
- 全通話の10%しかチェックできず、残り90%はノーチェックで流れている
- チェック基準が属人的で、担当者によって評価が割れる
私たちClassLabは、年間15万件の通話を扱うコールセンターを運営しています。この記事では、通話録音をOpenAIのgpt-4o-transcribeで全件自動文字起こしし、QAレビューを「聴く」から「読む」に変えて工数80%削減した設計と実装を公開します。
1. 背景 — なぜ全件文字起こしが必要だったか
ClassLabはライフライン(電気・ガス)の取次事業を展開しており、コールセンターでは毎日数百件の通話が発生します。品質管理チームが通話録音を聴き、オペレーターの対応品質を評価するのですが、物理的に全件チェックは不可能でした。
ビジネス上の制約
- 通話件数: 約600件/日(年間15万件超)
- QAチーム: 2名
- 1件あたりの平均通話時間: 8分
- 1件のチェックに必要な時間: 通話再生 + 評価記入で約15分
2名 × 8時間 = 16時間/日で、15分/件だと64件/日が限界。600件中64件 = チェック率わずか10%。残りの90%はノーチェックで流れていました。
転機: Zoom Phoneの導入
ClassLabのコールセンターはZoom Phoneを使用しており、通話録音がクラウドに自動保存されます。「録音データがAPIで取得できるなら、全件自動で文字起こしできるのでは?」——これがプロジェクトの出発点でした。
2. 課題 — 文字起こし自動化の4つの壁
| # | 課題 | 影響度 | 技術的な壁 |
|---|---|---|---|
| 1 | 日本語音声認識の精度 | 高 | コールセンター特有の業界用語・略語が多い |
| 2 | 通話時間の長さ | 中 | 1通話平均8分、最長20分超。APIの入力上限 |
| 3 | リアルタイム性の要求 | 中 | 通話終了後30分以内にテキストが見たい |
| 4 | コスト | 中 | 600件/日を全件処理するAPI費用 |
特に課題2が実装上の最大のハードルでした。gpt-4o-transcribeのAPIは1リクエストあたりの音声ファイルサイズに制限があるため、長い通話を分割して送信する仕組みが必要です。
3. 設計 — Cloud Run + gpt-4o-transcribe パイプライン
graph TD
ZOOM[Zoom Phone
通話終了] -->|Webhook| SERVICE[Cloud Run Service
HTTP トリガー]
SERVICE -->|非同期| JOB[Cloud Run Job
文字起こし実行]
JOB --> DL[Zoom API
録音ダウンロード]
DL --> SPLIT[pydub
無音区間で分割]
SPLIT --> API[gpt-4o-transcribe
チャンク別に文字起こし]
API --> MERGE[テキスト結合]
MERGE --> SF[Salesforce
タスクに紐付け保存]
style SERVICE fill:#3b82f6,color:#fff
style JOB fill:#8b5cf6,color:#fff
style API fill:#10b981,color:#fff
style SF fill:#f59e0b,color:#fff
なぜ gpt-4o-transcribe を選んだか
| 候補 | 日本語精度 | コスト | 導入コスト | 選定 |
|---|---|---|---|---|
| Google Speech-to-Text | 高 | 従量課金(高) | 中 | × コスト |
| AWS Transcribe | 中〜高 | 従量課金(中) | 中 | × 精度 |
| Whisper large-v3 (self-hosted) | 高 | GPU固定費 | 高(インフラ構築) | × 運用コスト |
| **gpt-4o-transcribe (OpenAI API)** | **高** | **従量課金(低)** | **低(API呼出のみ)** | **採用** |
決め手は導入コストの低さです。セルフホストのWhisperも検討しましたが、GPUインスタンスの運用・スケーリングの工数を考えると、2名のエンジニアチームではAPI方式が現実的でした。精度面でもgpt-4o-transcribeはWhisper large-v3と同等以上(社内テストでWER 11.8%)で、コールセンター音声との相性が良好です。
音声分割の設計
1通話が長い場合、pydubのsplit_on_silenceで無音区間を検出して分割します。
from pydub import AudioSegment
from pydub.silence import split_on_silence
def split_audio(audio_content: bytes) -> list[bytes]:
"""無音区間で音声を分割し、APIの入力上限内に収める"""
audio = AudioSegment.from_file(io.BytesIO(audio_content))
chunks = split_on_silence(
audio,
min_silence_len=700, # 700ms以上の無音で分割
silence_thresh=-40, # -40dBFS以下を無音とみなす
keep_silence=300, # 分割後も前後300msの無音を残す
)
return [chunk.export(format="wav").read() for chunk in chunks]
分割後の各チャンクをgpt-4o-transcribeに送信し、結果を時系列順に結合してフルテキストを生成します。
Cloud Run の2層構成
Cloud Run Service(HTTPトリガー): Zoom Phoneからのwebhookを受信し、Cloud Run Jobを非同期起動。リクエストを受けたら即座にレスポンスを返す(webhook のタイムアウト回避)。
Cloud Run Job(バッチ処理): 実際の録音ダウンロード・分割・文字起こし・保存を実行。1通話あたり30秒〜2分で完了。失敗時はCloud Runの自動リトライ機能で最大3回再実行。
graph LR
WH[Webhook受信
即座に200返却] -->|非同期起動| JOB[Cloud Run Job]
JOB -->|成功| SF[Salesforce保存]
JOB -->|失敗| RETRY[自動リトライ
最大3回]
RETRY -->|3回失敗| ALERT[Slackアラート]
style WH fill:#3b82f6,color:#fff
style JOB fill:#8b5cf6,color:#fff
style ALERT fill:#ef4444,color:#fff
4. 実装 — 2名で6週間
このプロジェクトはバックエンドエンジニア1名(パイプライン構築)とSalesforceエンジニア1名(データモデル・UI)の2名体制です。
Phase 1: プロトタイプ(2週間)
Zoom APIからの録音ダウンロード → gpt-4o-transcribe → コンソール出力という最小構成を構築。この段階で精度検証を実施し、QAチームの手動評価との一致率82%を確認。
Phase 2: Cloud Run パイプライン構築(2週間)
Cloud Run Service + Job の2層構成を構築。pydubの無音分割を追加し、長時間通話に対応。Salesforceのタスクオブジェクトにテキストを保存し、既存のQAワークフローに統合。
Phase 3: QAダッシュボード統合(2週間)
Salesforceのレポート・ダッシュボードを活用し、文字起こしテキストの全文検索、キーワードアラート(「クレーム」「解約」「上司」等の出現時に自動フラグ)、1日のサマリー表示を実装。
失敗: 最初の分割パラメータ
最大の失敗は、無音検出のパラメータ調整です。最初はmin_silence_len=500(500ms)で分割したところ、会話中の短い間(相槌の間など)でも分割されてしまい、1通話が30以上のチャンクに分かれました。API呼び出し回数が爆発し、コストが想定の3倍に。
min_silence_len=700に調整し、さらにチャンクの最大長を20分に制限するロジックを追加。コストは想定範囲内に収まりました。
5. 結果 — QAレビュー工数80%削減
3ヶ月間の運用データです。
| 指標 | Before | After | 改善率 |
|---|---|---|---|
| QAチェック対象 | 64件/日(サンプリング) | 全600件/日(全件テキスト化) | **全件カバー** |
| 1件あたりレビュー時間 | 15分(全編再生) | 3分(テキスト検索+要所のみ再生) | **-80%** |
| QA担当者1人あたり作業時間/日 | 8時間 | 1.5時間 | **-81%** |
| キーワードアラート検出 | なし | 平均12件/日(要注意通話の自動フラグ) | **新機能** |
| 文字起こし完了までの時間 | — | 通話終了後 平均3分 | **ほぼリアルタイム** |
なぜ「聴く」から「読む」で80%削減できたか
従来のQAレビューは通話を最初から最後まで再生する必要がありました。8分の通話なら8分かかる。早送りしても内容を把握するのに5分はかかる。
文字起こし後は、テキストを目で追って問題箇所だけ音声で確認する運用に変わりました。キーワードアラートが付いた通話を優先的にレビューし、テキスト上でネガティブワード周辺のコンテキストを確認。音声再生は「本当に問題がある箇所」だけ。これで1件3分に短縮できました。
コスト
| 項目 | 月額 |
|---|---|
| OpenAI API(gpt-4o-transcribe, 月約5,000件 × 平均8分) | 約8万円 |
| Cloud Run(Service + Job) | 約1.5万円 |
| 合計 | **約9.5万円** |
QA担当者2名の作業時間を81%削減。空いた時間をオペレーター個別フィードバックや研修改善に充てています。
6. 展望 — 次に取り組むこと
感情分析の追加
現在は文字起こしテキストのキーワード検索でフラグ付けしていますが、今後はテキストに感情分析を組み合わせ、ネガティブ感情の通話を自動検出する仕組みを検討しています。文字起こし基盤が整ったことで、この上に分析レイヤーを載せる土台ができました。
話者分離
現在は通話全体を1つのテキストとして出力していますが、オペレーターと顧客の発話を分離できれば、「顧客がネガティブワードを発した箇所」と「オペレーターの対応品質」を個別に評価できます。pyannote.audio等の話者分離技術の導入を検討中です。
リアルタイム文字起こし
現在は通話終了後のバッチ処理ですが、通話中にリアルタイムで文字起こしし、SVに即時表示する仕組みも構想しています。ただしストリーミング処理の精度とレイテンシのトレードオフがあるため、中期目標として位置づけています。
「音声データをテキスト化する」だけで、QA業務の在り方が根本的に変わりました。技術的には枯れたAPIを呼ぶだけのシンプルな構成ですが、業務インパクトは大きい。シンプルな技術で大きな価値を出す——ClassLabの開発スタイルがよく表れたプロジェクトでした。
採用情報
ClassLab では一緒に技術的挑戦に取り組むエンジニアを募集しています。