أدلة API

الأخطاء وحدود المعدل

صنّف نتائج الفشل، واحتفظ بالأدلة المنظمة، وأعد محاولة العمليات الآمنة ضمن حدود فقط.

عند أي فشل، احتفظ أولاً بالإشارة، وأوقف العمل المتأثر، وحدد هل النتيجة معلومة. لا تعد المحاولة إلا عندما تكون العملية آمنة للتكرار، وتسمح الحالة المنظمة بذلك، وتبقى مهلة للتطبيق.

1. صنّف موضع ظهور الفشل

السطحما تلاحظهالإجراء الأول
النقلفشل اتصال أو قراءة أو خمول أو انقطاع من دون استجابة منصةعامل النتيجة كمجهولة حتى يثبت عقد العملية أمان التكرار؛ أوقف وسيلة النقل المتأثرة وأغلقها
HTTPحالة غير 2xx وجسم ErrorResponse منظم غالبًااحتفظ بالحالة والجسم، ثم اتخذ القرار من code وretryable
Socket.IOحدث error منظم مع code وmessage وretryable وtimestamp وid اختياريأوقف تغذية الطلب أو البث الموجه قبل اتخاذ قرار التعافي
SDKاستثناء Batch ذو نوع، أو استدعاء Socket.IO منظم، أو رفض عام بعد الإسقاطاستخدم أغنى إشارة ذات نوع أو استدعاء متاح؛ لا تتخذ القرار من نص الاستثناء

غياب الاستجابة ليس مساويًا لـretryable: true. كما أن retryable: true المنظمة لا تكفي وحدها؛ فقد يظل تكرار الرفع أو البث المنقطع غير آمن أو ملتبسًا.

2. احتفظ بحقول HTTP وSDK

تستخدم عمليات Batch REST وHTTP المباشر المحمية شكل HTTP المسمى ErrorResponse:

الحقلالمعنى
errorمعرّف قديم؛ احتفظ به للتشخيص والتوافق
codeفئة قابلة للقراءة آليًا لاتخاذ قرار التطبيق
detailتفصيل بشري اختياري؛ لا تتخذ القرار من صياغته
messageرسالة قديمة اختيارية في بعض استجابات المصادقة
job_idUUID اختياري لعمل Batch أو تدفق Realtime HTTP مرتبط بالفشل
request_idمعرّف ارتباط اختياري لطلب Batch
retryableهل يصنف الخادم فشل هذا الطلب قابلاً لإعادة المحاولة
timestampتوقيت الخادم
dataدليل منظم اختياري للحد أو التحقق؛ احتفظ بحقوله ووحداته

يعني مثال Batch المتحقق منه هذا «صحح الجسم متعدد الأجزاء ولا تعده من دون تغيير»:

{
  "error": "error.api.error.multipart.file.missing",
  "code": "VALIDATION_REQUIRED_FIELD",
  "detail": "error.api.error.multipart.file.missing",
  "retryable": false,
  "timestamp": "2026-01-15T10:30:00Z"
}

تحقق دائمًا من حالة HTTP قبل اختيار محلل النجاح. احتفظ بالجسم الخام عندما يفشل التحليل المنظم.

يعرض SDK 0.18.0 إسقاطات مختلفة:

سطح SDKالمعلومات المنظمة
Batch في JavaScriptيعرض BatchTranscribeError القيم statusCode وpayload وcode وretryable وjobId وdetail وtimestamp وcapacity وrawBody؛ وتضيف أخطاء حد المعدل retryAfter
Batch في Pythonيعرض BatchTranscribeError القيم status_code وpayload وcode وretryable وjob_id وdetail وtimestamp وcapacity وraw_body؛ وتضيف أخطاء حد المعدل retry_after
استدعاءات Socket.IOيحتفظ ErrorResponse في SDK بالقيم الاختيارية id وmessage وcode وretryable وtimestamp وretry_after_seconds وdata وreason وretry_scope
رفض TTS بسبب خطأ الخادمترفض JavaScript بـError عام، وترفع Python RuntimeError عامًا؛ يحتفظ الرفض بالرسالة فقط، لذلك سجل الحقول المنظمة في onError / on_error
رموز حدود العمليحتفظ SDK 0.18.0 بالحقل data، ويصنف رموز الحدود الحالية، ويوجه الرفض الحامل للمعرّف إلى سياق الطلب النشط. يظل الاستدعاء العام يعمل أولًا، ثم يُرفض استدعاء التوليف بخطئه العام الذي يحتفظ بالرسالة فقط.
رموز سياسة محتوى TTSيصدر SDK 0.18.0 الثابتين TTS_INPUT_NOT_ALLOWED وTTS_MODERATION_UNAVAILABLE، ويصنفهما على أنهما مملوكان لـTTS، ويوجه الخطأ الحامل للمعرّف إلى سياق التوليف النشط

