الرابط الأساسي https://api.echonova.ai

المطورون

دليل البدء لتحويل النص إلى كلام

اعرض قائمة الأصوات، وحوّل جملة عربية واحدة إلى مقطع صوتي عبر نقطة النهاية المتزامنة، ثم احفظ الملف، وشغّل الطلب نفسه كمهمة غير متزامنة واستعلم عنها دوريًا حتى تكتمل.

في هذا الدليل تُجري أربعة استدعاءات: تعرض الأصوات، وتنشئ جملة عربية واحدة بنقطة النهاية المتزامنة، وتحفظ الملف الصوتي، ثم تشغّل الجملة نفسها كمهمة غير متزامنة وتستعلم عنها دوريًا حتى تكتمل. في النهاية يكون لديك طلب يعمل لكل مسار، وتعرف ما يعيده كل واحد منها.

ما تحتاج إليه

  • مفتاح API. راجع احصل على مفتاح API. يحتاج المفتاح إلى وصول إلى تحويل النص إلى كلام، أو ألا يكون مقيّدًا بأي خدمة.
  • الرابط الأساسي. يعرض التنبيه في أعلى هذه الصفحة المضيف الذي تستدعيه العينات. راجع الرابط الأساسي.
  • مساحة عمل فيها رصيد. تُخصم كل عملية إنشاء قبل أن تبدأ. راجع الرصيد.
  • cURL مع jq، أو Python 3 مع requests، أو Node 18 أو أحدث. تستخدم العينات YOUR_API_KEY في موضع السر.

الخطوات

الخطوة 1: اعرض الأصوات

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

curl https://api.echonova.ai/v1/text-to-speech/voices \
  -H "Authorization: Bearer YOUR_API_KEY"

تأتي الاستجابة داخل الغلاف المعتاد. يحتوي data.items على الأصوات، و data.total على عددها:

{
  "data": {
    "items": [
      {
        "id": "66e5ef3a9c1d2b4f8a7e6c01",
        "name": "ae_ahmed",
        "displayName": "Ahmed",
        "language": "ar",
        "gender": "Male"
      }
    ],
    "total": 1
  },
  "success": true,
  "statusCode": 200,
  "errorMessage": null
}

اختر صوتًا قيمة language فيه ar، واحتفظ بقيمة id الخاصة به. يسمّيه باقي هذا الدليل VOICE_ID. تُشرح الحقول في الأصوات والخيارات في تحويل النص إلى كلام.

الخطوة 2: أنشئ الكلام بشكل متزامن

أرسل النص ومعرّف الصوت إلى POST /v1/text-to-speech/sync. يتوقف الاستدعاء حتى يصبح المقطع الصوتي جاهزًا، ويعيد رابط الملف في الاستجابة نفسها. جملة العينة 41 حرفًا من عربية بلا حركات:

curl -X POST https://api.echonova.ai/v1/text-to-speech/sync \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "الطقس اليوم جميل والسماء صافية في المدينة",
    "voiceId": "VOICE_ID"
  }'

الاستجابة:

{
  "data": {
    "jobId": "66e5f0c2a1b2c3d4e5f60718",
    "status": "completed",
    "audioUrl": "https://storage.example.com/tts/tts-output.wav?X-Amz-Signature=...",
    "durationSeconds": 3.4,
    "creditsConsumed": 41
  },
  "success": true,
  "statusCode": 200,
  "errorMessage": null
}

لم تُرسل speed و cfg و numSteps و tashkeel، فطُبّقت القيم الافتراضية. للجملة 41 حرفًا، مع احتساب المسافات، لذا تكلّف 41 credits. راجع الرصيد للسعر.

الخطوة 3: احفظ المقطع الصوتي

audioUrl رابط موقّع إلى ملف WAV. اجلبه بطلب GET عادي دون header Authorization:

# AUDIO_URL is data.audioUrl from Step 2
curl -o speech.wav "$AUDIO_URL"

افتح speech.wav في أي مشغّل لتسمع الجملة.

تعامل مع audioUrl على أنه تعليمات تنزيل، لا عنوان تحتفظ به.

الموصى به

  • نزّل الملف عند وصول الاستجابة، واحفظه لديك، وقدّمه من خادمك.

الأقل فاعلية

  • أن تلصق audioUrl في صفحة أو رسالة ستُفتح لاحقًا، فتجده منتهي الصلاحية.

