OpenAI WebSocket API の使い方

Ashley Innocent

Ashley Innocent

24 2月 2026

OpenAI WebSocket API の使い方

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

要約

OpenAIは、異なるユースケースに対応するため、2つのWebSocket APIモードを提供しています。Responses API WebSocketモードは、頻繁なツール呼び出しを伴うエージェントワークフロー向け(20回以上のツール呼び出しで最大40%高速化)、Realtime APIは、低遅延の音声およびオーディオアプリケーション向けです。どちらのモードも、ステートレスなHTTPリクエストの代わりに永続的なWebSocket接続を使用することで、繰り返しの接続オーバーヘッドを排除し、イベント駆動型のステートフルな対話を可能にすることで、レイテンシを削減します。

はじめに

OpenAIのAPIは、単純なリクエスト・レスポンスのパターンを超えて進化しました。迅速なツール呼び出しやリアルタイムオーディオストリーミングを必要とするアプリケーションでは、従来のHTTPモデルは不要なオーバーヘッドを生み出します。新しいリクエストごとに接続の確立、認証、状態の送信が必要となり、同じ会話を続けている場合でも同様です。

OpenAIのWebSocket APIは、永続的な双方向接続を維持することでこの問題を解決します。20回以上の連続したツール呼び出しを伴うエージェントワークフローの場合、これによりエンドツーエンドの実行速度が約40%高速化されます。音声アプリケーションの場合、500ミリ秒未満のレイテンシで、自然で中断可能な会話を実現します。

💡
WebSocket接続のテストは、従来、複雑なデバッグツールを必要としました。ApidogのWebSocketテストインターフェースを使用すると、接続の確立、イベントの送信、応答のリアルタイム監視が可能になり、OpenAI WebSocket統合を本番デプロイ前に検証するために不可欠です。
button

このガイドでは、OpenAIのWebSocketモードの両方、すなわちツールを多用するエージェントワークフロー向けのResponses APIと、オーディオストリーミング向けのRealtime APIについて説明します。それぞれの用途、実装方法、および効果的なテスト方法を学びます。

OpenAI WebSocket APIとは?

OpenAI WebSocket APIは、OpenAIの言語モデルと対話するためのHTTPに代わるトランスポートメカニズムを提供します。API呼び出しごとに新しい接続を作成する代わりに、WebSocketはセッション期間中開いたままになる単一の長寿命接続を確立します。

主な特徴

永続的な接続: 一度確立されると、WebSocket接続は明示的に閉じられるまで開いたままであり、リクエストごとの接続オーバーヘッドが排除されます。

双方向通信: クライアントとサーバーの両方がいつでもメッセージを送信でき、真のイベント駆動型アーキテクチャを可能にします。

ステートフルなセッション: サーバーは現在の接続のコンテキストを維持し、完全な会話履歴を再送信することなく、以前の応答を参照できるようにします。

イベント駆動型モデル: 通信は、リクエスト・レスポンスのペアではなく、離散的なイベント(JSONメッセージ)を通じて行われます。

WebSocketプロトコルの基本

WebSocket接続は、HTTPアップグレードリクエストから始まり、その後WebSocketプロトコルに切り替わります。OpenAIの場合、以下のようなエンドポイントに接続します。

wss://スキームは、セキュアなWebSocket接続(HTTPにおけるHTTPSに相当)を示します。

2つのWebSocketモードを解説

OpenAIは、それぞれ異なるユースケースに最適化された2つの異なるWebSocketモードを提供しています。

Responses API WebSocketモード

Responses APIは、多数の連続したツール呼び出しを行う必要があるエージェントワークフローのためにWebSocket接続をサポートしています。このモードは、コーディングアシスタント、オーケストレーションシステム、および複雑なタスクを達成するためにツールを繰り返し呼び出す自律エージェント向けに設計されています。

仕組み:

アクティブなWebSocket接続では、サービスは接続ローカルのインメモリキャッシュに1つの以前の応答状態(最新の応答)を保持します。ターンを継続する場合、送信するのは次のものだけです。

サーバーは、会話履歴全体を再処理する代わりに、キャッシュされた状態を再利用します。

パフォーマンス上の利点:

20回以上のツール呼び出しを伴うワークフローの場合、OpenAIはHTTPと比較して最大40%高速なエンドツーエンド実行を報告しています。これは以下の理由によるものです。

互換性:

WebSocketモードは、Zero Data Retention (ZDR)store=falseオプションの両方で機能するため、プライバシーに配慮したアプリケーションに適しています。

Realtime API WebSocketモード

Realtime APIは、音声駆動型アプリケーション向けに低遅延のストリーミングオーディオ機能を提供します。これにより、モデルがオーディオ入力にオーディオ出力で応答し、中断を自然に処理できる音声対音声の対話が可能になります。

仕組み:

Realtime APIは、WebSocketを使用してステートフルなイベント駆動型セッションを作成します。オーディオチャンクをAPIにストリーミングすると、APIは文字起こしと生成されたオーディオ応答の両方をストリーミングで返します。接続は以下をサポートします。

主な機能:

音声活動検出 (VAD): このAPIには、ユーザーが一時停止しただけなのか、話し終えたのかを理解するセマンティックVADが含まれています。これにより、より自然な会話の流れが生まれます。

マルチモーダル機能: GPT-4oのネイティブマルチモーダル機能に直接アクセスし、オーディオとテキストの両方を統合されたモデルで処理します。

低遅延: 音声対話用に500ミリ秒未満のレイテンシで設計されており、リアルタイム会話に適しています。

WebSocket vs HTTP: パフォーマンス比較

WebSocketとHTTPのどちらを選択するかは、アプリケーションの特性に依存します。各プロトコルが優れているケースを以下に示します。

WebSocketとHTTPの比較

WebSocketがHTTPを上回る場合

大量のツール呼び出し:
ワークフローで10回以上の連続したツール呼び出しを行う場合、WebSocketの永続的な接続により、繰り返しのセットアップオーバーヘッドがなくなります。各HTTPリクエストには以下が必要です。

WebSocketはこれを一度だけ行い、その後接続を再利用します。

レイテンシに敏感なアプリケーション:
1ミリ秒が重要となるリアルタイム音声またはチャットアプリケーションの場合、WebSocketの永続的な接続とストリーミング機能は、知覚されるレイテンシを大幅に削減します。

サーバーによる更新開始:
WebSocketは、ポーリングなしでサーバーがクライアントにデータをプッシュすることを可能にします。長時間実行されるエージェントタスクの場合、サーバーはイベント発生時に進捗状況の更新を送信できます。

HTTPで十分な場合

単純なリクエスト・レスポンス:
1回限りのAPI呼び出しや、1~2回のツール呼び出しを伴うワークフローの場合、HTTPは実装とデバッグがより簡単です。ほとんどの開発者はHTTPクライアントに精通しており、インフラストラクチャ(ロードバランサー、プロキシ)はHTTPをうまく処理します。

ステートレスな操作:
リクエスト間でセッション状態を維持する必要がない場合、HTTPのステートレス性はむしろ利点となります。接続管理は不要です。

インフラストラクチャの制約:
一部のデプロイ環境(サーバーレス関数、特定のプロキシ)は、長寿命のWebSocket接続をサポートしていません。HTTPは普遍的に機能します。

パフォーマンス指標

OpenAIのドキュメントとコミュニティテストに基づいています。

指標HTTPWebSocket (Responses API)WebSocket (Realtime API)
接続設定リクエストごと(約100~300ミリ秒)1回のみ(約100~300ミリ秒)1回のみ(約100~300ミリ秒)
20回以上のツール呼び出しワークフロー基準約40%高速該当なし
音声往復レイテンシ該当なし(この目的には設計されていない)該当なし500ミリ秒未満
メモリオーバーヘッド低い(ステートレス)中程度(キャッシュされた状態)中程度~高い(セッション状態)
実装の複雑さ低い中程度中程度~高い

Responses API WebSocketモードの使い方

エージェントワークフローのためにResponses APIへのWebSocket接続を実装しましょう。

前提条件

接続設定

Node.jsの例:

const WebSocket = require('ws');

// Connect to Responses API WebSocket endpoint
const ws = new WebSocket('wss://api.openai.com/v1/responses', {
  headers: {
    'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
    'OpenAI-Beta': 'responses-api=v1'
  }
});

