تحويل النص إلى كلام في الوقت الحقيقي
قم ببث النصوص تدريجيًا واستلم بايتات صوت PCM أو MP3 الخام فورًا
يقوم بإنشاء اتصال WebSocket ثنائي الاتجاه لبث تحويل النص إلى كلام في الوقت الحقيقي. أرسل مقاطع النص تدريجيًا (مثالي لمخرجات نماذج اللغة الضخمة) واستلم تيارات صوتية ثنائية باستمرار. يتم حساب النقاط بنفس طريقة نقطة نهاية HTTP.
لتحقيق زمن استجابة منخفض للغاية (~ 200 مللي ثانية لأول بايت)، تأكد من انتهاء مقاطع النص بعلامات ترقيم صريحة (نقطة .، علامة تعجب !، أو علامة استفهام ؟). يقوم الذكاء الاصطناعي طبيعيًا بتخزين النص مؤقتًا حتى يكتشف نهاية الجملة لضمان نبرة صوت بشرية مثالية.
المصادقة
قم بالمصادقة باستخدام ترويسة Authorization أثناء مصافحة WebSocket:
Authorization: Bearer YOUR_API_KEY
إعداد الاتصال
بعد الاتصال، أرسل رسالة تهيئة مع الإعدادات المطلوبة:
{
"type": "init",
"voice_id": 1710,
"prerecording": 1,
"output_format": "pcm_24000",
"voice_settings": {
"temperature": 25,
"similarity": 100,
"expressiveness": 0,
"speed": 1.0,
"fast_mode": 2
}
}
معلمات التهيئة
| Parameter | إجراء مطلوب | النوع | الوصف |
|---|---|---|---|
| type | مطلوب | نص (string) | يجب أن تكون "init" في رسالة التهيئة. |
| voice_id | مطلوب | عدد صحيح (integer) | معرف الصوت من قائمة الأصوات. |
| output_format | اختياري | نص (string) | صيغة الصوت المطلوبة. القيمة الافتراضية pcm_24000. الخيارات تشمل:
|
| prerecording | اختياري | عدد صحيح (integer) | 1 (عادي، افتراضي) أو 2 (تحسين بالذكاء الاصطناعي). يؤثر على تكلفة الرصيد.1 (عادي، افتراضي) أو 2 (تحسين بالذكاء الاصطناعي). يؤثر على تكلفة النقاط. |
| voice_settings | اختياري | كائن (object) | خيارات تخصيص الصوت. راجع قسم إعدادات الصوت أدناه. |
كائن إعدادات الصوت
| Parameter | النوع | النطاق | افتراضي | الوصف |
|---|---|---|---|---|
| temperature | عدد صحيح (integer) | 0 – 100 | 25 | أقل = مستقر وقابل للتنبؤ، أعلى = إبداعي ومتنوع. |
| similarity | عدد صحيح (integer) | 0 – 100 | 100 | مدى مطابقة الكلام لاستنساخ الصوت الأصلي. |
| speed | عدد عشري (float) | 0.5 – 2.0 | 1.0 | مضاعف سرعة التشغيل. |
| fast_mode | عدد صحيح (integer) | 0, 1, or 2 | 0 |
يقلل وقت الاستجابة بشكل كبير.
|
مسار البث
1. إرسال مقاطع النص
أرسل النص تدريجيًا كما يتم توليده من نموذج اللغة:
{"type": "text", "data": "مرحبا بكم."}
سيقوم الخادم بمعالجة المقطع فورًا، وخصم النقاط المحددة لهذا الطول، وبدء بث الصوت مرة أخرى.
2. إشارة الاكتمال (توقف)
عندما ينتهي توليد النص تمامًا، أرسل إشارة التوقف:
{"type": "stop"}
سيقوم الخادم بإنهاء توليف النص المتبقي في الذاكرة المؤقتة، وإرسال آخر بايتات الصوت إليك، ثم إرسال إشارة نهاية البث.
استقبال الرسائل
يقوم الخادم بدفع نوعين من الإطارات عبر WebSocket:
1. مقاطع صوتية ثنائية (PCM / MP3)
بايتات صوت خام يتم بثها بسرعة توليدها. تعتمد الصيغة على output_format المطلوب (الافتراضي PCM 16-بت بتردد 24 كيلوهرتز). إذا طلبت MP3، يمكنك كتابة هذه البايتات مباشرة في ملف.
2. رسائل تحكم JSON
جاهزية التهيئة:
{"status": "ready", "message": "تمت التهيئة وجاهز لاستقبال النص."}
نهاية البث (إشارة الإغلاق الآمن):
{"type": "end_of_stream"}
عند استلامك هذه الرسالة، فإن ذلك يضمن رياضيًا أنه قد تم تسليم 100% من مقاطع الصوت. يمكنك الآن إغلاق اتصال WebSocket بأمان من جانب العميل.
خطأ أثناء البث:
{"error": "رصيد غير كافٍ أثناء البث"}
أمثلة جاهزة للإنتاج
# pip install websockets
import asyncio
import websockets
import json
API_KEY = "YOUR_API_KEY"
url = "wss://api.moknah.io/api/v1/tts/ws/"
async def stream_tts():
headers = {"Authorization": f"Bearer {API_KEY}"}
async with websockets.connect(url, additional_headers=headers) as ws:
# 1. Initialize session (Requesting MP3 so we can save to file)
await ws.send(json.dumps({
"type": "init",
"voice_id": 1710,
"output_format": "mp3_44100_128",
"voice_settings": {"fast_mode": 2}
}))
print(f"Server: {await ws.recv()}")
# 2. Receiver Task
async def receive_audio():
with open("audio.mp3", "wb") as f:
async for msg in ws:
if isinstance(msg, bytes):
f.write(msg)
else:
data = json.loads(msg)
if data.get("type") == "end_of_stream":
print("✅ Stream finished safely.")
await ws.close()
break
receiver = asyncio.create_task(receive_audio())
# 3. Send Text
for chunk in ["مرحبا بكم.", "في منصة مُكنة."]:
await ws.send(json.dumps({"type": "text", "data": chunk}))
await asyncio.sleep(0.5)
# 4. Signal Stop
await ws.send(json.dumps({"type": "stop"}))
await receiver
asyncio.run(stream_tts())
// npm install ws
const WebSocket = require('ws');
const fs = require('fs');
const API_KEY = "YOUR_API_KEY";
const ws = new WebSocket('wss://api.moknah.io/api/v1/tts/ws/', {
headers: { "Authorization": `Bearer ${API_KEY}` }
});
const audioStream = fs.createWriteStream('audio.mp3');
ws.on('open', function open() {
// Requesting MP3 to safely write to an MP3 file
ws.send(JSON.stringify({
type: "init",
voice_id: 1710,
output_format: "mp3_44100_128",
voice_settings: { fast_mode: 2 }
}));
});
ws.on('message', function incoming(data, isBinary) {
if (isBinary) {
audioStream.write(data); // Save MP3 chunks
} else {
const msg = JSON.parse(data.toString());
if (msg.status === 'ready') {
console.log("Ready! Sending text...");
ws.send(JSON.stringify({ type: "text", data: "مرحبا بكم." }));
setTimeout(() => ws.send(JSON.stringify({ type: "text", data: "في منصة مُكة." })), 500);
setTimeout(() => ws.send(JSON.stringify({ type: "stop" })), 1000);
} else if (msg.type === 'end_of_stream') {
console.log("✅ All audio received. Closing connection.");
ws.close();
}
}
});
<?php
// composer require textalk/websocket
require 'vendor/autoload.php';
use WebSocket\Client;
$apiKey = "YOUR_API_KEY";
$client = new Client("wss://api.moknah.io/api/v1/tts/ws/", [
'headers' => ['Authorization' => "Bearer $apiKey"],
'timeout' => 60
]);
// 1. Initialize (Requesting MP3 format)
$client->text(json_encode([
"type" => "init",
"voice_id" => 1710,
"output_format" => "mp3_44100_128",
"voice_settings" => ["fast_mode" => 2]
]));
echo "Server: " . $client->receive() . "\n";
// 2. Send Text Chunks
$client->text(json_encode(["type" => "text", "data" => "مرحبا بكم."]));
$client->text(json_encode(["type" => "text", "data" => "في منصة مُكنة."]));
$client->text(json_encode(["type" => "stop"]));
// 3. Receive Audio & Control Messages
$audioFile = fopen("audio.mp3", "wb");
while (true) {
$message = $client->receive();
$decoded = json_decode($message, true);
if ($decoded && isset($decoded['type']) && $decoded['type'] == 'end_of_stream') {
echo "✅ Stream finished successfully.\n";
break;
} elseif (!$decoded) {
// If it can't be decoded as JSON, it's our binary MP3 audio chunk
fwrite($audioFile, $message);
}
}
fclose($audioFile);
$client->close();
?>
# Standard cURL does not support bidirectional WebSockets easily.
# Use 'websocat' to test WebSockets from the command line:
websocat wss://api.moknah.io/api/v1/tts/ws/ \
-H "Authorization: Bearer YOUR_API_KEY"
# Once connected, paste the JSON payloads interactively:
{"type": "init", "voice_id": 1710, "output_format": "mp3_44100_128"}
{"type": "text", "data": "مرحبا بكم."}
{"type": "stop"}
أكواد الإغلاق والأخطاء
قد يتم إغلاق اتصال WebSocket بأحد هذه الأكواد القياسية:
| الكود | النوع | الوصف |
|---|---|---|
1000 |
نجاح | اكتمل البث بشكل طبيعي. |
3011 |
خطأ في التوليد | فشل توليد الصوت في واجهة برمجة التطبيقات المصدرية. أعد المحاولة. |
4001 |
مفتاح API مفقود | لم يتم توفير مفتاح API في ترويسة Authorization. |
4002 |
فشل المصادقة | مفتاح غير صالح، حساب غير نشط، رصيد أولي غير كافٍ، أو قيود على عنوان IP. |
4290 |
حد التزامن | المستخدم لديه بالفعل اتصال TTS WebSocket نشط. الحد هو اتصال واحد لكل مستخدم. |
للأسئلة أو المشكلات المتعلقة بواجهة برمجة التطبيقات، اتصل بنا على api@moknah.io.