الرابط ينتهي. نزّل الملف عند استلام الاستجابة. إذا انتهت صلاحية الرابط، فاستدعِ GET /v1/text-to-speech/jobs/{jobId} بقيمة jobId من الاستجابة؛ كل استدعاء يعيد رابطًا جديدًا.

الخطوة 4: شغّل الطلب نفسه بشكل غير متزامن واستعلم عنه دوريًا

يقبل POST /v1/text-to-speech الجسم نفسه، لكنه يعيد معرّف المهمة فورًا. يُنتَج المقطع الصوتي في الخلفية. أرسل الطلب:

curl -X POST https://api.echonova.ai/v1/text-to-speech \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "الطقس اليوم جميل والسماء صافية في المدينة",
    "voiceId": "VOICE_ID"
  }'

تحمل الاستجابة معرّف المهمة وحالتها، وتكون الحالة processing بعد قبول المهمة:

{
  "data": {
    "jobId": "66e5f0c2a1b2c3d4e5f60718",
    "status": "processing"
  },
  "success": true,
  "statusCode": 200,
  "errorMessage": null
}

استعلم عن GET /v1/text-to-speech/jobs/{jobId} حتى تصبح status قيمة completed أو failed. يُحتسب كل استعلام من حد الطلبات البالغ 100 طلب كل 60 ثانية لكل مفتاح على تلك النقطة، لذا انتظر بضع ثوانٍ بين الاستدعاءات:

# JOB_ID is data.jobId from the request above
while true; do
  STATUS=$(curl -s https://api.echonova.ai/v1/text-to-speech/jobs/$JOB_ID \
    -H "Authorization: Bearer YOUR_API_KEY" | jq -r '.data.status')
  echo "$STATUS"
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then break; fi
  sleep 3
done
curl -s https://api.echonova.ai/v1/text-to-speech/jobs/$JOB_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

تبدو المهمة المكتملة هكذا. لاحظ أن كائن المهمة يسمّي المعرّف id، بينما الاستجابة التي بدأتها سمّته jobId:

{
  "data": {
    "id": "66e5f0c2a1b2c3d4e5f60718",
    "status": "completed",
    "text": "الطقس اليوم جميل والسماء صافية في المدينة",
    "voiceId": "66e5ef3a9c1d2b4f8a7e6c01",
    "audioUrl": "https://storage.example.com/tts/tts-output.wav?X-Amz-Signature=...",
    "durationSeconds": 3.4,
    "creditsConsumed": 41,
    "createdAt": "2026-09-15T10:21:04.512Z"
  },
  "success": true,
  "statusCode": 200,
  "errorMessage": null
}

ما دامت المهمة pending أو processing، لا يوجد audioUrl ولا durationSeconds في الكائن. عندما تصبح failed، يحمل error السبب، ويُعاد الرصيد إلى مساحة العمل. المهمة التي تبقى في processing لأكثر من 10 دقائق تُعلَّم failed خلال 15 دقيقة من POST، فتنتهي حلقة الاستعلام دائمًا. احفظ الصوت تمامًا كما في الخطوة 3.

بدل الاستعلام الدوري، سجّل نقطة نهاية Webhook واستقبل job.completed أو job.failed مع audioUrl نفسه. راجع إعداد Webhook وأحداث Webhook. الاستدعاءات المتزامنة لا تُصدر هذه الأحداث أبدًا.

ما تحصل عليه

  • ملف صوتي واحد لكل استدعاء، يُوصل إليه عبر audioUrl موقّع لمدة محدودة. يبقى الملف مرتبطًا بالمهمة، و GET /v1/text-to-speech/jobs/{jobId} يعيد رابطًا جديدًا في كل استدعاء.
  • مهمة لكلا المسارين. يُنشئها الاستدعاء المتزامن مكتملة فورًا؛ أما الاستدعاء غير المتزامن فينقلها عبر pending و processing، ثم إلى completed أو failed.
  • creditsConsumed في كل مهمة: العدد الدقيق للأرصدة المخصومة لذلك النص. تُعاد أرصدة المهمة الفاشلة.
  • GET /v1/text-to-speech/jobs يعرض مهام API في مساحة العمل، الأحدث أولًا، بواقع 20 في الصفحة افتراضيًا و 100 كحد أقصى. يرى هذه المهام أي مفتاح في مساحة العمل له وصول إلى تحويل النص إلى كلام، أيًا كان المفتاح الذي أنشأها. والمفتاح بلا ذلك الوصول يحصل على 403. و GET /v1/text-to-speech/jobs/{jobId} يعيد 404 لمهمة تنتمي إلى مساحة عمل أخرى.