استمر في التحقق من دخل TTS قبل الإرسال، ومرّر دائمًا مهلة صريحة (timeoutSeconds في JavaScript وtimeout_seconds في Python). اقرأ code وdata من استدعاء الخطأ العام قبل رفض الطلب؛ فالاستثناء العام يحتفظ بالرسالة فقط.

3. طبّق جدول القرار

الحالة المرصودةتفسير النتيجةالإجراء
400 أو رمز تحققالطلب غير صالحصحح UUID أو المعاملات أو التأطير أو الملف أو الصوت؛ لا تعده من دون تغيير
401 أو رمز مصادقةالمفتاح مفقود أو غير صالحصحح بيانات الاعتماد قبل طلب آخر
403 مع AUTH_FORBIDDENقبلت المنصة المفتاح لكنه لا يملك القدرةحدّث الوصول عبر مسار إدارة المفاتيح في مؤسستك؛ لا تعد الطلب من دون تغيير
استجابة 403 أخرىرفضت بوابة أو طبقة وسيطة الطلباحتفظ بالجسم الخام أو معرّف الدعم، ثم تحقق من العنوان والمسار وبيانات الاعتماد وأي ترويسات خاصة بالنشر
404 / TRANSCRIPTION_JOB_NOT_FOUNDالمهمة المطلوبة غير متاحة تحت UUID ذلكأوقف الاستعلام عن UUID ذلك، وتحقق من المعرّف المخزن
405 / METHOD_NOT_ALLOWEDالمسار أو الطريقة خطأصحح التوجيه قبل طلب آخر
Realtime TTS 422 / CHARACTER_COUNT_EXCEEDEDالنص، أو نص مرجع الصوت، أطول من الحد المسموح. يحدد data.bound أيهما: tts_input_characters أو tts_voice_reference_text_charactersاختصر النص بالاستناد إلى data.limit، ولا تعد الطلب نفسه بلا تغيير
Realtime TTS 422 / VOICE_REFERENCE_COUNT_EXCEEDEDأكثر من عنصر واحد في voice_references؛ يُقبل عنصر واحد فقطأرسل مرجعًا واحدًا، ولا تعد الطلب نفسه بلا تغيير
Realtime TTS 422 / AUDIO_DURATION_EXCEEDED مع data.bound بقيمة tts_voice_reference_durationمقطع المرجع أطول من حد المرجع المضبوط في النشر، وقد يضبطه النشر أقل من حد النموذج نفسهاقتطع المقطع إلى data.limit ثانية — وdata.limit هي المرجع لا أي قيمة افتراضية منشورة، ولا تعد الطلب نفسه بلا تغيير
Realtime TTS 413 / PAYLOAD_TOO_LARGE مع data.bound بقيمة tts_voice_reference_bytesالحجم المفكوك لمقطع المرجع يتجاوز الحدأرسل مقطعًا أقصر أو بمعدل عينات أقل، ولا تعد الطلب نفسه بلا تغيير
TTS 400 / TTS_INPUT_NOT_ALLOWEDرفضت سياسة المحتوى النص؛ ولن يُقبل النص نفسهغيّر النص قبل إرسال طلب آخر، ولا تعده بلا تغيير
TTS 503 / TTS_MODERATION_UNAVAILABLEتعذر على جهة الإشراف على المحتوى اتخاذ قرار، فأوقف التوليف بصورة مغلقةلا تعامل الحالة كرفض لسياسة المحتوى. لا تعد المحاولة إلا بعد تراجع محدود وما دامت مهلة التطبيق باقية
402 / CREDITS_EXHAUSTEDنفد الرصيد ولا يمكن لإعادة فورية استعادتهأوقف العمل المتأثر ولا تعد الطلب من دون تغيير. يكون الحدث في منتصف تدفق Realtime طرفيًا ويتبعه فصل.
503 / BILLING_AUTHORIZATION_UNAVAILABLEلم تتمكن جهة الفوترة من اتخاذ قرار، فأخفقت المنصة بصورة مغلقةأوقف العمل المتأثر ولا تعده إلا بعد تراجع محدود. يكون الحدث في منتصف Realtime طرفيًا ويتطلب تدفقًا جديدًا.
Realtime ‏409 / ASR_STREAM_EXPIREDأنهى خمول الصوت أو فقد تسلسل الخلفية تدفق ASR هذااقرأ reason، وتحقق من retry_scope: "new_stream"، واحتفظ بالخرج المثبت، وابدأ UUID جديدًا؛ ولا تعِد الإطارات على المعرّف المنتهي.
422 في Batch مع رمز تحقق مثل VALIDATION_FILE_CORRUPTالملف غير مدعوم أو تالف أو فارغ أو بمدة صفريةصحح الدخل؛ لا تعد البايتات نفسها
422 / AUDIO_DURATION_EXCEEDED في Batch مع data.bound بقيمة audio_durationالصوت صالح لكن مدته المفكوكة أطول من المدة المقبولةقسّم التسجيل إلى data.limit ثانية أو أقل، أو أرسل ملفًا أقصر، ولا تعد الطلب نفسه بلا تغيير
422 / FILE_COUNT_EXCEEDED في Batchعدد الأجزاء أكبر مما يقبله الطلب الواحد. يحدد data.bound أيهما، ويبين data.unit وحدة العد: يعد file_parts الملفات الصوتية، ويعد multipart_parts كل أجزاء multipartمع file_parts أرسل data.limit ملفًا صوتيًا على الأكثر في الطلب؛ ومع multipart_parts ابقِ النموذج كاملًا داخل data.limit جزءًا، ولا تعد الطلب نفسه بلا تغيير
429 / RATE_LIMIT_EXCEEDED في Batchضغط سعة صريحضع عمليات الإرسال في طابور أو أبطئها، ثم استخدم سياسة إعادة محاولة محدودة
HTTP 5xx مع retryable: true في GET لنتيجة Batch استُدعي مع save_result=trueفشلت قراءة نتيجة محفوظةأعدها بتراجع محدود وjitter ما دامت المهلة باقية
HTTP 5xx مع retryable: true في رفعيدعو الخادم إلى الإعادة، لكن نتيجة الإنشاء قد تظل ملتبسةلا تكرر بلا تمييز؛ طبق سياسة صريحة لخطر التكرار
أي استجابة مع retryable: falseيطلب الخادم عدم إعادة حالة الطلب هذهتوقف حتى يتغير الدخل أو بيانات الاعتماد أو المسار أو الإعداد
مهلة قراءة قبل أي استجابةلا يوجد تصنيف من المنصةلا تعد إلا قراءة يحفظ عقدها النتيجة، وضمن المهلة فقط
خطأ أو انقطاع Realtimeقد تكون حالة البث القديم وحد الصوت المقبول ملتبسينتوقف، واحتفظ بالنتائج المثبتة، ونظف، وتعافَ بـUUID جديد إذا سمحت السياسة
خطأ حل voice_id في TTS (SAU-2258)voice_id المُرسَل من العميل الذي ليس UUID صالحًا هو 400 VALIDATION_INVALID_UUID؛ والصالح البنية لكنه لا يحدد صوتًا متاحًا هو 400 TTS_VOICE_NOT_FOUND (كلاهما غير قابل للإعادة). وصوت محلول بياناته المخزَّنة ناقصة أو تالفة هو 500 TTS_VOICE_RESOLUTION_FAILED غير قابل للإعادة؛ وانقطاع عابر لقاعدة البيانات/التخزين أثناء الحل هو 503 SERVER_DEPENDENCY_FAILURE قابل للإعادة. أما أخطاء النموذج/السعة/الاستدلال الحقيقية فتبقى 500 TTS_SYNTHESIS_FAILED قابلة للإعادةصحّح voice_id أو أرسل voice_references؛ وأعد محاولة 503 و500 TTS_SYNTHESIS_FAILED فقط مع تراجع، ولا تعد أبدًا محاولة الـ400 غير القابلين للإعادة ولا 500 TTS_VOICE_RESOLUTION_FAILED
خطأ TTS بقيمة 400 عند إرسال المحددين معًا أو مرجع مشوهإرسال voice_id مع voice_references غير فارغة، أو مصفوفة voice_references فارغة صريحة، أو صوت مرجع ليس base64 قياسيًا صارمًا بصيغة RIFF/WAVE أحادي القناة PCM16، هو خطأ تحقق غير قابل للإعادةفي SDK، اختر واحدًا بالضبط من voice_id أو عنصر voice_references قياسي واحد. يسمح HTTP المباشر بحذف المحددين لاختيار يعتمد على النشر. لا ترسل المحددين معًا.

