أخطاء
فهم استجابات أخطاء واجهة برمجة التطبيقات، وأكواد إغلاق WebSocket، وكيفية التعامل معها
تنسيق أخطاء REST API (HTTP)
عند حدوث خطأ في نقطة نهاية HTTP قياسية، ترجع واجهة برمجة التطبيقات استجابة JSON بالهيكل التالي:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "وصف للخطأ مقروء للبشر",
"details": {
// سياق إضافي (يختلف حسب نوع الخطأ)
}
}
}
تنسيق أخطاء WebSocket (WSS)
تتعامل الـ WebSockets مع الأخطاء بشكل مختلف. يمكن أن تحدث الأخطاء أثناء المصافحة الأولية للاتصال، أو في منتصف البث أثناء توليد الصوت.
- أخطاء فادحة: يتم قطع الاتصال بكود إغلاق محدد (مثلاً: 4290).
- أخطاء منتصف البث: يرسل الخادم إطار خطأ JSON بسيط قبل الإغلاق:
{"error": "رصيد غير كافٍ أثناء البث"}
أكواد الحالة وأكواد الإغلاق
أكواد حالة HTTP (REST)
| الحالة | المعنى | الوصف |
|---|---|---|
200 |
موافق | نجح الطلب |
400 |
طلب غير صالح | Parameter طلب غير صالحة أو طلب مشوه |
401 |
غير مصرح | مفتاح API مفقود أو غير صالح |
402 |
الدفع مطلوب | رصيد غير كافٍ لإكمال الطلب |
403 |
محظور | مفتاح API لا يملك الصلاحية لهذا الإجراء |
404 |
غير موجود | المورد المطلوب غير موجود |
409 |
تعارض | الطلب يتعارض مع الحالة الحالية (مثلاً: طلب HTTP متزامن) |
429 |
طلبات كثيرة جداً | تم تجاوز حد الاستخدام |
500 |
خطأ داخلي في الخادم | حدث خطأ ما من جانبنا |
أكواد إغلاق WebSocket (WSS)
| الكود | النوع | الوصف |
|---|---|---|
1000 |
إغلاق عادي | اكتمل البث بنجاح. |
3011 |
خطأ في التوليد | فشل توليد الصوت في واجهة برمجة التطبيقات المصدرية. أعد المحاولة. |
4001 |
المصادقة مفقودة | لم يتم توفير مفتاح API في ترويسة Authorization أثناء المصافحة. |
4002 |
فشلت المصادقة | مفتاح غير صالح، حساب غير نشط، رصيد أولي غير كافٍ، أو قيود على عنوان IP. |
4290 |
حد التزامن | لديك بالفعل اتصال TTS WebSocket نشط. الحد هو اتصال واحد لكل مستخدم. |
سيناريوهات الأخطاء الشائعة
1. غير مصرح / فشلت المصادقة
فشلت المصادقة بسبب مفتاح API مفقود أو غير صالح، أو قيود القائمة البيضاء لعنوان IP.
الأسباب الشائعة:
- ترويسة Authorization: Bearer مفقودة
- تنسيق مفتاح API غير صالح أو تم إلغاء المفتاح
- الاتصال من عنوان IP غير موجود في القائمة البيضاء لمفتاحك
2. رصيد غير كافٍ
حسابك لا يملك رصيداً كافياً لإكمال هذا الطلب.
- HTTP: يفشل فوراً قبل توليد الصوت.
- WebSocket: إذا نفد رصيدك في منتصف البث، يرسل الخادم
{"error": "رصيد غير كافٍ أثناء البث"}ويغلق الاتصال بشكل نظيف. الصوت الذي تم توليده قبل نفاد الرصيد سيتم تسليمه.
3. التزامن وحدود الاستخدام
تعالج مكنة طلبًا واحدًا لكل مستخدم في كل مرة لضمان الاستخدام العادل.تقوم منصة مكنه بمعالجة طلب واحد لكل مستخدم في المرة الواحدة لضمان الاستخدام العادل.
- HTTP 409: يتم حالياً معالجة طلب آخر من حسابك. انتظر حتى ينتهي.
- HTTP 429: لقد تجاوزت حد 60 طلباً في الدقيقة (RPM).
- WSS 4290: لقد حاولت فتح اتصال WebSocket ثاني بينما كان اتصالك الأول لا يزال نشطاً.
4. طلب غير صالح / بيانات خاطئة
Parameters الطلب غير صالحة، أو أنك تجاوزت حدود مقاطع النص.
- HTTP: مقول مفقودة مطلوبة (text, voice_id).
- WebSocket: إرسال مقطع نصي أكبر من 2000 حرف سيؤدي إلى
{"error": "المقطع كبير جداً. بحد أقصى 2000 حرف لكل مقطع."}.
التعامل مع الأخطاء في الكود
import requests
import time
def generate_speech(text, voice_id, api_key):
url = "https://moknah.io/api/v1/tts/generate"
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.post(url, json={"text": text, "voice_id": voice_id}, headers=headers)
if response.status_code == 200:
return response.content # بايتات الصوت
elif response.status_code == 402:
raise Exception("كردت غير كافٍ")
elif response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 5))
time.sleep(retry_after)
return generate_speech(text, voice_id, api_key) # إعادة المحاولة
elif response.status_code == 409:
time.sleep(5)
return generate_speech(text, voice_id, api_key) # إعادة المحاولة
else:
raise Exception(f"API error: {response.status_code}")
async function generateSpeech(text, voiceId, apiKey) {
const response = await fetch("https://moknah.io/api/v1/tts/generate", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ text: text, voice_id: voiceId })
});
if (response.ok) return await response.blob();
if (response.status === 429) {
const retryAfter = response.headers.get("Retry-After") || 5;
await new Promise(r => setTimeout(r, retryAfter * 1000));
return generateSpeech(text, voiceId, apiKey);
}
if (response.status === 409) {
await new Promise(r => setTimeout(r, 5000));
return generateSpeech(text, voiceId, apiKey);
}
const error = await response.json();
throw new Error(error.error?.message || "API Error");
}
const ws = new WebSocket('wss://moknah.io/api/v1/api/v1/tts/ws/', {
headers: { "Authorization": `Bearer ${apiKey}` }
});
// Handle Mid-Stream JSON Errors
ws.on('message', (data, isBinary) => {
if (!isBinary) {
const msg = JSON.parse(data.toString());
if (msg.error) {
console.error("Stream Error:", msg.error);
// e.g., "Insufficient credits during stream"
}
}
});
// Handle Fatal Close Codes
ws.on('close', (code, reason) => {
switch(code) {
case 1000:
console.log("Stream finished successfully.");
break;
case 4001:
case 4002:
console.error("Authentication failed. Check your API key.");
break;
case 4290:
console.error("Concurrency limit reached. Close other active streams.");
// Wait a few seconds before attempting to reconnect
setTimeout(reconnect, 5000);
break;
case 3011:
console.error("Upstream generation failed. Please try again.");
break;
default:
console.error(`Disconnected with code ${code}`);
}
});
لأخطاء 429 (HTTP) و409 (HTTP) و4290 (WSS)، قم بتنفيذ التراجع الأسي: انتظر ثانية واحدة، ثم ثانيتين، ثم 4 ثوانٍ، وهكذا. هذا يمنع إرهاق واجهة برمجة التطبيقات ويضمن نجاح طلبك بمجرد فك القفل.
للأسئلة أو المشكلات المتعلقة بواجهة برمجة التطبيقات، اتصل بنا على api@moknah.io.