پرش به محتوا

اتصال زنده (Realtime)

گفت‌وگوی صوتی زنده روی WebSocket، سازگار با OpenAI Realtime API: پاسخ‌گوی تلفنی و اتصال به Asterisk با A-law و μ-law، تشخیص پایان گفتار، فراخوانی ابزار و نمونه‌کد Node.js و Python.

بازبینی: ۱۴ مهر ۱۴۰۵ ۲۰ دقیقه مطالعه

نشانی اصلی: wss://gisoo.pro/api/v1/realtime؛ نشانی ویژهٔ ایران: wss://ir.gisoo.pro/api/v1/realtime. پارامترها و کلید دسترسی در هر دو یکسان‌اند.

با اتصال زنده (Realtime) یک گفت‌وگوی صوتی دوطرفه روی یک اتصال WebSocket دارید: صدای کاربر را همان لحظه که حرف می‌زند می‌فرستید و پاسخ مدل را تکه‌تکه، هم به‌صورت صدا و هم متن، پس می‌گیرید. بیشتر برای تلفن گویا و دستیار صوتی به کار می‌رود: منشی تلفنی، ثبت سفارش تلفنی یا پاسخ‌گوی مرکز تماس. پروتکل با OpenAI Realtime API (نام رویدادهای نسخهٔ نهایی یا GA) سازگار است، پس کد و کتابخانه‌ای که برای آن نوشته شده با عوض کردن نشانی و کلید کار می‌کند.

GETwss://gisoo.pro/api/v1/realtime?model=<model-id>

این نشانی از سرورهای داخل ایران هم در دسترس است. کلید، اعتبار و گزارش مصرف همان است که در درخواست‌های HTTP دارید. درخواست ارتقا به WebSocket یک درخواست GET است.

چطور کار می‌کند

  1. اتصال

    سرور شما با هدر Authorization: Bearer <کلید> به نشانی بالا وصل می‌شود و مدل را در پارامتر model می‌گوید. پیام session.created یعنی جلسه باز است.

  2. تنظیم جلسه

    با session.update دستور سیستمی (instructions)، قالب صدا، صدای گوینده و ابزارها را تعیین می‌کنید.

  3. فرستادن صدا

    صدای کاربر را تکه‌تکه با input_audio_buffer.append می‌فرستید. به‌طور پیش‌فرض سرویس خودش پایان حرف را تشخیص می‌دهد (server_vad) و پاسخ را شروع می‌کند.

  4. گرفتن پاسخ

    صدای پاسخ در response.output_audio.delta و متن همان پاسخ در response.output_audio_transcript.delta می‌رسد. اگر مدل ابزاری را صدا بزند، شما تابع خودتان را اجرا می‌کنید و نتیجه را برمی‌گردانید.

دو نوع مدل روی اتصال زنده کار می‌کند. مدل‌های گفتاری مستقیم (GPT Realtime و Gemini Live) صدا را خودشان می‌شنوند و خودشان با صدا جواب می‌دهند؛ مکث پیش از پاسخ در آن‌ها کوتاه‌تر است و برای پاسخ‌گوی تلفنی و فروش تلفنی مناسب‌ترند. در بقیهٔ مدل‌ها خروجی مدل متن است. وقتی خروجی صوتی روشن است، سرویس همان متن را تکه‌به‌تکه به گفتار تبدیل می‌کند و اول عبارت کوتاهی می‌فرستد تا کاربر شروع پاسخ را بشنود و بقیه‌اش در همان حال نوشته شود. در این حالت یک دستور کوتاه هم به دستور سیستمی شما اضافه می‌شود تا مدل با جمله‌های ساده و گفتاری جواب بدهد، بدون Markdown، فهرست یا ایموجی.