قد تعيد بوابة النشر 429 لطلب Realtime HTTP، بينما قد تطوي خلفية Fast أو البث الحي الحالية فشل سعة الصوت الداخلي إلى 500 قابلة للإعادة مع ASR_TRANSCRIPTION_FAILED. لا تستنتج حصة Realtime أو مجموعة سعة أو نافذة إعادة ضبط من أي من الاستجابتين أو من سعة Batch.

4. عامل Batch 429 كضغط سعة

يتضمن 429 في Batch الحقول المنظمة المعتادة إضافة إلى data.capacity:

{
  "error": "error.rate_limit",
  "code": "RATE_LIMIT_EXCEEDED",
  "detail": "error.rate_limit",
  "retryable": true,
  "timestamp": "2026-01-15T10:30:00Z",
  "data": { "capacity": 120.5 }
}

capacity هي السعة المتبقية مقاسة بثواني الصوت. استخدمها لقرارات الطابور والقبول. وهي ليست حصة موثقة أو نافذة إعادة ضبط أو عدد ثوانٍ للانتظار.

لا يَعِد عقد OpenAPI بترويسة Retry-After. لا تُملأ retryAfter / retry_after في SDK إلا عندما توجد ترويسة صالحة فعلاً. عند غيابها، طبق تراجعًا أسيًا محدودًا مع jitter. قيّد دائمًا المحاولات، وكل تأخير، وزمن إعادة المحاولة الكلي، وتزامن المنتجين بمهلة كلية.

