Realtime HTTP
اختر عمليات HTTP للصوت المكتمل أو المباشر المؤطر أو تحويل النص إلى كلام، وتعامل مع بثها بأمان.
عمليات /realtime/http/* هي API مباشرة للمنصة. لا يغلفها SDK 0.18.0.
استخدمها فقط من وقت تشغيل موثوق يستطيع حماية x-api-key، وفرض المهل، وتنفيذ
تأطير OpenAPI المتحقق منه.
1. اختر العملية وفق دورة حياة الدخل
| الدخل والنتيجة | الاختيار | وحدة الطلب | إشارة الاكتمال |
|---|---|---|---|
| اجتماع أو بودكاست أو أرشيف طويل أو كبير مكتمل | Batch REST، وليس عملية Realtime HTTP | ملف مكتمل واحد ثم الاستعلام عن العمل | حالات Batch: done أو failed أو cleared |
| وحدة محادثة واحدة مكتملة حساسة لزمن الاستجابة | POST /realtime/http/stt | ملف multipart/form-data واحد | استجابة NDJSON من نوع STTResponse مع is_final: true |
| صوت لا يزال يصل عندما تحتاج نصًا مباشرًا | POST /realtime/http/stt-stream | جسم واحد من ترويسة 18 بايت وPCM لكل طلب | يحدد سجل مرصود مع is_speech_final حد الكلام، ولا يكمل البث إلا سجل مرصود مع is_final |
| صوت لا يزال يصل عندما تحتاج خطًا زمنيًا للمتحدثين | POST /realtime/http/diarization-stream | جسم PCM مؤطر واحد لكل طلب متسلسل | سجل مرصود مع is_final: true؛ وقد يبقى ذيل مؤقت نشط |
| نص يجب تحويله إلى كلام | TTS عبر Socket.IO في SDK للخرج القابل للتشغيل؛ وHTTP المباشر لتسجيل البروتوكول فقط | طلب JSON واحد | اكتمال SDK؛ ولا يملك HTTP المباشر حد إطار يمكن اكتشافه عمومًا |
يبث النسخ Fast أسطر النتيجة، لكن دخله يظل ملفًا كاملاً واحدًا. وهو ليس وسيلة نقل لميكروفون مباشر.
2. جهّز المصادقة والمعرّفات والمهل
- احصل على
API_URLوAPI_KEYالخاصين بالبيئة من تدفق الوصول الموثق. لا تستنتج مضيفًا من بيئة أخرى. - أرسل
x-api-keyفي كل طلب من خلفية موثوقة. لا تستطيع شيفرة المتصفح أو الهاتف إبقاء بيانات الاعتماد هذه سرية. يحتاج المفتاح أيضًا إلى القدرة المخصصة: ASR الفوري لـFast وASR الحي، أو diarization لتدفق المتحدثين، أو TTS للتوليف. - أنشئ UUID صالحًا لـ
id. يضعه Fast STT في الاستعلام، ويضعه TTS في JSON، وتحمل الإطارات المباشرة بايتاته الخام الستة عشر. لا تعد استخدام UUID واحد إلا لطلبات البث المباشر نفسه. - ضع مهلة اتصال، ومهلة محدودة لكل طلب وقراءة، ومهلة كلية للعملية. تحقق من حالة HTTP قبل تحليل بث النجاح.
- اجمع NDJSON بين قراءات النقل ولا تقسم إلا عند السطر الجديد. قد تحتوي قراءة شبكة واحدة جزءًا من سطر أو عدة أسطر.
ينطبق API_PATH على عملاء Socket.IO ولا تستخدمه مسارات HTTP هذه.
3. أرسل وحدة مكتملة واحدة للنسخ Fast
أرسل UUID في id وملفًا مكتملاً واحدًا في حقل file متعدد الأجزاء. يطبق Fast
اختيار اللغة ونموذج ASR فقط:
| المحدد | القيم المقبولة |
|---|---|
language أو lang | en، ar، codeswitch، auto |
asr أو model | قيمة النموذج المنشورة على البروتوكول |
تسبق قيمة language غير الفارغة lang، وتسبق قيمة asr غير الفارغة
model. تستخدم اللغة المحذوفة أو auto والنموذج المحذوف إعدادات البيئة
الافتراضية. استخدم Batch عندما تحتاج إلى تمييز المتحدثين أو ITN أو التنقيح.
export REQUEST_ID="7f51f2c2-e7bc-41c8-a850-f848df2ddfc8"
curl -N --fail-with-body --connect-timeout 10 --max-time 120 \
"${API_URL%/}/realtime/http/stt?id=$REQUEST_ID&language=codeswitch&asr=bayan_cs_ar_en" \
-H "x-api-key: $API_KEY" \
-F "file=@turn.wav"تعيد HTTP 200 النوع application/x-ndjson. كل سطر غير فارغ كائن JSON واحد
مكتمل؛ مثلاً:
{"id":"7f51f2c2-e7bc-41c8-a850-f848df2ddfc8","seq":0,"transcription":"hello wor","words":[{"start_time":0.0,"end_time":0.45,"word":"hello"}],"is_final":false}
{"id":"7f51f2c2-e7bc-41c8-a850-f848df2ddfc8","seq":0,"transcription":"hello world","words":[{"start_time":0.0,"end_time":0.45,"word":"hello"},{"start_time":0.46,"end_time":0.9,"word":"world"}],"is_final":true}عالج السجلات بترتيب الوصول المرصود، واحتفظ بـseq للتشخيص فقط؛ فعقد Fast
العام الحالي لا يعرّف لها ترتيبًا أو تفرّدًا. عامل is_final: false كحالة
مؤقتة، ولا تنه حالة الطلب إلا بعد is_final: true. لا تعامل مقاطع قراءة HTTP
الخام كسجلات، ولا تفترض أن كل نص مؤقت يُلحق بما سبقه.
بعد بدء الناتج الجزئي، ينهي أي إخفاق لاحق بث HTTP 200 الجزئي من دون إلحاق
سجل JSON للخطأ. يكون انتهاء الاستجابة أو الإلغاء أو مهلة التطبيق من دون
is_final: true غير مكتمل وملتبس؛ ولا تعرّف العملية عقد إعادة، لذلك لا تعد
إرسال الصوت بلا تمييز.
4. أطّر ASR والتمييز المباشرين
تقبل العمليتان المباشرتان application/octet-stream. يحمل جسم كل طلب هذا
التخطيط:
استخدم UUID جديدًا غير صفري طوال العملية. اضبط بت البداية في أول طلب، ولا تضبط
أي علم في الطلبات الوسطية، واضبط بت النهاية في آخر طلب؛ واضبط العلمين لتدفق
من مقطع واحد، وأبق البتات المحجوزة صفرًا. يجب أن يحمل كل طلب صوتًا. يمكن إرسال
ملف مؤطر مثل frame.bin باستخدام --data-binary؛ وهو ليس ملف صوت بمفرده لأنه
يتضمن ترويسة التحكم ذات 18 بايت.
ابنِ إطارًا صالحًا
تنشئ هذه الأدوات المختبرة افتراضيًا تدفقًا من مقطع واحد، ولذلك تضبط علمي
الحدود معًا. لعدة مقاطع، أعد استخدام STREAM_ID، واضبط IS_FINAL=0 في المقطع
الأول، واضبط العلمين إلى 0 في المقاطع الوسطية، واضبط IS_FINAL=1 فقط في
المقطع الأخير.
import { randomUUID } from 'node:crypto';
import { readFile, writeFile } from 'node:fs/promises';
const languageBytes = {
ar: 0,
en: 1,
codeswitch: 2,
auto: 255,
} as const;
function uuidBytes(id: string): Uint8Array {
const hex = id.replaceAll('-', '');
if (!/^[0-9a-f]{32}$/i.test(hex) || /^0{32}$/.test(hex)) {
throw new Error('STREAM_ID must be a nonzero UUID');
}
return Uint8Array.from(hex.match(/.{2}/g)!, (byte) => Number.parseInt(byte, 16));
}
function frame(
id: string,
pcm16le: Uint8Array,
options: { language: keyof typeof languageBytes; isStart: boolean; isFinal: boolean },
): Uint8Array {
if (pcm16le.byteLength === 0 || pcm16le.byteLength % 2 !== 0) {
throw new Error('PCM16 payload must be nonempty and contain an even number of bytes');
}
const output = new Uint8Array(18 + pcm16le.byteLength);
output.set(uuidBytes(id), 0);
output[16] = (options.isStart ? 1 : 0) | (options.isFinal ? 2 : 0);
output[17] = languageBytes[options.language];
output.set(pcm16le, 18);
return output;
}
async function main(): Promise<void> {
const inputPath = process.argv[2] ?? 'chunk.pcm';
const outputPath = process.argv[3] ?? 'frame.bin';
const streamId = process.env.STREAM_ID ?? randomUUID();
const pcm = await readFile(inputPath);
// Defaults build a valid one-chunk stream. For a longer stream, reuse
// STREAM_ID and set only the boundary flags for each arriving PCM chunk.
const body = frame(streamId, pcm, {
language: 'codeswitch',
isStart: process.env.IS_START !== '0',
isFinal: process.env.IS_FINAL !== '0',
});
await writeFile(outputPath, body);
console.info({ streamId, bytes: body.byteLength, outputPath });
}
void main().catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
});
ASR المباشر
curl -N --fail-with-body --connect-timeout 10 --max-time 30 \
-X POST "${API_URL%/}/realtime/http/stt-stream" \
-H "x-api-key: $API_KEY" \
-H "content-type: application/octet-stream" \
--data-binary @frame.binأرسل طلب POST واحدًا لكل مقطع صوت مؤطر. تحتوي كل استجابة HTTP 200 صفرًا أو
أكثر من سجلات NDJSON ذات id وseq وtranscription وwords و
is_speech_final وis_final. وينهي أي فشل لاحق بث 200 الجزئي من دون إلحاق
سجل خطأ. اجمع البيانات عبر القراءات وحلل الأسطر المكتملة. يحدد
is_speech_final حد مقطع كلام مكتشفًا؛
ولا يكمل البث كله إلا سجل مرصود مع is_final: true. لا يثبته علم النهاية في
الطلب ولا انتهاء الاستجابة، بما في ذلك 200 فارغة. عامل seq كقيمة معتمة،
ووفّق النص المؤقت باستخدام id وترتيب الوصول المرصود كما هو موضح في
دليل دورة حياة Realtime.
لا يعرّف العقد العام ما إذا كان ينبغي تداخل طلبات POST للمقاطع أو إرسالها تتابعيًا. استخدم فقط نمط التنسيق المخصص لبيئتك، ولا تستنتج أمان التوجيه من تزامن HTTP العادي.
تنتهي نافذة الاستجابة العادية غير النهائية بعد ثانيتين مع الحفاظ على الجلسة. ويلغي إجهاض طلب POST أو انقضاء مهلة الاستجابة النهائية الجلسة. كما تنتهي صلاحيتها بعد 60 ثانية من دون صوت عميل مقبول أو استجابة من محرك الاستدلال.
المسار POST /realtime/http/realtime-asr مسار توافقي. ينبغي للعملاء الجدد
استخدام العملية الأساسية POST /realtime/http/stt-stream.
التمييز المباشر
curl -N --fail-with-body --connect-timeout 10 --max-time 30 \
-X POST "$API_URL/realtime/http/diarization-stream" \
-H "x-api-key: $API_KEY" \
-H "content-type: application/octet-stream" \
--data-binary @frame.binليس لهذه العملية معاملات استعلام أو نموذج متعدد الأجزاء أو محدد نموذج من
العميل. يجب أن يكون بايت اللغة 0 أو 1 أو 2 أو 255، لكن الخدمة تتجاهله
بعد التحقق. ضع علم النهاية على آخر إطار صوت حقيقي لأن إطار الإنهاء الفارغ غير
صالح. يعيد بث لم يستقبل إطار بدء حالة HTTP 400 مع
VALIDATION_REQUIRED_FIELD.
لا تُبقِ أكثر من طلب POST واحد قيد التنفيذ لكل UUID. التقط الصوت بالتزامن في طابور محدود، لكن استخدم مرسلاً واحدًا لتفريغه وإغلاق كل استجابة قبل إرسال الإطار التالي. قد تستبدل الطلبات المتزامنة للـUUID نفسه ملكية الاستجابة؛ ويمكن تشغيل تدفقات UUID المختلفة بالتزامن.
تحتوي كل استجابة HTTP 200 صفرًا أو أكثر من سجلات NDJSON ذات id و
final_segments وactive_segments وis_final. وينهي أي فشل لاحق بث 200
الجزئي من دون إلحاق سجل خطأ. اجمع إضافات final_segments غير المشاهدة لأن كل
مصفوفة إضافة خاصة بالسجل. استبدل
لقطة active_segments السابقة، ثم رتب الخط الزمني الموفق من المقاطع النهائية
والنشطة حسب start_time. تسميات المتحدثين نسبية لتدفق واحد وليست هويات،
والأزمنة نسبية إلى بدايته.
لا يكمل التدفق إلا سجل مرصود مع is_final: true. لا يثبته علم النهاية في
الطلب ولا 200 فارغة ولا EOF ولا مهلة الاستجابة. قد يحتفظ السجل النهائي بذيل
نشط غير فارغ؛ أبقه مؤقتًا ولا تحوله ضمنيًا إلى نهائي. تنتهي نافذة الاستجابة
العادية غير النهائية بعد ثانيتين مع الحفاظ على الجلسة. ويلغي إجهاض طلب POST أو
انقضاء مهلة الاستجابة النهائية الجلسة، وتنتهي صلاحيتها بعد 60 ثانية من دون
نشاط العميل أو محرك الاستدلال. لا يوجد عقد لإعادة المقاطع أو الاستئناف أو
idempotency. بعد فشل ملتبس، أغلق كل الاستجابات وعلّم الخط الزمني غير مكتمل
وتعافَ بـUUID جديد بدلاً من إعادة مقطع قديم.
5. اطلب TTS عبر HTTP مع مراعاة عقد الخرج
يتطلب جسم JSON قيمة id جديدة ونص text يحتوي بعد إزالة الفراغات على حرف
Unicode أو رقم واحد على الأقل. الحقول الاختيارية هي
model وvoice_id وvoice_references.
لاختيار صوت متوقع، أرسل voice_id واحدًا بصيغة UUID أو مرجعًا واحدًا يكون
audio فيه RIFF/WAVE بترميز base64 القياسي مع بيانات PCM16 أحادية غير فارغة،
ويكون text نصه. المحددان متنافيان. احصل على voice_id عبر listVoices() أو
list_voices() في SDK؛ ولا توجد عملية HTTP لسرد الأصوات. اضبط model على
nebula صراحة بدل الاعتماد على افتراضي النشر، الذي يرجع إلى nebula عند
غيابه.
curl --fail-with-body --connect-timeout 10 --max-time 120 \
-X POST "$API_URL/realtime/http/tts" \
-H "x-api-key: $API_KEY" \
-H "content-type: application/json" \
--data '{"id":"7f51f2c2-e7bc-41c8-a850-f848df2ddfc8","text":"Hello from HUMAIN Voice","model":"nebula"}' \
--output tts-frames.binتعيد HTTP 200 جسمًا متصلاً من النوع application/octet-stream:
تلحق الخدمة إطارًا نهائيًا حتى عندما لا يحمل ذلك الإطار PCM إضافيًا. لا يعرّف
العقد طول إطار أو فاصلاً. مقاطع قارئ HTTP هي مقاطع نقل ولا يُضمن تطابقها مع
حدود إطارات الخدمة، لذلك لا يمكن لعميل عام إزالة 17 بايت من كل قراءة بأمان.
الملف tts-frames.bin في المثال تسجيل للبروتوكول، وليس ملف PCM أو WAV قابلاً
للتشغيل.
إذا فشل التوليف بعد إرسال بايتات، فإن تدفق 200 الثنائي الجزئي ينتهي فقط: ولا
تُلحق أي بيانات JSON منظمة للخطأ. لذلك يترك غياب العلم النهائي القابل لتمييز
الحدود أو EOF مبكر أو انتهاء المهلة تسجيلًا غير مكتمل بلا تفسير داخل القناة، ولا
يمكن الإبلاغ بـJSON منظم إلا عن فشل يحدث قبل تثبيت الخرج. ويلغي إجهاض طلب HTTP
التوليف الجاري له وحده. تُبلَّغ أخطاء
النموذج والسعة والاستدلال في عملية HTTP المباشرة بالحالة 500 TTS_SYNTHESIS_FAILED
القابلة للإعادة؛ وقد تعيد البوابة 429 بصورة مستقلة. رفض سياسة المحتوى هو
400 TTS_INPUT_NOT_ALLOWED غير قابل للإعادة؛ غيّر النص بدل إعادة إرساله. وإذا
تعذر على جهة الإشراف اتخاذ قرار، يفشل التوليف بصورة مغلقة مع
503 TTS_MODERATION_UNAVAILABLE القابل للإعادة؛ فلا تبلغ عن فشل البنية التحتية
هذا بوصفه محتوى محظورًا. ولم يعد voice_id المُرسَل من العميل يُطوى في
TTS_SYNTHESIS_FAILED (SAU-2258): فـvoice_id غير القابل للتحليل هو
400 VALIDATION_INVALID_UUID، وvoice_id صالح البنية لكنه لا يحدد صوتًا متاحًا هو
400 TTS_VOICE_NOT_FOUND (كلاهما غير قابل للإعادة)؛ وصوت محلول بياناته المخزَّنة
ناقصة أو تالفة هو 500 TTS_VOICE_RESOLUTION_FAILED (غير قابل للإعادة)؛ وانقطاع
عابر لقاعدة البيانات/التخزين أثناء حل الصوت هو 503 SERVER_DEPENDENCY_FAILURE
(قابل للإعادة).
لم تعد مشكلات النص ومرجع الصوت تُطوى بهذه الطريقة. فالنص الذي يتجاوز الحد، ونص
المرجع الذي يتجاوز حده، وأكثر من مرجع واحد، ومقطع المرجع الأطول من حد المرجع
المضبوط في النشر، كلها 422 غير قابلة للإعادة؛ والمرجع الذي يتجاوز حجمه المفكوك الحد هو
413؛ وأما المرجع المشوه أو إرسال المحددين معًا أو مصفوفة voice_references
الفارغة الصريحة فهي 400 غير قابلة للإعادة. ويتم التحقق من جميعها قبل أي بحث عن
النموذج أو قبول أو محاسبة، ويحمل كل رفض للحد كائن data يسمي الحد وقيمته
المضبوطة والقيمة المرصودة. راجع
الأخطاء وحدود المعدل.
إلى أن يملك عميلك المباشر آلية غير ملتبسة لحدود الإطارات، استخدم TTS عبر Socket.IO في SDK ووصفة TTS إلى WAV لخرج قابل للتشغيل. لا تفترض صيغة خرج Socket.IO ذات 24 kHz لهذه العملية عبر HTTP ذات 16 kHz.
6. قيّد حالات الفشل ونظّف كل بث
- تحقق من حالة HTTP قبل اختيار محلل نجاح NDJSON أو الثنائي. قد تعيد بوابة
النشر
429، بينما قد تطوي الخلفيات الحالية فشل السعة إلى500قابلة للإعادة معASR_TRANSCRIPTION_FAILEDأوDIARIZATION_FAILEDأوTTS_SYNTHESIS_FAILED. عامل حالة كل طبقة وجسمها كدليل، ولا تستنتج حصة رقمية أو نافذة إعادة ضبط. - في
ErrorResponse، اتخذ القرار منcodeوretryableلا من صياغةerrorأوdetailأوmessage. - عند فشل بث مباشر أو انتهاء مهلته، أوقف إرسال الإطارات، وألغِ الطلب، وأغلق قارئ استجابته، وابدأ التعافي بـUUID جديد. استئناف الجلسة بعد الانقطاع غير موثق.
- تكون المهلة بعد إرسال الملف متعدد الأجزاء الكامل ملتبسة. لا يعرّف العقد إعادة idempotent، لذلك لا تكرر الطلب بلا تمييز.
- إذا انتهى عميل TTS القادر على تمييز الحدود من دون إطار نهائي، فافصل البايتات الجزئية عن الخرج المكتمل وأغلق الاستجابة. لا تستنتج الاكتمال من إغلاق الاتصال وحده.
طبّق إعادة محاولة محدودة فقط عندما يسمح الخطأ المنظم بذلك، وتكون العملية آمنة وفق سياسة تطبيقك، وتبقى المهلة الكلية. راجع الأخطاء وحدود المعدل.
7. انتقل إلى العقد وتحققات الإنتاج
ابدأ بأصغر طلب ممثل للعملية المختارة، وتحقق من إشارتها النهائية الموثقة. أبق مرجع OpenAPI المولد بجانب تنفيذك للمعاملات والمخططات والأخطاء الدقيقة، ثم اختبر المهل، والإطارات غير الصالحة، والانقطاعات، والتنظيف قبل الإطلاق.