ws.on('open', () => {
  console.log('Connected to OpenAI Responses API');

  // Send initial request
  const initialMessage = {
    model: 'gpt-4o',
    messages: [
      { role: 'user', content: 'Help me analyze this codebase and suggest improvements.' }
    ],
    tools: [
      {
        type: 'function',
        function: {
          name: 'read_file',
          description: 'Read contents of a file',
          parameters: {
            type: 'object',
            properties: {
              path: { type: 'string', description: 'File path to read' }
            },
            required: ['path']
          }
        }
      },
      {
        type: 'function',
        function: {
          name: 'search_code',
          description: 'Search for code patterns',
          parameters: {
            type: 'object',
            properties: {
              pattern: { type: 'string', description: 'Regex pattern to search' }
            },
            required: ['pattern']
          }
        }
      }
    ]
  };

  ws.send(JSON.stringify(initialMessage));
});

ws.on('message', (data) => {
  const response = JSON.parse(data);
  console.log('Received:', response);

  // Check if model wants to call tools
  if (response.choices[0].finish_reason === 'tool_calls') {
    const toolCalls = response.choices[0].message.tool_calls;

    // Execute tools (simplified)
    const toolResults = toolCalls.map(call => ({
      tool_call_id: call.id,
      output: executeToolLocally(call.function.name, call.function.arguments)
    }));

    // Continue the conversation with tool results
    const continuation = {
      previous_response_id: response.id, // Reference previous response
      input: toolResults
    };

    ws.send(JSON.stringify(continuation));
  }
});

ws.on('error', (error) => {
  console.error('WebSocket error:', error);
});

ws.on('close', () => {
  console.log('Connection closed');
});

function executeToolLocally(name, args) {
  // Your tool execution logic
  if (name === 'read_file') {
    const { path } = JSON.parse(args);
    return fs.readFileSync(path, 'utf-8');
  }
  // ... other tools
}

Pythonの例:

import websocket
import json
import os

def on_message(ws, message):
    response = json.loads(message)
    print(f"Received: {response}")

    # Handle tool calls
    if response['choices'][0]['finish_reason'] == 'tool_calls':
        tool_calls = response['choices'][0]['message']['tool_calls']

        # Execute tools
        tool_results = []
        for call in tool_calls:
            result = execute_tool(call['function']['name'],
                                 json.loads(call['function']['arguments']))
            tool_results.append({
                'tool_call_id': call['id'],
                'output': result
            })

        # Send continuation with only new input + previous_response_id
        continuation = {
            'previous_response_id': response['id'],
            'input': tool_results
        }
        ws.send(json.dumps(continuation))

def on_error(ws, error):
    print(f"Error: {error}")

def on_close(ws, close_status_code, close_msg):
    print("Connection closed")

def on_open(ws):
    print("Connected to OpenAI Responses API")

    # Send initial request
    initial_message = {
        'model': 'gpt-4o',
        'messages': [
            {'role': 'user', 'content': 'Analyze this codebase and suggest improvements.'}
        ],
        'tools': [
            {
                'type': 'function',
                'function': {
                    'name': 'read_file',
                    'description': 'Read file contents',
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'path': {'type': 'string'}
                        },
                        'required': ['path']
                    }
                }
            }
        ]
    }
    ws.send(json.dumps(initial_message))

def execute_tool(name, args):
    if name == 'read_file':
        with open(args['path'], 'r') as f:
            return f.read()
    # ... other tools

# Create WebSocket connection
ws = websocket.WebSocketApp(
    "wss://api.openai.com/v1/responses",
    header={
        "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
        "OpenAI-Beta": "responses-api=v1"
    },
    on_open=on_open,
    on_message=on_message,
    on_error=on_error,
    on_close=on_close
)

ws.run_forever()

主要な実装詳細

状態管理:
HTTPとの決定的な違いは、継続処理でprevious_response_idを使用することです。これは、APIに最後の応答からのキャッシュされた状態を再利用するよう指示します。

入力のみの継続:
ターンを継続する場合、送信するのは次のものだけです。

完全なmessages配列を再送信しないでください。サーバーはすでにそのコンテキストを持っています。

Zero Data Retention:
WebSocketモードでZDRを使用するには、最初のリクエストにstore: falseを含めます。

Realtime API WebSocketモードの使い方

Realtime APIは低遅延の音声対話を可能にします。その実装方法を以下に示します。

前提条件

接続設定

JavaScript(ブラウザ)の例:

// Connect to Realtime API
const ws = new WebSocket(
  `wss://api.openai.com/v1/realtime?model=gpt-realtime`,
  ['realtime', 'openai-insecure-api-key.' + process.env.OPENAI_API_KEY]
);