5. احفظ نتيجة Batch قبل إعادة قراءتها

لا يعيد SDK المنشور محاولات Batch. الخيار maxRetries / max_retries مهمل ومتجاهل ومحتفظ به للتوافق فقط. تعيد هذه الأمثلة المختبرة getResult() / get_result()، لا الرفع، وتمرر صراحة saveResult: true / save_result=True. قد تمسح القيمة الافتراضية false النتيجة النهائية بعد بناء الاستجابة، ولذلك قد تتبع الاستجابة المفقودة حالة cleared. يتيح خيار الحفظ إعادة محدودة لكنه لا يحدد مدة احتفاظ. تستخدم الأمثلة الخصائص ذات النوع المنشورة:

batch-error-retry.ts
import {
  BatchTranscribeClient,
  BatchTranscribeError,
  BatchTranscribeRateLimitError,
  Language,
  type TranscriptionResponse,
} from '@humain-voice/sdk';

function requiredEnv(name: 'API_KEY' | 'API_URL'): string {
  const value = process.env[name];
  if (!value) throw new Error(`${name} is required`);
  return value;
}

async function pause(milliseconds: number): Promise<void> {
  await new Promise<void>((resolve) => setTimeout(resolve, milliseconds));
}

async function getResultWithRetry(
  client: BatchTranscribeClient,
  jobId: string,
  attempts = 5,
): Promise<TranscriptionResponse> {
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
    try {
      // saveResult prevents a terminal read from clearing the stored result
      // before a retry. It does not establish a retention duration.
      return await client.getResult(jobId, Language.ArEn, { saveResult: true });
    } catch (error: unknown) {
      if (!(error instanceof BatchTranscribeError)) throw error;

      const rateLimited = error instanceof BatchTranscribeRateLimitError;
      const retryable = rateLimited || error.retryable === true;
      console.error({
        statusCode: error.statusCode,
        code: error.code,
        capacity: error.capacity,
      });
      if (!retryable || attempt === attempts) throw error;

      const serverDelayMs = rateLimited && error.retryAfter !== undefined
        ? error.retryAfter * 1_000
        : 0;
      const exponentialDelayMs = 500 * 2 ** (attempt - 1);
      await pause(Math.max(serverDelayMs, exponentialDelayMs) + Math.random() * 250);
    }
  }

  throw new Error('Retry loop exhausted');
}

async function main(): Promise<void> {
  const jobId = process.argv[2];
  if (!jobId) throw new Error('Pass a batch job ID as the first argument');

  const client = new BatchTranscribeClient({
    api_url: requiredEnv('API_URL'),
    api_key: requiredEnv('API_KEY'),
  });
  try {
    const result = await getResultWithRetry(client, jobId);
    console.info(result.status, result.results?.transcript ?? '');
  } finally {
    await client.close();
  }
}