اتصال و احراز هویت

  • کلید را در هدر Authorization: Bearer … یا X-API-Key بفرستید؛ همان کلیدی که برای درخواست‌های HTTP دارید (sk-gisoo-v1-… یا sk-ntz-v1-…).
  • کلید پیش از باز شدن اتصال بررسی می‌شود، درست مثل یک درخواست HTTP: باطل یا منقضی یا غیرفعال بودن کلید، فهرست IPهای مجاز و فهرست مدل‌های مجاز کلید و پروژه.
  • اگر اتصال پذیرفته نشود، WebSocket باز نمی‌شود و یک پاسخ HTTP معمولی (۴۰۱، ۴۰۲، ۴۰۳، ۴۲۹ یا ۵۰۳) با همان قالب خطای {"error": {...}} می‌گیرید.
  • مدل را در نشانی انتخاب می‌کنید و تا پایان جلسه عوض نمی‌شود.
  • پارامتر اختیاری codec قالب صدای ورودی و خروجی را از همان لحظهٔ اتصال تعیین می‌کند: alaw و ulaw (G.711 با ۸ کیلوهرتز، همان چیزی که Asterisk می‌دهد)، pcm8، pcm16 و pcm24 (PCM شانزده‌بیتی با ۸، ۱۶ یا ۲۴ کیلوهرتز). مقدار ناشناخته خطای ۴۰۰ invalid_codec می‌دهد.
کلید را در صفحهٔ وب نگذارید

مرورگر نمی‌تواند هدر Authorization را روی WebSocket بگذارد و کلید هم نباید به دست کاربر برسد. این API برای ارتباط سرور با سرور است: مرورگر یا اپ شما به سرور خودتان وصل می‌شود و سرور شما به گیسو.

متن اتصال ردشده
HTTP/1.1 402 Payment Required
Content-Type: application/json; charset=utf-8

{"error": {"message": "…", "type": "insufficient_quota", "code": "insufficient_credit", "param": null}}

مدل‌ها

شناسهٔ مدلسازندهنوعمناسب برای
gpt-realtime-2.1OpenAIگفتاری مستقیمفروش و پشتیبانی تلفنی، وقتی کیفیت گفت‌وگو از هزینه مهم‌تر است
gpt-realtime-2.1-miniOpenAIگفتاری مستقیمبیشتر تماس‌ها؛ کم‌هزینه‌تر از نسخهٔ کامل
gemini-3.8-liveGoogleگفتاری مستقیمگفت‌وگوی طبیعی فارسی با هزینهٔ کمتر از GPT Realtime
qwen3.8-omni-flash-realtimeAlibaba (Qwen)گفتاری مستقیمپاسخ‌گوی تلفنی فارسی با مکث کوتاه و هزینهٔ کم
qwen/qwen3.8-omni-flashQwenمتن، سپس تبدیل به گفتارآزمایش و تماس‌های ساده
  • مدل‌های گفتاری مستقیم فقط روی همین اتصال کار می‌کنند؛ برای همین در فهرست GET /models نیستند و در /chat/completions پذیرفته نمی‌شوند.
  • صدای گوینده را در audio.output.voice بدهید: در GPT Realtime یکی از صداهای OpenAI (مثل marin، cedar یا alloy) و در Gemini Live یکی از صداهای Gemini (مثل Kore، Puck، Charon یا Aoede). در Gemini Live نام ناشناخته صدای Kore را می‌گیرد. در Qwen Realtime صدای پیش‌فرض Tina است و نام صداهای OpenAI همان صدای پیش‌فرض را می‌گیرد.
  • در qwen3.8-omni-flash-realtime تصویر فقط JPEG (به شکل data:image/jpeg;base64,…) پذیرفته می‌شود، tool_choice و تنظیمات جداگانه در response.create اثری ندارند، و conversation.item.truncate فقط تأیید می‌شود: پاسخ قطع‌شده در حافظهٔ گفت‌وگوی مدل کامل می‌ماند.
  • در Gemini Live دستور سیستمی، صدا و ابزارها را در همان اولین session.update بدهید. تغییرشان در میانهٔ جلسه هم پذیرفته می‌شود، ولی اتصال به مدل از نو برقرار می‌شود و ممکن است یک لحظه مکث بشنوید. پیام‌های conversation.item.create در Gemini Live فقط متن می‌پذیرند؛ صدا را با input_audio_buffer.append بفرستید.