ws.addEventListener('open', () => {
  console.log('Connected to Realtime API');

  // Configure session
  ws.send(JSON.stringify({
    type: 'session.update',
    session: {
      modalities: ['text', 'audio'],
      voice: 'alloy',
      input_audio_format: 'pcm16',
      output_audio_format: 'pcm16',
      turn_detection: {
        type: 'server_vad', // or 'semantic_vad' for smarter detection
        threshold: 0.5,
        prefix_padding_ms: 300,
        silence_duration_ms: 500
      }
    }
  }));
});

ws.addEventListener('message', (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case 'session.created':
      console.log('Session created:', message.session);
      break;

    case 'conversation.item.created':
      console.log('New item:', message.item);
      break;

    case 'response.audio.delta':
      // Received audio chunk - play it
      const audioChunk = base64ToArrayBuffer(message.delta);
      playAudioChunk(audioChunk);
      break;

    case 'response.audio_transcript.delta':
      // Received transcript chunk
      console.log('Transcript:', message.delta);
      break;

    case 'input_audio_buffer.speech_started':
      console.log('User started speaking');
      break;

    case 'input_audio_buffer.speech_stopped':
      console.log('User stopped speaking');
      break;

    case 'error':
      console.error('API error:', message.error);
      break;
  }
});

// Send audio from microphone
async function streamMicrophoneToAPI() {
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  const audioContext = new AudioContext({ sampleRate: 24000 });
  const source = audioContext.createMediaStreamSource(stream);
  const processor = audioContext.createScriptProcessor(4096, 1, 1);

  processor.onaudioprocess = (e) => {
    const inputData = e.inputBuffer.getChannelData(0);

    // Convert Float32 to Int16 PCM
    const pcmData = new Int16Array(inputData.length);
    for (let i = 0; i < inputData.length; i++) {
      pcmData[i] = Math.max(-32768, Math.min(32767, inputData[i] * 32768));
    }

    // Send to API
    ws.send(JSON.stringify({
      type: 'input_audio_buffer.append',
      audio: arrayBufferToBase64(pcmData.buffer)
    }));
  };

  source.connect(processor);
  processor.connect(audioContext.destination);
}

// Send text input
function sendTextMessage(text) {
  ws.send(JSON.stringify({
    type: 'conversation.item.create',
    item: {
      type: 'message',
      role: 'user',
      content: [
        { type: 'input_text', text: text }
      ]
    }
  }));

  // Request response generation
  ws.send(JSON.stringify({
    type: 'response.create'
  }));
}

function playAudioChunk(arrayBuffer) {
  const audioContext = new AudioContext({ sampleRate: 24000 });
  audioContext.decodeAudioData(arrayBuffer, (buffer) => {
    const source = audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(audioContext.destination);
    source.start();
  });
}

Pythonの例:

import websocket
import json
import base64
import pyaudio

# Audio configuration
RATE = 24000
CHUNK = 4096
FORMAT = pyaudio.paInt16
CHANNELS = 1

audio = pyaudio.PyAudio()

def on_open(ws):
    print("Connected to Realtime API")

    # Configure session
    ws.send(json.dumps({
        'type': 'session.update',
        'session': {
            'modalities': ['text', 'audio'],
            'voice': 'alloy',
            'input_audio_format': 'pcm16',
            'output_audio_format': 'pcm16',
            'turn_detection': {
                'type': 'server_vad',
                'threshold': 0.5,
                'silence_duration_ms': 500
            }
        }
    }))

    # Start streaming microphone
    stream_microphone(ws)

def on_message(ws, message):
    data = json.loads(message)

    if data['type'] == 'response.audio.delta':
        # Decode and play audio
        audio_chunk = base64.b64decode(data['delta'])
        play_audio(audio_chunk)

    elif data['type'] == 'response.audio_transcript.delta':
        print(f"Transcript: {data['delta']}", end='', flush=True)

    elif data['type'] == 'input_audio_buffer.speech_started':
        print("\n[User speaking...]")

    elif data['type'] == 'error':
        print(f"Error: {data['error']}")

def stream_microphone(ws):
    stream = audio.open(
        format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        input=True,
        frames_per_buffer=CHUNK
    )

    def audio_thread():
        while True:
            audio_data = stream.read(CHUNK)
            ws.send(json.dumps({
                'type': 'input_audio_buffer.append',
                'audio': base64.b64encode(audio_data).decode('utf-8')
            }))

    import threading
    threading.Thread(target=audio_thread, daemon=True).start()