الحدود

الحد القيمة ينطبق على
طول text من 1 إلى 500 حرف، بعد إزالة المسافات البيضاء من البداية والنهاية كلا النقطتين
speed من 0.5 إلى 2، الافتراضي 1 كلا النقطتين
cfg من 1 إلى 5، الافتراضي 2 كلا النقطتين
numSteps واحدة من 16 أو 32 أو 48 أو 64 أو 128، الافتراضي 48 كلا النقطتين
الطلبات 100 طلب كل 60 ثانية لكل مفتاح على كل نقطة كل الاستدعاءات، بما فيها الاستعلامات الدورية
المهام في كل صفحة limit من 1 إلى 100، الافتراضي 20؛ offset 0 أو أكثر، الافتراضي 0 GET /v1/text-to-speech/jobs

جدول الخيارات الكامل في الأصوات والخيارات في تحويل النص إلى كلام.

حل المشكلات

400 text must be shorter than or equal to 500 characters

حقل text تجاوز الحد. قسّم النص وأرسل استدعاءً واحدًا لكل جزء، أو استخدم النقطة غير المتزامنة لكل جزء.

400 Invalid identifier

voiceId أو jobId ليس معرّفًا صالحًا. استخدم قيمة id تمامًا كما أعادتها قائمة الأصوات أو استجابة المهمة.

404 Voice not found

لا يوجد صوت نشط بهذا المعرّف. اعرض قائمة الأصوات من جديد، فقد يُسحب صوت من القائمة.

404 TTS Job not found

معرّف المهمة غير معروف، أو المهمة تنتمي إلى مساحة عمل أخرى، أو أُنشئت من البوابة. يستطيع أي مفتاح API في مساحة العمل له وصول إلى تحويل النص إلى كلام قراءة مهامه عبر API.

403 This API key does not have access to Text-to-Speech services

المفتاح يقيّد الخدمات، وتحويل النص إلى كلام ليس من بينها. اضغط تعديل على المفتاح في البوابة، ثم امنح وصول إلى تحويل النص إلى كلام.

402 Insufficient subscription balance

رصيد مساحة العمل لا يغطي الخصم لهذا النص. لم يُنتج شيء. راجع الرصيد.

429 Monthly spending limit exhausted

حد الرصيد على المفتاح لهذه الدورة كان سيُتجاوز. ارفع الحد على المفتاح أو أزِله. هذا ليس حد معدل الطلبات؛ ذلك الـ429 يحمل header Retry-After ويُشرح في حدود معدل الطلبات.

503 Speech generation is temporarily unavailable. Please try again.

تعذّر توليد الكلام في هذا الطلب. يُعاد الرصيد. أعد المحاولة بعد انتظار قصير.

انتهت المهمة بالفشل

error في المهمة يحمل السبب، أو AI server generation failed إذا لم يُذكر سبب. يُعاد الرصيد. أعد الطلب؛ وإن فشل بالنص نفسه مرة أخرى، فاختصر النص أو جرّب صوتًا آخر.

انتهت المهمة بالفشل بسبب Job timed out

بقيت المهمة في processing لأكثر من 10 دقائق دون نتيجة. تُعلَّم failed مع error بقيمة Job timed out — AI server did not respond خلال 15 دقيقة من POST، ويُعاد الرصيد. أرسل الطلب من جديد.

الأسئلة الشائعة

أي نقطة نهاية أستخدم في تطبيقك المباشر؟

المتزامنة حين يكون شخص ينتظر الصوت، وغير المتزامنة مع Webhook للدفعات. راجع الاستدعاءات المتزامنة وغير المتزامنة.

ينتهي الرابط، لذا نزّل الملف فور حصولك عليه. كل استدعاء لـ GET /v1/text-to-speech/jobs/{jobId} يعيد رابطًا جديدًا.

هل أستطيع اختيار صيغة الصوت؟

لا. الملف بصيغة WAV.

هل أدفع ثمن المهمة الفاشلة؟

لا. يُعاد الرصيد عند فشل المهمة، و creditsConsumed يحتفظ بالمبلغ الذي خُصم وأُعيد.

هل أستطيع إرسال نص إنجليزي؟

استخدم صوتًا قيمة language فيه en، عندما تعرض قائمة الأصوات واحدًا منها. الصوت يحدد اللغة، و text يقبل أي سلسلة حتى 500 حرف.