void main().catch((error: unknown) => {
  console.error(error);
  process.exitCode = 1;
});

السلوك المتوقع: تستخدم القراءات القابلة للإعادة خمس محاولات على الأكثر، وتحترم قيمة retryAfter / retry_after فعلية عند وجودها، وتضيف تأخيرًا أسيًا وjitter، وتعيد إطلاق الفشل النهائي. لا يغني حد المحاولات عن مهلة كلية للتطبيق.

6. أبقِ العمليات الملتبسة خارج الإعادة الآلية

رفع الملفات الكاملة

لا يوثق إنشاء عمل Batch وإرسال الصوت الكامل عبر Fast عقد مفتاح idempotency. لا تثبت المهلة أو الانقطاع بعد إرسال البايتات النجاح أو الفشل؛ فقد يكون الخادم قبل الطلب.

إذا عاد jobId أو UUID للطلب، فاحتفظ به وتابع مسار النتيجة المعتاد لتلك العملية. ومن دون استجابة حاسمة، سجل المحاولة الملتبسة ولا تكرر إلا وفق سياسة تطبيق تقبل صراحة العمل المكرر.

بث Realtime

لا تعرّف عقود Socket.IO وHTTP العامة استئنافًا شفافًا ولا إعادة idempotent للإطارات. عند خطأ أو انقطاع:

  1. أوقف إرسال الصوت وأغلق البث أو الاستجابة القديمة.
  2. احتفظ بالنتائج المثبتة وتجاهل الحالة المؤقتة غير المحسومة.
  3. سجل فترة الصوت الملتبسة.
  4. أعد الاتصال بتراجع محدود وUUID جديد فقط إذا سمح الخطأ ومهلة التطبيق.
  5. افصل البث الجديد حتى يوفق التطبيق الخطين الزمنيين صراحة.

لا تعد الإطارات القديمة أو تستخدم UUID القديم بافتراض إزالة الخادم لتكرارها.

7. افصل المهل عن المهلة الكلية

التحكمما يقيّدهما يثبته الانتهاء
مهلة الاتصال أو الطلبمرحلة شبكة أو طلب واحدتوقف العميل عن الانتظار؛ لا تثبت هل نفذ الخادم أم لا
مهلة القراءة أو الخمولانتظار البايت أو المقطع أو الحدث التاليلم يصل تقدم في تلك الفترة؛ لا تثبت مدة العملية الكلية
مهلة انتظار Realtime النهائيالانتظار بعد إطار الدخل النهائيانتهى الانتظار؛ لا تثبت وصول نتيجة نهائية
مهلة التطبيق الكليةالاتصال والعمل والإعادات والتأخيرات والتنظيف معًايجب أن يوقف التطبيق مزيدًا من العمل

تكون قيمة timeoutSeconds في TTS لـJavaScript افتراضيًا 30 ثانية من الخمول أثناء انتظار كل مقطع صوت. لا يضع TTS في Python مهلة ما لم تمرر timeout_seconds. ينتظر close() في Realtime ASR SDK ‏is_final على مستوى البروتوكول أو خطأ موجهًا أو مهلة الإغلاق فقط، ويمكنه العودة عند انتهاء ذلك الانتظار. لا يغني أي من هذه الضوابط عن المهلة الكلية.

بعد أي انتهاء، نظف داخل finally: ألغِ قراءات HTTP وأغلق أجسام الاستجابة؛ وأوقف صوت Socket.IO واستدعِ disconnect() أو اخرج من سياق Python غير المتزامن؛ وأغلق عميل Batch. لا تستنتج أن تنظيف العميل ألغى العمل على الخادم. ولا تستنتج أنه ألغى توليف TTS جارٍ.

8. سجل القرارات واختبر مسارات الفشل

سجل العملية، ووسيلة النقل، وحالة HTTP أو اسم الحدث، وcode، وقرار إعادة المحاولة، وUUID للطلب أو العمل، ورقم المحاولة، والمهلة المتبقية، ونوع المهلة، وسعة Batch عند وجودها. لا تسجل مفاتيح API أو الصوت الكامل أو نصًا حساسًا افتراضيًا.

بعد ذلك، شغّل مثال القراءة الآمنة، ثم اختبر الدخل غير الصالح، والمصادقة، و429 الصريح، ومهلة القراءة، ومهلة رفع ملتبسة، وانقطاع Realtime، وانتهاء انتظار النتيجة النهائية، والتنظيف في بيئة اختبار معزولة.

في هذه الصفحة