def play_audio(audio_chunk):
    stream = audio.open(
        format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        output=True
    )
    stream.write(audio_chunk)
    stream.stop_stream()
    stream.close()

# Create WebSocket connection
ws = websocket.WebSocketApp(
    f"wss://api.openai.com/v1/realtime?model=gpt-realtime",
    header={
        "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"
    },
    on_open=on_open,
    on_message=on_message
)

ws.run_forever()

主要な実装詳細

イベントタイプ:

Realtime APIはイベント駆動型通信を使用します。一般的なイベントは以下の通りです。

クライアント → サーバー:

サーバー → クライアント:

音声活動検出:

2つのVADモードから選択します。

server_vad: 音量と無音時間に基づく基本的な音声活動検出。

semantic_vad: 自然な一時停止とターンの完了を理解する、よりスマートな検出。ユーザーが思考中に一時停止する可能性のある、より自然な会話に使用します。

ApidogでWebSocket接続をテストする

WebSocket APIのテストはHTTPテストとは異なり、接続を維持し、イベントを送信し、双方向のメッセージフローを監視する必要があります。Apidogは、特殊なWebSocketテスト機能を提供します。

Apidog Webデザインインターフェース

ApidogでのWebSocketテストの設定

ステップ1: WebSocketリクエストを作成

Apidogで新しいリクエストを作成し、プロトコルとして「WebSocket」を選択します。接続URLを入力します。

ApidogでWebSocketリクエストを作成
wss://api.openai.com/v1/responses

ステップ2: ヘッダーを設定

認証ヘッダーを追加します。

Authorization: Bearer YOUR_OPENAI_API_KEY
OpenAI-Beta: responses-api=v1

Realtime APIの場合、URLベースの認証も使用できます。

wss://api.openai.com/v1/realtime?model=gpt-realtime

サブプロトコルヘッダーにAPIキーを含めます。

ステップ3: 接続を確立

「Connect」をクリックしてWebSocket接続を確立します。Apidogには以下が表示されます。

ステップ4: イベントを送信

Apidogのメッセージコンポーザーを使用してJSONイベントを送信します。Responses APIの場合:

{
  "model": "gpt-4o",
  "messages": [
    {
      "role": "user",
      "content": "What's the weather in San Francisco?"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather",
        "parameters": {
          "type": "object",
          "properties": {
            "location": { "type": "string" }
          }
        }
      }
    }
  ]
}

ステップ5: 応答を監視

Apidogには以下が表示されます。

継続のテスト

previous_response_idを使用した継続パターンをテストするには:

  1. 最初のメッセージを送信し、応答内のresponse.idをメモします。
  2. 新しい入力のみを含む継続を送信します。
{
  "previous_response_id": "resp_abc123",
  "input": [
    {
      "tool_call_id": "call_xyz789",
      "output": "{\"temperature\": 72, \"conditions\": \"sunny\"}"
    }
  ]
}
  1. 完全なコンテキストを再送信する場合と比較して、レイテンシが減少していることを確認します。

Realtime APIのテスト

Realtime APIの場合、Apidogでは以下のことが可能です。

これは、音声アシスタントがユーザーの発話を途中で遮ったり、音声を適切に検出しない理由をデバッグする際に特に役立ちます。

環境変数

Apidogの環境変数を使用してAPIキーを安全に保存します。

{{OPENAI_API_KEY}}

これにより、リクエストを編集することなく、開発キーと本番キーを切り替えることができます。

実際のユースケース

OpenAIのWebSocketモードが優れている実際のシナリオを見てみましょう。

ユースケース1: 自律コーディングエージェント

シナリオ: コードベースを分析し、問題を特定し、自律的に改善を行うコーディングアシスタント。

Responses API WebSocketを使用する理由:

実装パターン:

// Initial task
ws.send({ messages: [{ role: 'user', content: 'Audit security vulnerabilities' }], tools: [...] })

// First response: model calls read_file
ws.on('message', (resp1) => {
  ws.send({ previous_response_id: resp1.id, input: [tool_result_1] })
})

// Second response: model calls search_code
ws.on('message', (resp2) => {
  ws.send({ previous_response_id: resp2.id, input: [tool_result_2] })
})

// Continue for 20+ iterations...

ユースケース2: 音声カスタマーサービスボット

シナリオ: 自然な会話の流れで顧客の問い合わせに対応する電話サポートボット。

Realtime API WebSocketを使用する理由:

実装パターン:

