تفرّغ واجهة API هذه الملفات الصوتية المكتملة إلى نصوص عبر مهام في قائمة انتظار. أرسل ملفا، واحتفظ بمعرّف المهمة الذي تتلقاه، واستعلم عن المهمة حتى تكتمل المعالجة. أرسل جميع الطلبات عبر HTTPS باستخدام بيانات اعتماد حسابك، إما بيانات HTTP Basic كما في الأمثلة أو رمز API، كما هو موضح في قسم المصادقة. احتفظ ببيانات الاعتماد على خادمك.
نقاط النهاية
يشترك خادما API، https://api.multi.tel وخادم التوافق https://api.multitel.net، في المهام ومفاتيح عدم التكرار والحدود والفوترة نفسها الخاصة بالحساب. ويختلفان في ترميز الرفع وغلاف الاستجابة، لذا استخدم خادما واحدا باستمرار مع محلّل يتوافق معه.
| العملية | الطريقة والمسار |
|---|---|
| معلومات الخدمة | GET /v3/speech_to_text |
| إرسال مهمة | POST /v3/speech_to_text |
| الحصول على تقدير دون إنشاء مهمة | POST /v3/speech_to_text/estimate |
| جلب مهمة | GET /v3/speech_to_text/JOB_ID |
| سداد مهمة تنتظر الدفع | POST /v3/speech_to_text/JOB_ID/settle |
| الاستخدام | GET /v3/speech_to_text/usage |
على api.multi.tel، تتوفر جميع المسارات أيضا بالبادئة /v1/speech-to-text بدلا من /v3/speech_to_text، مثل POST /v1/speech-to-text/estimate. على api.multitel.net، استخدم مسارات /v3/speech_to_text.
تعرض استجابة معلومات الخدمة الحقول mode (batch), realtime (false), paidEnabled (ما إذا كان إرسال مهام مدفوعة جديدة مقبولا حاليا)، pricePerMinuteUsd (0.005), billingUnit (audio_second), maxAudioSeconds (7200) وmaxUploadBytes (26214400)، مع وصف موجز في description. جلب هذه المعلومات مجاني ويعمل أثناء تعطيل إرسال المهام المدفوعة؛ ولا يعيد 503 transcription_unavailable إلا عندما تكون الخدمة بأكملها غير متاحة.
إعداد ملف صوتي
استخدم ملفا صوتيا مكتملا لا يتجاوز حجمه 25 MiB (26,214,400 بايت) ولا تتجاوز مدته 2 ساعة (7,200 ثانية). عند الإرسال، يجب أن يُتعرّف على الملف كوسائط MP3 أو WAV أو Ogg أو FLAC أو MOV أو Matroska تحتوي على تدفق صوتي، وأن تكون المدة في بياناته الوصفية أكبر من الصفر ولا تتجاوز 7,200 ثانية. يُرفض الملف الذي يُتعرّف عليه ولا يجتاز هذه الفحوص باستجابة 422 unsupported_audio. أما الملف الذي لا يمكن قراءته بأي من هذه الصيغ فقد يُرفض حاليا بخطأ خادم (500) بدلا من ذلك؛ لا تعِد إرسال هذا الملف دون تعديله. امتداد الملف وحده لا يثبت التوافق.
اجتياز هذه الفحوص لا يضمن إمكان فك ترميز الصوت. يُعالج الصوت كقناة واحدة أو قناتين. ينتهي الملف الذي يحتوي على أكثر من قناتين صوتيتين، أو الذي تتجاوز مدة صوته بعد فك الترميز 2 ساعة، أو أي ملف آخر يفشل فك ترميزه أثناء المعالجة، كمهمة بحالة failed، وعادة بالرمز decode_failed، ولا تُفرض عليه رسوم. حوّل الصوت متعدد القنوات إلى أحادي أو ثنائي القناة قبل إرساله.
تلميح اللغة الاختياري هو رمز اللغة المنطوقة من حرفين أو ثلاثة أحرف صغيرة، مثل en. لعدم تقديم تلميح، احذف الحقل؛ إذ يرفض api.multi.tel السلسلة الفارغة. يوجّه التلميح المعالجة، لكنه لا يُفحص مقابل قائمة باللغات المدعومة، لذا استخدم رمزا صالحا للغة المنطوقة.
إرسال مهمة تفريغ صوتي
أرسل JSON مع الترويسة Content-Type: application/json إلى POST https://api.multi.tel/v3/speech_to_text. يمكن أن يصل حجم جسم الطلب إلى 35 MiB، وهو ما يستوعب ملفا بالحجم الأقصى بعد ترميز base64؛ ويُرفض الجسم الأكبر باستجابة 413.
| الحقل | المعنى |
|---|---|
audioBase64 | مطلوب. الملف كاملا بترميز base64 القياسي (A–Z, a–z, 0–9, +, /) مع الحشو بالرمز = عند الحاجة. لا تضف بادئة data-URL أو فواصل أسطر أو مسافات، ولا تستخدم الأبجدية الآمنة لعناوين URL. يجب أن تُفك القيمة إلى ملف حجمه بين 1 بايت و25 MiB، وأن تنتج النص نفسه تماما عند إعادة ترميزها. |
language | تلميح لغة اختياري، كما هو موضح أعلاه. |
تُرفض أي خاصية JSON أخرى، بما فيها idempotency_key، باستجابة 400 invalid_transcription_request. أرسل المفتاح كترويسة.
مفتاح عدم التكرار
يتطلب كل إرسال ترويسة Idempotency-Key بطول من 1 إلى 190 حرفا. استخدم أحرف ASCII والأرقام و-, _, . و:، دون مسافات في البداية أو النهاية: يزيل خادم التوافق المحارف البيضاء المحيطة ويقيس المفتاح بالبايت، لذا قد يحسب كل خادم المحارف الأخرى بشكل مختلف. يُرفض المفتاح المفقود أو المكوّن من 191 حرفا أو أكثر باستجابة 400.
يقتصر نطاق المفاتيح على حسابك وعلى تحويل الكلام إلى نص، عبر كلا الخادمين وجميع بيانات اعتماد حسابك. تعيد إعادة إرسال المفتاح نفسه مع الملف واللغة نفسيهما المهمة الحالية باستجابة HTTP 200 وduplicate: true، مهما كانت حالتها وحتى إن جرى تحديث المعالجة منذ إنشائها، دون رسوم إضافية. تعيد إعادة استخدام مفتاح مع ملف أو لغة مختلفين 409 idempotency_conflict. ينشئ المفتاح الجديد مهمة جديدة حتى لملف مطابق، وتُفرض رسوم منفصلة إذا اكتملت المعالجة بنجاح.
API_USER="your-api-username"
API_PASSWORD="your-api-password"
node -e 'process.stdout.write(JSON.stringify({audioBase64:require("node:fs").readFileSync("completed-call.mp3").toString("base64"),language:"en"}))' > completed-call.json
curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: speech-call-001" \
--data-binary @completed-call.json \
-o speech-job.json \
https://api.multi.tel/v3/speech_to_text
node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).data.id'تعيد المهمة الجديدة HTTP 202 مع الحقول الموضحة أدناه، وتعيد إعادة الإرسال HTTP 200 مع كائن المهمة الكامل الموصوف في قسم قراءة النص المفرّغ. اقرأ معرّف المهمة، وهو UUID، من data.id. تبدو استجابة المهمة الجديدة كما يلي (المعرّف والقيم أمثلة):
{
"status": "success",
"data": {
"id": "3f6c1b2e-8a4d-4e7f-9c21-5b0d7e4a9f13",
"status": "queued",
"mode": "batch",
"realtime": false,
"source": "api",
"durationSeconds": 90.5,
"billedSeconds": 91,
"costUsd": "0.007583334",
"pricePerMinuteUsd": "0.005"
}
}عندما تكون المهمة في قائمة الانتظار أو قيد التنفيذ، تكون durationSeconds, billedSeconds وcostUsd تقديرات مستندة إلى البيانات الوصفية للملف. تعتمد الرسوم النهائية على المدة بعد فك الترميز.
قد يعيد الإرسال أيضا 402 insufficient_balance عندما لا يكفي الرصيد المدفوع مسبقا لتغطية المهمة مع مهامك الأخرى غير المنجزة، و429 transcription_queue_full عندما يكون لدى حسابك أو الخدمة عدد كبير جدا من المهام غير المنجزة، و429 audio_validation_busy عند بلوغ سعة التحقق من الملفات، و503 paid_transcription_not_enabled أثناء تعطيل التفريغ الصوتي المدفوع. أعد محاولة الطلبات ذات الاستجابات 429 و503 لاحقا باستخدام المفتاح نفسه.
الحصول على تقدير دون إنشاء مهمة
أرسل جسم JSON نفسه إلى POST https://api.multi.tel/v3/speech_to_text/estimate. لا يلزم مفتاح عدم تكرار. يتحقق التقدير من الملف ويقيسه، لكنه لا يفرّغه إلى نص أو ينشئ مهمة أو يحجز أموالا أو يفحص رصيدك أو يفرض رسوما على حسابك. يُقبل تلميح language لكنه لا يؤثر في التقدير.
يعيد التقدير الناجح HTTP 200 مع estimate: true, charged: false, mode, realtime, durationSeconds, billedSeconds, pricePerMinuteUsd وcostUsd ضمن data. يستخدم المدة الموجودة في البيانات الوصفية للملف، بينما تُحسب رسوم المهمة المكتملة بناء على المدة بعد فك الترميز، التي قد تختلف. تخضع التقديرات لفحوص الملفات نفسها التي تخضع لها عمليات الإرسال. وهي متاحة فقط أثناء تفعيل التفريغ الصوتي المدفوع (وإلا فتعيد 503 paid_transcription_not_enabled). وقد تعيد 429 audio_validation_busy عند بلوغ سعة التحقق من الملفات؛ أعد المحاولة بعد انتظار قصير.
قراءة النص المفرّغ
استعلم دوريا من GET /v3/speech_to_text/JOB_ID كما هو موضح في دليل سير عمل المهام. يحتوي كائن المهمة على هذه الحقول:
| الحقل | المعنى |
|---|---|
id | معرّف UUID للمهمة. |
status | queued, running, completed, failed أو awaiting_payment. |
progress | نسبة مئوية من 0 إلى 99 أثناء التنفيذ، عند توفرها؛ و100 عند الاكتمال؛ وإلا null. |
durationSeconds, billedSeconds | مدة الصوت والثواني الكاملة التي تُحسب عليها الرسوم. تكون هذه تقديرات من البيانات الوصفية عندما تكون المهمة في قائمة الانتظار أو قيد التنفيذ، وتستخدم المدة بعد فك الترميز بمجرد اكتمال المهمة أو انتظارها الدفع. |
costUsd, costIsEstimate | التكلفة بالدولار الأمريكي كسلسلة عشرية ذات تسع خانات بعد العلامة العشرية. تكون قيمة costIsEstimate هي true عندما تكون المهمة في قائمة الانتظار أو قيد التنفيذ. لا تُفرض رسوم على المهمة الفاشلة، مع أن costUsd الخاص بها يظل يعرض التقدير. |
pricePerMinuteUsd | 0.005 لمهام API، و0.000 لمهام تسجيلات Hosted PBX المجانية. |
failureCode | للمهمة الفاشلة: decode_failed (تعذر فك ترميز الصوت، مثلا لأنه يحتوي على أكثر من قناتين أو لأن مدته بعد فك الترميز تزيد على 2 ساعة)، inference_timeout (استغرقت المعالجة وقتا طويلا جدا)، service_error أو worker_lease_lost (انقطعت المعالجة). كما أن الرمزين unsupported_audio وquality_check_failed معرّفان أيضا. تعرض المهمة التي تنتظر الدفع insufficient_balance، وقد يظل ظاهرا بعد سداد المهمة. |
source, modelVersion, createdAt | source تكون قيمته api لعمليات الإرسال عبر API، أو hpbx لمهمة تسجيل Hosted PBX تابعة لحسابك. modelVersion سلسلة معتمة تمثل إصدار المعالجة. createdAt وقت الإرسال. |
duplicate | true في الاستجابات التي تعيد مهمة موجودة. |
result | يوجد فقط عندما تكون قيمة status هي completed. |
| حقل النتيجة | المعنى |
|---|---|
text | النص المفرّغ بالكامل: نصوص جميع المقاطع موصولة بفواصل أسطر، بترتيب المقاطع. |
segments | مصفوفة مقاطع مرتبة حسب وقت البدء. يغطي كل مقطع جزءا من الصوت يصل طوله إلى نحو 29 ثانية. يحدد الحقلان start وend (بالثواني من بداية الصوت) ذلك الجزء، وليس الكلمات أو الجمل المنفردة، وقد تتداخل الأجزاء المتتالية بمقدار يصل إلى 1 ثانية. ويحتوي كل مقطع أيضا على text وlanguage (رمز لغة قد يكون فارغا)، إضافة إلى channel للنتائج ثنائية القناة. |
channelCount | 1 أو 2. يوجد في النتائج الحالية؛ وقد لا تتضمنه النتائج الأقدم. |
audioDurationMs | المدة بعد فك الترميز بالمللي ثانية. تُقرّب الفوترة هذه المدة إلى الأعلى إلى ثوان كاملة. |
qualityFlags | فارغ، أو review_recommended مع repetition_detected (تتكرر عبارة بمعدل مرتفع على نحو غير معتاد ضمن جزء من الصوت)، no_speech (لم يُفرّغ أي كلام إلى نص)، أو كلاهما. |
pipelineVersion | قد يظهر. معرّف معالجة معتم. |
تُنتج النصوص المفرّغة وطوابعها الزمنية وتسميات اللغة والقنوات آليا، ولا تُضمن دقتها. اعتبر أي علامة جودة سببا لمراجعة النتيجة، وقارن الأسماء والأرقام والالتزامات المهمة بالصوت الأصلي. تُتجاوز فترات الصمت الطويلة والأجزاء الخافتة جدا ولا تنتج عنها مقاطع. لا تحدد النتائج هوية المتحدثين الأفراد. عندما تعرض النتيجة قيمة channelCount تساوي 2، يحتوي كل مقطع على channel بقيمة A (القناة الأولى، أو اليسرى) أو B (القناة الثانية، أو اليمنى). لا يفصل هذا بين المتحدثين إلا عندما يُسجّل كل متحدث على قناة منفصلة. تُحسب رسوم الصوت ثنائي القناة مرة واحدة بناء على مدته المنقضية، وليس لكل قناة. لا تحتوي النتائج أحادية القناة على تسميات قنوات.
استخدام api.multitel.net
تقبل نقطة نهاية التوافق POST https://api.multitel.net/v3/speech_to_text تنسيق multipart/form-data مع جزء ملف باسم audio وحقل اختياري باسم language بدلا من JSON audioBase64. تُعامل قيمة language الفارغة كعدم تقديم تلميح. أرسل ترويسة Idempotency-Key نفسها. إذا غابت الترويسة، يقبل هذا الخادم أيضا حقل نموذج باسم idempotency_key. تُرفض الحقول المسماة source, free, billing_source, realtime أو stream باستجابة 400 unsupported_transcription_option؛ وتُتجاهل حقول النموذج الأخرى. يعيد هذا الخادم أيضا الأخطاء التالية:
- 400
idempotency_key_requiredلمفتاح مفقود أو طويل جدا. - 400
audio_upload_requiredلرفع مفقود أو لم يُستلم بالكامل. - 400
invalid_languageللغة غير صالحة. - 413
invalid_audio_sizeلملف فارغ أو أكبر من الحد المسموح. - 400
invalid_jobلمعرّف مهمة ذي تنسيق غير صحيح.
تستخدم استجابات خدمة تحويل الكلام إلى نص على هذا الخادم الغلاف {"status":{"code":HTTP_STATUS},"response":{...}}. لاحظ أن status كائن وليس سلسلة. عند النجاح، يحتوي response على الكائن نفسه الموجود في data على الخادم الأساسي، لذا يكون معرّف المهمة response.id. عند الخطأ، يحتوي response.code على رمز الخطأ؛ ولا تُدرج رسالة أو معرّف طلب. تُعاد أخطاء المصادقة (401) من فحص تسجيل الدخول العام للخادم، وقد يكون جسمها مختلفا، لذا افحص حالة HTTP قبل التحليل. لا تستخدم ترميز الرفع أو محلّل الاستجابة الخاص بأحد الخادمين مع الآخر.
للحصول على تقدير على هذا الخادم، أرسل حقول multipart نفسها بطريقة POST إلى /v3/speech_to_text/estimate. لا يلزم مفتاح عدم تكرار، ويوجد التقدير ضمن response.
API_USER="your-api-username"
API_PASSWORD="your-api-password"
curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
-H "Idempotency-Key: speech-call-001" \
-F "audio=@completed-call.mp3" -F "language=en" \
-o speech-job.json \
https://api.multitel.net/v3/speech_to_text
node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).response.id'