از مدل‌های دیگر، هر مدل گفت‌وگوی فعالی که ورودی صوتی بپذیرد کار می‌کند. پیشنهاد ما qwen/qwen3.8-omni-flash است؛ شناسهٔ کاملش openrouter/qwen/qwen3.8-omni-flash است و نام کوتاه هم به همان مدل می‌رسد. مدلی که ورودی صوتی ندارد، پیش از باز شدن اتصال خطای model_not_realtime می‌گیرد. فهرست مدل‌ها در صفحهٔ مدل‌ها است.

نمونهٔ کامل: پاسخ‌گوی تلفنی با ثبت سفارش

این نمونه صدای تماس را با قالب A-law می‌فرستد و می‌گیرد، متن پاسخ را ثبت می‌کند، وقتی کاربر وسط حرف دستیار شروع به صحبت کند پخش را قطع می‌کند، و سفارش را با ابزار place_order ثبت می‌کند. شیء call نمایندهٔ خط تلفن در برنامهٔ شماست.

برای سرورها و کاربران داخل ایران، در این نمونه نشانی gisoo.pro را با ir.gisoo.pro جایگزین کنید؛ مسیر و کلید همان‌اند.

// npm install ws
import WebSocket from "ws";

const URL = "wss://gisoo.pro/api/v1/realtime?model=qwen/qwen3.8-omni-flash&codec=alaw";

const ws = new WebSocket(URL, {
  headers: { Authorization: `Bearer ${process.env.GISOO_API_KEY}` },
});

// A refused connection (bad key, no credit, wrong model…) is a plain HTTP response.
ws.on("unexpected-response", (req, res) => {
  let body = "";
  res.on("data", (chunk) => (body += chunk));
  res.on("end", () => console.error("refused:", res.statusCode, body));
});

ws.on("open", () => {
  ws.send(JSON.stringify({
    type: "session.update",
    session: {
      instructions: "You answer the phone for a pizza shop. Speak Persian, short and polite.",
      audio: { output: { voice: "alloy" } },
      tools: [{
        type: "function",
        name: "place_order",
        description: "Register the caller's order once items and address are confirmed.",
        parameters: {
          type: "object",
          properties: {
            items: { type: "array", items: { type: "string" } },
            address: { type: "string" },
          },
          required: ["items", "address"],
        },
      }],
    },
  }));

  // `call` is your telephony leg (e.g. Asterisk AudioSocket): raw A-law 8 kHz frames.
  call.on("audio", (frame) => {
    ws.send(JSON.stringify({ type: "input_audio_buffer.append", audio: frame.toString("base64") }));
  });
});

ws.on("message", async (data) => {
  const event = JSON.parse(data);

  switch (event.type) {
    case "response.output_audio.delta":
      call.play(Buffer.from(event.delta, "base64")); // already A-law: no conversion
      break;

    case "input_audio_buffer.speech_started":
      call.stopPlayback(); // the caller is talking over the answer
      break;

    case "response.output_audio_transcript.done":
      console.log("assistant:", event.transcript);
      break;

    case "response.function_call_arguments.done": {
      const args = JSON.parse(event.arguments);
      const result = await placeOrder(args); // your own code
      ws.send(JSON.stringify({
        type: "conversation.item.create",
        item: { type: "function_call_output", call_id: event.call_id, output: JSON.stringify(result) },
      }));
      ws.send(JSON.stringify({ type: "response.create" }));
      break;
    }

    case "error":
      console.error(event.error.code, event.error.message);
      break;
  }
});

ws.on("close", (code, reason) => console.log("closed", code, reason.toString()));

اتصال به Asterisk

AudioSocket و ExternalMedia در Asterisk صدای تماس را به شکل slin، alaw یا ulaw با ۸ کیلوهرتز می‌دهند. کافی است همان قالب را در نشانی بگویید: codec=alaw یا codec=ulaw، و برای slin مقدار codec=pcm8. آن‌وقت صدای تماس را بی‌تغییر می‌فرستید و صدای پاسخ را هم بی‌تغییر روی خط پخش می‌کنید؛ به تبدیل نرخ نمونه‌برداری یا قالب نیازی نیست. برنامهٔ میان Asterisk و این API (مثل نمونهٔ بالا) را خودتان می‌نویسید؛ ماژول آماده‌ای برای Asterisk نداریم.

تنظیم جلسه (session.update)

JSON session.update با همهٔ گزینه‌ها
{
  "type": "session.update",
  "session": {
    "output_modalities": ["audio"],
    "instructions": "You are the receptionist of a dental clinic. Speak Persian.",
    "audio": {
      "input": {
        "format": { "type": "audio/pcm", "rate": 16000 },
        "turn_detection": {
          "type": "server_vad",
          "threshold": 0.5,
          "prefix_padding_ms": 300,
          "silence_duration_ms": 500,
          "create_response": true,
          "interrupt_response": true
        }
      },
      "output": {
        "format": { "type": "audio/pcm", "rate": 16000 },
        "voice": "coral",
        "model": "gpt-4o-mini-tts",
        "instructions": "Warm, calm and unhurried."
      }
    },
    "tools": [],
    "tool_choice": "auto",
    "temperature": 0.7,
    "max_output_tokens": 1024,
    "reasoning": { "effort": "none" }
  }
}
output_modalities array
["audio"] (پیش‌فرض: پاسخ گفتاری و متن آن) یا ["text"] (فقط متن).
instructions string
دستور سیستمی، تا ۲۰٬۰۰۰ نویسه.
audio.input.format object
{"type":"audio/pcm","rate":8000|16000|24000} (شانزده‌بیتی little-endian، تک‌کاناله؛ پیش‌فرض ۲۴۰۰۰)، {"type":"audio/pcmu"} (G.711 μ-law، ۸ کیلوهرتز) یا {"type":"audio/pcma"} (G.711 A-law، ۸ کیلوهرتز). نام‌های نسخهٔ بتا (pcm16، g711_ulaw، g711_alaw) هم پذیرفته می‌شوند.
audio.output.format object
همان گزینه‌ها؛ اگر تعیین نکنید، خروجی همان قالب ورودی را دارد.
audio.input.turn_detection object | null
تشخیص خودکار پایان گفتار (server_vad، پیش‌فرض) با threshold بین ۰ و ۱ (پیش‌فرض ۰٫۵)، prefix_padding_ms (۳۰۰)، silence_duration_ms (۵۰۰)، create_response و interrupt_response (هر دو true). با null خودتان commit و response.create می‌فرستید.
audio.output.voice string
نام صدای گوینده؛ پیش‌فرض alloy. صداهای gpt-4o-mini-tts: alloy، ash، ballad، coral، echo، fable، nova، onyx، sage، shimmer، verse.
audio.output.model string
مدل گفتار از فهرست مدل‌ها؛ پیش‌فرض gpt-4o-mini-tts. مدل‌های Gemini TTS هم کار می‌کنند و فارسی را طبیعی‌تر می‌خوانند، ولی هر جمله حدود ۳ ثانیه دیرتر می‌رسد.
audio.output.instructions string
لحن و حال‌وهوای گوینده برای مدل گفتار، تا ۱۰۰۰ نویسه.
tools، tool_choice array، string | object
ابزارهای تابعی ({"type":"function","name","description","parameters"})، حداکثر ۶۴ ابزار و ۶۴ کیلوبایت. tool_choice: auto، none، required یا {"type":"function","name":"…"}.
temperature number
بین ۰ و ۲.
max_output_tokens integer | "inf"
بین ۱ و ۱۶٬۳۸۴، یا "inf".
reasoning object
افزودهٔ گیسو: {"effort":"none"|"low"|"medium"|"high"}. پیش‌فرض none است، چون فکر کردن مدل پیش از پاسخ چند ثانیه به شروع جواب اضافه می‌کند و کاربر آن را سکوت می‌شنود.

نوبت‌ها و قطع کردن حرف

با server_vad سرویس پایان حرف کاربر را تشخیص می‌دهد، صدا را commit می‌کند و پاسخ می‌سازد. اگر کاربر وسط ساخته شدن پاسخ شروع به حرف زدن کند، پاسخ لغو می‌شود (interrupt_response) و رویداد input_audio_buffer.speech_started می‌رسد. پخش صدایی را که پیش‌تر گرفته‌اید باید خودتان قطع کنید. اگر بخواهید مدل بداند کاربر تا کجای پاسخ را شنیده، conversation.item.truncate بفرستید:

JSON نگه داشتن فقط بخش شنیده‌شده
{"type": "conversation.item.truncate", "item_id": "item_7Kx2…", "content_index": 0, "audio_end_ms": 1800}

اگر نوبت‌ها را خودتان مدیریت می‌کنید (مثلاً با دکمه‌ای که کاربر هنگام حرف زدن نگه می‌دارد، یا Push-to-talk)، تشخیص خودکار را خاموش کنید:

JSON نوبت دستی
{"type": "session.update", "session": {"audio": {"input": {"turn_detection": null}}}}

{"type": "input_audio_buffer.append", "audio": "<base64 audio>"}
{"type": "input_audio_buffer.append", "audio": "<base64 audio>"}
{"type": "input_audio_buffer.commit"}
{"type": "response.create"}

برای پاسخ فقط متنی، یا فرستادن متن به‌جای صدا:

JSON حالت متنی
{"type": "session.update", "session": {"output_modalities": ["text"]}}

{"type": "conversation.item.create", "item": {
  "type": "message", "role": "user",
  "content": [{"type": "input_text", "text": "ساعت کاری شما تا کی است؟"}]
}}
{"type": "response.create"}

فراخوانی ابزار (Function Calling)

ابزارها را در session.update تعریف می‌کنید. وقتی مدل ابزاری را صدا بزند، آرگومان‌هایش در response.function_call_arguments.done می‌رسد. تابع خودتان را اجرا کنید (مثلاً سفارش را ثبت کنید)، نتیجه را با conversation.item.create و {"type":"function_call_output","call_id":…,"output":"…"} برگردانید (output یک رشتهٔ JSON است) و سپس response.create بفرستید تا مدل نتیجه را به کاربر بگوید. چرخهٔ ابزارها همان است که در فراخوانی ابزار آمده است.

رویدادها

رویدادهای کلاینت (شما می‌فرستید)

typeکار
session.updateتنظیم جلسه (بخش «تنظیم جلسه» در پایین). هر وقت لازم شد دوباره بفرستید.
input_audio_buffer.appendیک تکه صوت کاربر، base64 و با قالب ورودی جلسه.
input_audio_buffer.commitپایان نوبت کاربر؛ فقط وقتی تشخیص خودکار گفتار خاموش است لازم می‌شود.
input_audio_buffer.clearدور ریختن صوتی که هنوز commit نشده.
conversation.item.createافزودن پیام به گفت‌وگو: برای user با input_text یا input_audio، برای assistant و system با text؛ یا نتیجهٔ ابزار با type: function_call_output.
conversation.item.deleteحذف یک آیتم از گفت‌وگو.
conversation.item.retrieveگرفتن یک آیتم گفت‌وگو.
conversation.item.truncateوقتی کاربر وسط پاسخ حرف زد: فقط بخشی از پاسخ را که واقعاً شنیده (تا audio_end_ms) در گفت‌وگو نگه می‌دارد.
response.createگرفتن پاسخ از مدل.
response.cancelمتوقف کردن پاسخی که در حال ساخت است.

هر رویداد دیگری خطای unsupported_event می‌گیرد.

رویدادهای سرور (شما می‌گیرید)

typeمعنا
session.created / session.updatedجلسه باز شد / تنظیمات تازه پذیرفته شد (تنظیمات کامل جلسه همراهش می‌آید).
input_audio_buffer.speech_started / speech_stoppedکاربر شروع به حرف زدن کرد / ساکت شد. با speech_started پخش صدای خودتان را قطع کنید.
input_audio_buffer.committed / clearedنوبت کاربر ثبت شد / بافر خالی شد.
conversation.item.added / done / deleted / retrieved / truncatedتغییرات آیتم‌های گفت‌وگو.
response.createdساخت پاسخ شروع شد.
response.output_item.added / doneیک آیتم خروجی (پیام یا فراخوانی ابزار) شروع شد / تمام شد.
response.content_part.added / doneیک بخش از محتوای پیام شروع شد / تمام شد.
response.output_audio.delta / doneصدای پاسخ، base64 و با قالب خروجی جلسه، در قاب‌های حدوداً ۲۰۰ میلی‌ثانیه‌ای.
response.output_audio_transcript.delta / doneمتن همان پاسخ گفتاری، هم‌زمان با نوشته شدنش.
response.output_text.delta / doneپاسخ متنی، وقتی output_modalities برابر ["text"] است.
response.function_call_arguments.delta / doneآرگومان‌های فراخوانی ابزار؛ در done، مقدار call_id، name و arguments کامل می‌آید.
response.doneپایان پاسخ با status (completed، cancelled، incomplete یا failed) و مصرف توکن.
errorخطا؛ جلسه باز می‌ماند مگر خود خطا بگوید بسته شده است.

محدودیت‌ها

موردسقف
یک پیام WebSocket۱ مگابایت
سرعت فرستادن صداحداکثر چهار برابر زمان واقعی
یک نوبت گفتار۶۰ ثانیه
حافظهٔ گفت‌وگو۲۰۰ آیتم آخر؛ از صدای کاربر فقط حدود ۲ مگابایت آخر به‌صورت صدا به مدل می‌رسد. صدای نوبت‌های قدیمی‌تر دیگر به مدل نمی‌رسد، ولی متن‌ها و پاسخ‌ها می‌مانند.
طول جلسهیک ساعت، یا ۱۲۰ ثانیه بدون هیچ پیامی از سمت شما
جلسه‌های هم‌زمان۱۰ جلسه برای هر حساب
  • هر نوبت پاسخ مثل یک درخواست معمولی حساب می‌شود: یکی از درخواست‌های هم‌زمان حساب و یکی از سقف درخواست در دقیقهٔ کلید را می‌گیرد (مدیریت هزینه و محدودیت‌ها).
  • سرور هر ۲۵ ثانیه ping می‌فرستد. کتابخانه‌های WebSocket خودشان جواب pong را می‌دهند و کاری لازم نیست.
  • اگر کلید را باطل کنید، جلسه‌های باز آن کلید حداکثر حدود ۳۰ ثانیه بعد بسته می‌شوند.

سرعت پاسخ

در اندازه‌گیری‌های ما با qwen/qwen3.8-omni-flash، متن پاسخ معمولاً ۳ تا ۴ ثانیه بعد از ساکت شدن کاربر شروع می‌شود و اولین تکهٔ گفتاری با gpt-4o-mini-tts حدود یک ثانیه بعد از آن می‌رسد. این عددها تضمینی نیستند و به طول گفت‌وگو، مدل و شلوغی سرویس‌دهنده بستگی دارند. مدل‌های گفتاری مستقیم (جدول «مدل‌ها») چون صدا را خودشان می‌شنوند و می‌سازند، این مکث را ندارند و برای تماس تلفنی پیشنهاد ما همین‌ها هستند. برای کوتاه‌تر شدن مکث، reasoning.effort را روی none بگذارید و در دستور سیستمی از مدل بخواهید کوتاه جواب بدهد.

هزینه