// Stream phone audio to API
phoneSystem.on('audio', (chunk) => {
  ws.send({
    type: 'input_audio_buffer.append',
    audio: base64Encode(chunk)
  })
})

// Play AI responses immediately
ws.on('message', (event) => {
  if (event.type === 'response.audio.delta') {
    phoneSystem.playAudio(base64Decode(event.delta))
  }
})

よくある問題のトラブルシューティング

接続の確立に失敗する

症状: WebSocket接続が開かず、すぐに切断イベントが発生する。

一般的な原因:

  1. 無効なAPIキー - Authorizationヘッダーを再確認してください。
  2. ベータヘッダーの欠落 - Responses APIにはOpenAI-Beta: responses-api=v1が必要です。
  3. ネットワーク制限 - 一部の企業ネットワークではWebSocketがブロックされることがあります。
  4. 不正なURL - wss://ws://ではない)とエンドポイントパスを確認してください。

解決策:
Apidogを使用して、詳細なエラーメッセージで接続をテストします。リクエストインスペクターは送信されたヘッダーを正確に表示するため、APIキーの欠落や間違いを簡単に見つけることができます。

デバッグコード:

ws.on('error', (error) => {
  console.error('Connection error:', error);
});

ws.on('close', (code, reason) => {
  console.log(`Closed with code ${code}: ${reason}`);
  // 一般的なコード:
  // 1006: 異常終了(認証の問題が多い)
  // 1008: ポリシー違反(無効なヘッダー)
});

WebSocketを使用しているにもかかわらず高遅延

症状: WebSocket接続は機能するが、HTTPより高速ではない。

一般的な原因:

  1. previous_response_idを使用していない - 完全なコンテキストを再送信している
  2. コールドスタート - 新しい接続での最初のリクエストは遅い
  3. ネットワークレイテンシ - APIサーバーまでの地理的な距離
  4. 大きなペイロード - 継続時に不要なデータを送信している

解決策:
継続時に新しい入力のみを送信していることを確認してください。

// 誤り - 毎回完全なコンテキストを送信している
ws.send({
  messages: [...allPreviousMessages, newMessage],
  tools: [...]
})

// 正しい - キャッシュされた状態を参照している
ws.send({
  previous_response_id: lastResponse.id,
  input: [newMessage]
})

長期間実行される接続でのメモリリーク

症状: 永続的な接続により、アプリケーションのメモリが時間とともに増加する。

一般的な原因:

  1. イベントリスナーが削除されていない - 再接続時にリスナーが蓄積されている
  2. オーディオバッファが解放されていない - 再生されたオーディオへの参照を保持している
  3. メッセージ履歴が増大している - 受信したすべてのメッセージを保存している

解決策:

// 再接続時にイベントリスナーをクリーンアップ
function cleanupAndReconnect(ws) {
  ws.removeAllListeners();
  ws.close();

  const newWs = createConnection();
  return newWs;
}

// 再生後にオーディオバッファを解放
function playAndRelease(audioBuffer) {
  const source = audioContext.createBufferSource();
  source.buffer = audioBuffer;
  source.connect(audioContext.destination);
  source.start();

  source.onended = () => {
    source.disconnect();
    // バッファはガベージコレクションによって解放されます
  };
}

// メッセージ履歴の制限
const messageHistory = [];
const MAX_HISTORY = 100;

ws.on('message', (data) => {
  messageHistory.push(data);
  if (messageHistory.length > MAX_HISTORY) {
    messageHistory.shift(); // 最も古いものを削除
  }
});

結論

OpenAIのWebSocket APIモードは、AIアプリケーションに新たな可能性を切り開きます。Responses API WebSocketモードは、頻繁なツール呼び出しを伴うエージェントワークフローで最大40%高速な実行を実現し、自律コーディングアシスタントやオーケストレーションシステムに最適です。Realtime APIは、音声アプリケーション向けに500ミリ秒未満のレイテンシを提供し、自然で中断可能な会話を可能にします。

適切なモードの選択は、ユースケースによって異なります。

WebSocket接続の永続的でイベント駆動型の性質は、HTTPとは異なるテストアプローチを必要とします。ApidogのリアルタイムWebSocketクライアントを使用してOpenAIのWebSocket APIをテストしてください — APIキーをインポートし、接続を確立し、イベントを送信し、詳細なロギングで応答を監視します。無料でお試しいただき、本番デプロイ前に統合を検証してください。

button

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる