gpt-4o-transcribe-diarizeは、OpenAIのTranscription API(/v1/audio/transcriptions)で使える、話者分離(ダイアリゼーション)付きの音声認識モデルです。response_formatにdiarized_jsonを指定すると、「誰が・いつ・何を話したか」を話者ラベルと秒単位のタイムスタンプ付きのセグメントで返します。料金は音声1分あたり約0.006ドルです。
一方でOpenAIは2026年8月26日、このモデルを含む4つの文字起こしモデルの廃止を告知しました。APIからの提供終了は2027年2月26日です。本記事では2026年9月時点の公式ドキュメントをもとに、仕様・料金・Pythonでの使い方に加えて、長い録音を分割したときに話者ラベルがずれる問題の対処と、提供終了に向けた移行先の選び方まで整理します。
まとめ:gpt-4o-transcribe-diarizeの要点と2026年9月時点の位置づけ
- 話者ラベル付きの文字起こしを1回のAPI呼び出しで返す、OpenAIで唯一のモデル。公式の文字起こしガイドでも「話者ラベル付きの文字起こしが必要なとき」の指定モデルになっている
- 話者ラベルを受け取るには
response_format="diarized_json"が必須。30秒を超える音声ではchunking_strategyの指定も必須("auto"またはVAD設定) - ファイルは25MBまで(公式記載)。音声長は1400秒(約23分)を超えると拒否されるエラーが利用者から報告されている。長い会議は分割が前提で、分割するとリクエストごとに話者ラベルがA・Bから振り直される。参照音声を引き継いで揃える
- 料金は1分あたり約0.006ドル(公式の推定額。請求は音声入力100万トークン2.50ドル・出力10ドルのトークン課金)。gpt-4o-transcribeと同額
- Realtime API、
prompt、logprobs、語単位タイムスタンプ、Batch APIには対応しない - OpenAI APIでは2027年2月26日に提供終了。後継として案内されたgpt-transcribe・gpt-live-transcribeは、2026年9月時点で話者ラベルを返さない。新規に組むなら、話者分離の担い手を差し替えられる設計にしておく
gpt-4o-transcribe-diarizeの仕様|diarizeの意味と返る情報
diarize(ダイアリゼーション)の意味と、このモデルが返すもの
diarize(diarization)は、音声を「どの区間を誰が話したか」で区切る処理です。日本語では話者分離、または話者識別と訳されます。通常の文字起こしは話者の区別がない1本のテキストを返しますが、話者分離を組み合わせると「A: 〜」「B: 〜」の形に分けられます。会議の議事録やコールセンターの通話記録のように発言者が成果物の一部になる用途では、この区別が必要になります。
gpt-4o-transcribe-diarizeは、文字起こしと話者分離を1つのモデルで同時に処理します。公式のAPIリファレンスによると、話者ラベルはA・B…と大文字のアルファベットで順に振られます。後述の既知話者(known_speaker_names)を渡した場合は、渡した名前がそのままラベルになります。
モデル仕様と使えない機能
モデルページに記載されている仕様と、APIリファレンスで「このモデルでは使えない」と明記されている機能は次のとおりです。
| 項目 | 内容 |
|---|---|
| モデルID | gpt-4o-transcribe-diarize(スナップショットはこの1つ) |
| 対応エンドポイント | /v1/audio/transcriptions のみ |
| コンテキスト長/最大出力 | 16,000トークン/2,000トークン |
| ファイル上限 | 25MB |
| 音声長の上限 | 公式記載なし(1400秒超のエラー報告あり) |
| 入力形式 | flac・mp3・mp4・mpeg・mpga・m4a・ogg・wav・webm |
| 出力形式 | json・text・diarized_json |
| 使えないもの | prompt・include(logprobs)・timestamp_granularities |
| 非対応のAPI | Realtime・Batch・Chat Completions・Responses |
音声長の上限は公式ドキュメントに書かれていません。ただし実際に長い録音を送ると、「audio duration 1830.530612 seconds is longer than 1400 seconds which is the maximum for this model」という400エラーが返ります(2026年1月、OSSの文字起こしツールspeakrのissue #168で報告)。chunking_strategy="auto"を指定していてもこの上限は外れません。30分・60分の会議はファイルを分割して送る前提で設計します。
注意したいのは出力形式です。jsonやtextも指定できますが、この2つでは話者ラベルが返りません。話者分離のためにこのモデルを選んだのなら、diarized_json以外を指定する理由はありません。
専門用語の読みをpromptで補正する使い方もできません。固有名詞の誤認識が多い用途では、後段で辞書置換をかけるか、テキスト側だけ別モデルで起こし直す構成を検討します。
gpt-4o-transcribe・gpt-transcribe・whisper-1との違いと料金
OpenAIのファイル文字起こし系モデルを、話者ラベルの有無と料金で並べると次のとおりです。料金は2026年9月時点の公式料金ページの値で、単位は音声1分あたりの米ドル(トークン課金のモデルは推定額)です。
| モデル | 話者ラベル | タイムスタンプ | prompt | 1分単価 | 提供終了 |
|---|---|---|---|---|---|
| gpt-4o-transcribe-diarize | あり | セグメント単位 | 不可 | $0.006 | 2027-02-26 |
| gpt-4o-transcribe | なし | なし | 可 | $0.006 | 2027-02-26 |
| gpt-4o-mini-transcribe | なし | なし | 可 | $0.003 | 2027-02-26 |
| whisper-1 | なし | 語・セグメント単位 | 可(224トークン) | $0.006 | 2027-02-26 |
| gpt-transcribe | なし | なし | 可 | $0.0045 | 未告知 |
gpt-4o-transcribeとの主な違いは、話者ラベルとセグメント単位のタイムスタンプの有無に加え、prompt・logprobs・対応する出力形式です。単価は同じなので、話者の区別が要らない用途でdiarizeを選ぶ理由はありません。gpt-4o-transcribeの出力だけでは話者を特定できません。元音声を別の話者分離処理に渡し、文字起こしとの時刻合わせを追加すれば、後段で話者を割り当てる構成は可能です。
whisper-1との違いは2点あります。whisper-1は話者ラベルを返しませんが、語単位のタイムスタンプとsrt・vttの字幕形式を出せます。字幕の生成にはwhisper-1、発言者ごとの記録にはdiarize、という分担です。
2026年7月28日に追加されたgpt-transcribeは、ファイル文字起こしの推奨モデルです。1分0.0045ドルとdiarizeより25%安く、prompt・keywords・languagesで文脈を渡せます。ただし話者ラベルもタイムスタンプも返しません。
料金の目安|1時間の会議と月100時間の試算
1分0.006ドルで計算すると、60分の会議1本は0.36ドルです(1400秒の上限があるため、実際には3本に分けて送ります)。月に100時間(6,000分)を処理する場合、1分0.006ドルと仮定した試算は36ドルです。ただし公式料金ページでこの1分単価は「Estimated cost(推定額)」の列にあり、請求はトークン課金(音声入力100万トークンあたり2.50ドル、テキスト出力10ドル)で計算されます。発話の密度で出力トークンが変わるため、本番の見積もりは代表的な録音を数本流し、利用状況のページで実額を確かめてから出します。
既知話者の参照音声を渡す場合、その音声も入力に含まれます。1人あたり10秒以内とはいえ、分割したすべてのリクエストに毎回付けると、その分だけ入力が増える点は見積もりに入れておきます。
他社の文字起こしAPIと横断で料金を比べたい場合は、文字起こしAPIの比較と選び方で主要7サービスの単価と日本語対応をまとめています。
Pythonでの使い方|diarized_jsonを受け取るまで
OpenAIのPython SDK(openaiパッケージ)は、2025年10月16日公開の2.4.0でこのモデルに対応しました。これより古い版ではdiarized_jsonの応答を型付きで受け取れないため、先に更新しておきます。SDKの導入とクライアントの初期化はOpenAI Python SDKの使い方を参照してください。
最小構成のコードとchunking_strategyの指定
from openai import OpenAI
client = OpenAI() # 環境変数 OPENAI_API_KEY を読む
with open("meeting.wav", "rb") as f:
result = client.audio.transcriptions.create(
model="gpt-4o-transcribe-diarize",
file=f,
response_format="diarized_json",
chunking_strategy="auto",
)
for seg in result.segments:
print(seg.speaker, round(seg.start, 1), round(seg.end, 1), seg.text)
chunking_strategyは、30秒を超える音声でこのモデルを使うときの必須パラメータです。"auto"を指定すると、サーバー側で音量を正規化したうえで、音声区間検出(VAD)で区切り位置を決めます。省略すると「chunking_strategy is required」のエラーで止まり、OpenAIの開発者フォーラムにも、このエラーの解決方法を尋ねるスレッドが立っています。
既知話者の参照音声による名前ラベルの付与
話者の声のサンプルを渡すと、ラベルがA・Bではなく指定した名前になります。公式の文字起こしガイドに書かれている仕様は次のとおりです。
known_speaker_names[]に名前、known_speaker_references[]に同じ順で音声を渡す- 参照音声は1件あたり2〜10秒、最大4人分
- 音声は本体と同じ形式でよく、multipartで送るときはdata URL(
data:audio/wav;base64,…)にする
Python SDKでは、この2つをextra_bodyに入れて渡します。公式ガイドのコード例も同じ書き方です。
import base64
def to_data_url(path):
with open(path, "rb") as fh:
return "data:audio/wav;base64," + base64.b64encode(fh.read()).decode("ascii")
with open("call.wav", "rb") as f:
result = client.audio.transcriptions.create(
model="gpt-4o-transcribe-diarize",
file=f,
response_format="diarized_json",
chunking_strategy="auto",
extra_body={
"known_speaker_names": ["agent", "customer"],
"known_speaker_references": [to_data_url("agent.wav"), to_data_url("customer.wav")],
},
)
LiteLLMのようなプロキシを経由する構成では、配列フィールドの扱いを確認してください。LiteLLMでは2026年6月、繰り返し送ったknown_speaker_names[]が最後の1件に潰れる不具合が報告されています(issue #29766)。現在のmainブランチでは全件を保持する実装に変わっていますが、中継層の版が古いと、最後の1人以外の参照音声が届かないまま処理されます。返ってきたspeakerに渡した名前が全員分出るかで確認できます。
streamで受け取るときのイベント
stream=Trueを付けると、処理済みのセグメントから順に受け取れます。話者付きの応答では、セグメントが確定するたびにtranscript.text.segmentイベントが届きます。途中経過のtranscript.text.deltaにはsegment_idが付きますが、話者は入っていません。話者はセグメントの確定時にだけ決まるため、画面に話者名を出すならsegmentイベントを待ってから描画します。
これは録音済みファイルを流しながら返す機能で、マイク入力をリアルタイムに話者分離するものではありません。Realtime APIの文字起こしセッションは話者ラベルに対応していないと公式ガイドに明記されています。ライブ字幕が要る場合はGPT-Live-Transcribeの実装手順とGPT-Transcribeとの使い分けで扱っている低遅延モデルを使い、話者付きの確定版は録音をあとからdiarizeへ流す二段構成にします。
diarized_jsonの構造と議事録形式への整形
diarized_jsonの応答は、全文のtext、音声の長さduration(秒)、セグメントの配列segmentsを持ちます。各セグメントのフィールドは次のとおりです。
| フィールド | 型 | 内容 |
|---|---|---|
| id | string | セグメントの識別子 |
| speaker | string | A・B…または既知話者の名前 |
| start / end | number | 開始・終了時刻(秒) |
| text | string | そのセグメントの文字起こし |
| type | string | 常に transcript.text.segment |
セグメントは発話の切れ目ごとに細かく分かれるため、同じ人の発言が数行に割れます。議事録として読むには、同じ話者が続く区間をまとめて時刻を付け直すと扱いやすくなります。
def to_minutes(segments):
"""同じ話者の連続セグメントをまとめ、[mm:ss] 話者: 本文 の行にする"""
lines = []
for seg in segments:
if lines and lines[-1]["speaker"] == seg.speaker:
previous = lines[-1]["text"]
separator = " " if previous and seg.text and previous[-1].isascii() and previous[-1].isalnum() and seg.text[0].isascii() and seg.text[0].isalnum() else ""
lines[-1]["text"] += separator + seg.text
continue
lines.append({"speaker": seg.speaker, "start": seg.start, "text": seg.text})
return "\n".join(
"[{:02d}:{:02d}] {}: {}".format(*divmod(int(l["start"]), 60), l["speaker"], l["text"])
for l in lines
)
print(to_minutes(result.segments))
# 出力の形
# [00:00] A: 本日の議題は3点です。
# [00:07] B: 1点目から確認させてください。
このコードは、SDK 2.48.0にモックの応答を返させて動作を確認しています(同じ話者の連続する2セグメントが1行にまとまることを確認)。整形したテキストをChatGPTなどに渡して要約させる手順は、ChatGPTで録音・議事録作成する方法で扱っています。
1400秒・25MBの上限による分割で話者ラベルがずれる問題と対処
Transcription APIが受け付けるファイルは25MBまでで、このモデルは音声長も1400秒(約23分)を超えると拒否されたという報告があります。25MBは圧縮形式に変換すれば収まることが多い一方、23分を超える録音は分割するしかありません。1時間の会議なら最低3本です。ここで問題になるのが話者ラベルの一貫性です。
分割ごとにA・Bが振り直される理由
話者ラベルはリクエストごとにAから順に振られます。1本目で「A」だった部長が、2本目では「B」になる可能性があり、同じラベルの維持は保証されません。リクエストをまたいで同じ人を同じ名前に揃える仕組みは、既知話者の参照音声だけです。OpenAIの開発者フォーラムにも、分割をまたいで話者を維持する方法を尋ねるスレッドが立っています。
1本目からの参照音声抽出と2本目以降への引き継ぎ
対処は、1本目の結果から話者ごとに2〜10秒の発話を1つずつ切り出し、2本目以降に既知話者として渡すことです。この例では2〜10秒のセグメントがない話者は対象外になるため、該当者には参照音声を別途用意します。次のコードはWAVを標準ライブラリのwaveで切り出すため、追加の依存はありません。
import base64
import io
import wave
def cut_wav(path, start, end):
"""WAVの start〜end 秒を切り出して bytes で返す"""
with wave.open(path, "rb") as src:
rate = src.getframerate()
src.setpos(int(start * rate))
frames = src.readframes(int((end - start) * rate))
buf = io.BytesIO()
with wave.open(buf, "wb") as dst:
dst.setparams(src.getparams())
dst.writeframes(frames)
return buf.getvalue()
def pick_references(path, result, max_speakers=4):
"""1本目の結果から、話者ごとに2〜10秒の発話を1つ選ぶ"""
names, refs = [], []
for seg in result.segments:
name = f"speaker_{seg.speaker}"
if name in names or not 2 <= seg.end - seg.start <= 10:
continue
names.append(name)
wav = cut_wav(path, seg.start, seg.end)
refs.append("data:audio/wav;base64," + base64.b64encode(wav).decode("ascii"))
if len(names) == max_speakers:
break
return names, refs
def transcribe(path, names=None, refs=None):
extra = {"known_speaker_names": names, "known_speaker_references": refs} if names else None
with open(path, "rb") as f:
return client.audio.transcriptions.create(
model="gpt-4o-transcribe-diarize", file=f,
response_format="diarized_json", chunking_strategy="auto",
extra_body=extra,
)
chunks = ["part1.wav", "part2.wav", "part3.wav"]
first = transcribe(chunks[0])
names, refs = pick_references(chunks[0], first)
for seg in first.segments:
seg.speaker = f"speaker_{seg.speaker}"
results = [first] + [transcribe(p, names, refs) for p in chunks[1:]]
モック応答で確かめた挙動は次のとおりです。1秒しかない発話は参照音声の候補から外れ、同じ話者の5.5秒の発話が選ばれます。2本目のリクエストにはknown_speaker_names[]とknown_speaker_references[]が人数分、繰り返しフィールドとして送られます。
運用では次の3点に注意します。
- 名前を
speaker_Aのように付け替えているのは、2本目で新しく現れた未知の話者に振られるAと衝突させないため - 2本目以降の
start・endは、そのファイルの先頭からの秒数。全体の時刻に直すには、それより前のファイルの長さを足す - 引き継げるのは4人まで。5人以上の会議では、1本目に発言が少ない人の分が漏れるため、発言量の多い順に選ぶなど優先順位を決める
「話者分離できるのは最大4人」は誤解
日本語の解説記事には「話者分離できる人数は最大4人なので、4人以上の会議はチャンクを分けて人数を4人以下にする」と書いたものがあります。公式ドキュメントで4人という上限が付いているのは、既知話者の参照音声(known_speaker_names[])の件数です。参照音声を渡さない場合に検出できる話者数の上限は、APIリファレンスにも文字起こしガイドにも記載がありません。
5人以上の会議を、人数を減らす目的で細かく分割するのは逆効果です。分割するほど前節のラベルずれが増えます。分割は1400秒と25MBの上限に合わせた最小限にとどめ、1本目の結果でラベルの割り当てを実際の音声と突き合わせてから、2本目以降の処理に進んでください。
2027年2月26日の提供終了と移行先の判断
後継のgpt-transcribe・gpt-live-transcribeにおける話者ラベルの非対応
OpenAIは2026年8月26日、whisper-1・gpt-4o-transcribe・gpt-4o-mini-transcribe・gpt-4o-transcribe-diarizeの4モデルについて、2027年2月26日にAPIから削除すると告知しました。OpenAIの廃止ページ(Deprecations)が推奨する移行先は、4モデルとも「gpt-live-transcribeまたはgpt-transcribe」です。
ところが2026年9月27日時点で、この2モデルのモデルページとAPIリファレンスに話者ラベルの記載はありません。diarized_jsonに対応するモデルとして名前が挙がっているのもgpt-4o-transcribe-diarizeだけで、文字起こしガイドの「専門機能」の表も話者ラベルにはdiarizeを指定したままです。gpt-transcribeはdiarized_jsonに対応しないため、モデル名だけの置換では移行できません。応答形式と、segmentsを参照する後続処理も変更する必要があります。後継の話者分離モデルが出るかどうかは、OpenAIの変更履歴(changelog)で追ってください。
Azure(Microsoft Foundry)版の退役日は2027年4月15日
Microsoft FoundryのAzure OpenAIでも、gpt-4o-transcribe-diarize(バージョン2025-10-15)が提供されています。Microsoft Learnのモデル退役スケジュール(2026年9月23日更新)では、退役日は2027年4月15日、後継モデルは空欄です。OpenAI直販より約7週間遅いものの、移行を先送りできる期間は短く、後継が決まっていない状況も同じです。Azureでのモデルの選び方はAzure OpenAI Serviceのモデル一覧と選び方で整理しています。
移行先の選び方|他社APIか、文字起こしと話者分離の分離か
2027年2月以降も話者ラベルが必要なら、選択肢は2つです。
1つ目は、話者分離を標準機能として持つ他社APIへ移ることです。AssemblyAI・Deepgram・Google Cloud Speech-to-Text・Amazon Transcribeはいずれも話者分離を提供しています。応答の形は各社で違うため、speaker・start・end・textの4項目に正規化する変換層を1枚挟んでおくと、次に乗り換えるときもアプリ側を触らずに済みます。
2つ目は、文字起こしと話者分離を別の処理に分けることです。WhisperX(BSD-2-Clause)は、Whisperの文字起こしに語単位のタイムスタンプを付け、pyannote.audioの話者分離結果と時刻で突き合わせる構成をとっています。自社サーバーで動かせるため、音声を外部に出せない案件にも向きます。ただし、gpt-transcribeはタイムスタンプを返さないため、その出力を直接時刻で突き合わせることはできません。利用する場合は、元音声と文字列から時刻を求めるアラインメント処理が別途必要です。
2026年9月以降に新規で組む案件では、gpt-4o-transcribe-diarizeを「5か月後に止まる前提の実装」として扱うべきです。検証やPoCで使うのは合理的です。本番に入れるなら、上の変換層を最初から設け、停止日までに差し替え先を決めておきます。
よくある質問
gpt-4o-transcribe-diarizeとgpt-4o-transcribeの違いは何ですか?
話者ラベルとセグメント単位のタイムスタンプを返すかどうかです。料金はどちらも1分約0.006ドルで同じです。diarizeはpromptとlogprobsに対応せず、gpt-4o-transcribeはjson形式しか出せず話者の情報を持ちません。
Realtime APIで話者分離はできますか?
できません。公式ガイドに、話者ラベルは/v1/audio/transcriptionsでのみ利用でき、Realtimeの文字起こしセッションには対応していないと明記されています。stream=Trueで録音済みファイルの結果を順次受け取ることはできます。
Whisperで話者分離はできますか?
OpenAI APIのwhisper-1は話者ラベルを返しません。オープンソースのWhisperを使う場合は、WhisperXのようにpyannote.audioの話者分離と組み合わせるツールを使います。whisper-1自体も2027年2月26日にAPIから削除される予定です。
何人まで話者を分離できますか?
公式に上限が示されているのは、名前を付けるための参照音声の件数(最大4人)です。参照音声なしで検出できる話者数の上限は公式ドキュメントに記載がありません。人数の多い会議では、実際の録音でラベルの割り当てを確認してください。
Azure OpenAIでも使えますか?
使えます。Microsoft FoundryのAzure OpenAIで、バージョン2025-10-15が提供されています。退役日は2027年4月15日で、OpenAI直販の2027年2月26日より後ですが、後継モデルは示されていません。