هزینهٔ اتصال زنده برای هر نوبت جدا از همان اعتبار حساب کم می‌شود: فراخوانی مدل یک ردیف است و هر تکهٔ گفتاری پاسخ یک ردیف جدا. همهٔ این ردیف‌ها با برچسب Realtime (WebSocket) و Speech و با هزینهٔ دقیق هر کدام در گزارش درخواست‌های اپ دیده می‌شوند.

در مدل‌های گفتاری مستقیم هر اتصال یک ردیف است: هنگام باز شدن اتصال مبلغی از اعتبار حساب کنار گذاشته می‌شود، در طول گفت‌وگو هر وقت لازم باشد بیشتر می‌شود و وقتی اتصال بسته شد فقط مصرف واقعی (توکن‌های صدا و متن ورودی و خروجی) کم می‌شود و بقیه آزاد می‌شود. این ردیف بعد از بسته شدن اتصال با برچسب Realtime (WebSocket) در همان گزارش دیده می‌شود. اگر اعتبار در میانهٔ گفت‌وگو تمام شود، پیش از بسته شدن اتصال یک رویداد error با کد insufficient_credit می‌رسد.

حریم خصوصی

صدا و متن گفت‌وگو را ذخیره نمی‌کنیم. مثل هر درخواست دیگر API، از هر نوبت فقط شمار توکن‌ها و هزینه‌اش ثبت می‌شود.

خطاها

پیش از باز شدن اتصال (پاسخ HTTP)

codeHTTPمعنا و راه رفع
missing_api_key401هدر Authorization یا X-API-Key فرستاده نشده.
invalid_api_key401کلید نادرست است.
api_key_revoked401کلید باطل شده، منقضی شده یا غیرفعال است.
ip_not_allowed403IP سرور شما در فهرست IPهای مجاز کلید نیست.
model_not_realtime400مدل ورودی صوتی ندارد؛ یک مدل گفت‌وگوی صوتی (مثل qwen/qwen3.8-omni-flash) انتخاب کنید.
insufficient_credit402اعتبار حساب کافی نیست؛ اعتبار را شارژ کنید.
realtime_session_limit429حساب شما ۱۰ جلسهٔ باز دارد؛ پیش از اتصال تازه یکی را ببندید.
too_many_connections429از یک IP در یک دقیقه بیش از حد اتصال تازه باز شده؛ کمی صبر کنید و دوباره وصل شوید.
invalid_codec400مقدار codec یکی از alaw، ulaw، pcm8، pcm16 یا pcm24 نیست.

در طول جلسه (رویداد error)

JSON رویداد خطا
{"type": "error", "error": {"type": "invalid_request_error", "code": "conversation_already_has_active_response", "message": "…", "param": null, "event_id": "evt_…"}}
codeمعنا و راه رفع
unsupported_eventنوع رویداد پشتیبانی نمی‌شود (فهرست رویدادهای کلاینت را ببینید).
invalid_audio_formatقالب صوتی در session.update معتبر نیست.
input_audio_buffer_commit_emptyبافر خالی را commit کرده‌اید.
input_audio_buffer_too_largeیک نوبت گفتار از ۶۰ ثانیه بیشتر شده.
audio_rate_exceededصوت سریع‌تر از چهار برابر زمان واقعی فرستاده شده.
conversation_already_has_active_responseپاسخ قبلی هنوز تمام نشده؛ صبر کنید یا response.cancel بفرستید.
speech_failedتبدیل یک تکه از پاسخ به گفتار ناموفق بود؛ متن آن در transcript هست.
session_closedجلسه بسته شد (یک ساعت گذشته، ۱۲۰ ثانیه پیامی نیامده، یا کلید باطل شده).
server_restartسرویس در حال به‌روزرسانی است؛ چند ثانیه بعد دوباره وصل شوید.

فهرست کامل کدهای خطای API در صفحهٔ خطاها است.

پاسخ پرسشتان را پیدا نکردید؟

شناسهٔ درخواست (هدر X-Request-Id) را با پرسشتان در تیکت بفرستید تا دقیق بررسی کنیم.

تیکت پشتیبانی