دليل المستخدم مرجع الواجهة البرمجية (API)

تحويل الكلام إلى نص في الوقت الحقيقي

تحويل البث الصوتي المباشر إلى نص في الوقت الحقيقي باستخدام WebSockets

WSS wss://moknah.io/api/v1/stt/ws/

بث الصوت الخام إلى خوادمنا واستلام نسخ نصي ثنائي الاتجاه في الوقت الحقيقي. يستجيب الخادم بنتائج جزئية (نص مباشر أثناء حديث المستخدم) ونتائج نهائية (جمل مكتملة مع طوابع زمنية على مستوى الكلمة).

💳 عداد فوترة مسبق الدفع (83 نقطة / دقيقة)

نظرًا لأن البث مباشر وغير متوقع، نستخدم عدادًا مسبق الدفع. عند الاتصال، نحجز فورًا 83 نقطة (دفعًا للثانية الستين الأولى). عند قطع الاتصال، نحسب استخدامك الفعلي بدقة إلى الثانية ونعيد تلقائيًا الاعتمادات غير المستخدمة إلى حسابك!بما أن البث مباشر وغير متوقع، فإننا نستخدم عداداً مسبق الدفع. عند الاتصال، نقوم فوراً بحجز 83 نقطة (ثمن أول 60 ثانية). عند قطع الاتصال، نحسب استخدامك الفعلي بالثانية ونعيد النقاط غير المستخدمة تلقائياً إلى حسابك!

المصادقة والاتصال

يجب عليك مصادقة اتصال WebSocket الخاص بك. تعتمد الطريقة على بيئة العميل لديك:

  • متصفحات الواجهة الأمامية (Frontend): لا تدعم WebSockets القياسية في المتصفحات ترويسات HTTP المخصصة. يجب عليك تضمين مفتاح API كمعلمة استعلام (?api_key=YOUR_KEY).
  • الخلفية (Backend) / بايثون / Node.js: يمكنك استخدام ترويسة HTTP القياسية Authorization: Bearer YOUR_API_KEY.
معلمة الاستعلام إجراء مطلوب النوع الوصف
api_key مشروط نص (string) مفتاح API الخاص بمكنه. (مطلوب هنا إذا لم يتم تمريره عبر ترويسة Authorization).
language اختياري نص (string) كود اللغة المراد نسخها. القيمة الافتراضية ar-JO. الأكواد المدعومة تشمل ar-SA، ar-EG، en-US، إلخ.

مواصفات الصوت

⚠️ هام جداً: بيانات ثنائية خام فقط

لا ترسل ملفات صوتية مضغوطة (مثل .mp3، .m4a) أو ملفات .wav قياسية مع ترويسات عبر WebSocket. سيقوم الذكاء الاصطناعي بإخراج ضجيج عشوائي أو نصوص فارغة. يقبل WebSocket حصرياً إطارات Raw Binary PCM.

قبل إرسال الإطارات الثنائية عبر المقبس، تأكد من مطابقة بث الصوت تماماً للمواصفات التالية:

  • معدل العينة (Sample Rate): 16,000 هرتز (16 كيلو هرتز)
  • عمق البت (Bit Depth): عدد صحيح 16 بت (Int16)
  • القنوات: 1 (مونو)
  • حجم المقطع (Chunk Size): أرسل في مقاطع صغيرة (مثلاً: 100 مللي ثانية / 3200 بايت). سيتم رفض المقاطع التي تزيد عن 256 كيلو بايت.

استجابات الخادم (أحداث JSON)

بينما تقوم ببث الصوت الثنائي إلى الخادم، سيرد الخادم بشكل غير متزامن بإطارات نصية بتنسيق JSON.

نوع الحدث مثال للبيانات
نجاح الاتصال
يتم إرسالها فور نجاح المصادقة.
{"status": "connected", "message": "جاهز لبث الصوت..."}
نتيجة جزئية
يتم إرسالها باستمرار. تُستخدم لعرض ترجمة فورية حية أثناء الكتابة.
{"type": "partial", "text": "مرحبا بك في منصة"}
نتيجة نهائية
يتم إرسالها عند اكتمال الجملة. تتضمن طوابع زمنية.
{
  "type": "final",
  "text": "مرحبا بك في منصة مكنة.",
  "words": [
    {"word": "مرحبا", "start_time_ms": 150, "duration_ms": 300},
    {"word": "بك", "start_time_ms": 460, "duration_ms": 200}
  ]
}

إنهاء البث: When the user stops speaking, send a JSON text frame: {"command": "stop"} to safely close the connection and calculate the final refund.


مثال للتكامل

# pip install websockets pyaudio
import asyncio
import websockets
import json
import pyaudio
import sys

API_KEY = "YOUR_API_KEY"
URL = "wss://moknah.io/api/v1/stt/ws/?language=ar-SA"

# 16kHz, 16-bit, Mono (100ms chunks)
CHUNK = 1600

async def stream_live_microphone(ws):
    audio = pyaudio.PyAudio()
    stream = audio.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=CHUNK)

    print("🎤 Microphone is LIVE. Start speaking!")
    loop = asyncio.get_running_loop()

    try:
        while True:
            data = await loop.run_in_executor(None, stream.read, CHUNK, False)
            await ws.send(data)
            await asyncio.sleep(0.001)
    except asyncio.CancelledError:
        await ws.send(json.dumps({"command": "stop"}))
    finally:
        stream.stop_stream()
        stream.close()
        audio.terminate()

async def receive_transcriptions(ws):
    async for message in ws:
        data = json.loads(message)
        if data.get('type') == 'partial':
            sys.stdout.write(f"\r⏳ {data['text']}")
            sys.stdout.flush()
        elif data.get('type') == 'final':
            sys.stdout.write(f"\r✅ {data['text']}\n")
            sys.stdout.flush()

async def main():
    headers = {"Authorization": f"Bearer {API_KEY}"}
    async with websockets.connect(URL, additional_headers=headers) as ws:
        await asyncio.gather(
            asyncio.create_task(stream_live_microphone(ws)),
            asyncio.create_task(receive_transcriptions(ws))
        )

asyncio.run(main())
// 1. Connect to WebSocket
const ws = new WebSocket('wss://moknah.io/api/v1/stt/ws/?api_key=YOUR_API_KEY&language=ar-SA');

ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    if (data.type === 'partial') {
        console.log("Live:", data.text);
    } else if (data.type === 'final') {
        console.log("Final:", data.text);
    }
};

// 2. Capture Microphone Audio on Connection
ws.onopen = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });

    // Force 16kHz sample rate for the AudioContext
    const audioCtx = new AudioContext({ sampleRate: 16000 });
    const source = audioCtx.createMediaStreamSource(stream);
    const processor = audioCtx.createScriptProcessor(4096, 1, 1);

    processor.onaudioprocess = (e) => {
        if (ws.readyState === WebSocket.OPEN) {
            const float32Data = e.inputBuffer.getChannelData(0);

            // Convert Browser Float32 to Int16 PCM (Required by Server)
            const pcm16 = new Int16Array(float32Data.length);
            for (let i = 0; i < float32Data.length; i++) {
                pcm16[i] = Math.max(-1, Math.min(1, float32Data[i])) * 0x7FFF;
            }

            // Send binary PCM audio chunk to server
            ws.send(pcm16.buffer);
        }
    };

    source.connect(processor);
    processor.connect(audioCtx.destination);
};

// 3. Handle graceful shutdown
function stopRecording() {
    ws.send(JSON.stringify({ command: "stop" }));
}

أكواد قطع الاتصال والخطأ

إذا تم رفض الاتصال أو انقطع، سيتم إغلاق WebSocket بأحد هذه الأكواد المحددة:

كود الإغلاق الاسم الوصف
1000 NORMAL_CLOSURE انتهى البث بنجاح. تم تسجيل الاستخدام ورد النقاط بشكل مناسب.
4001 MISSING_API_KEY لم يتم توفير معلمة ?api_key= أو أنها غير صالحة.
4002 UNAUTHORIZED مفتاح API غير صالح، IP مقيد، أو رصيد غير كافٍ لبدء/مواصلة البث.
4009 PAYLOAD_TOO_LARGE لقد أرسلت جزءًا صوتيًا أكبر من 256 كيلوبايت. قم بالبث في مخازن مؤقتة أصغر.لقد أرسلت مقطعاً صوتياً أكبر من 256 كيلو بايت. قم بالبث في مخازن مؤقتة أصغر.
4290 CONCURRENT_LIMIT توجد اتصالات WebSocket نشطة كثيرة جداً لحسابك. الحد هو بث نشط واحد.
دعم واجهة برمجة التطبيقات (API)

للأسئلة أو المشكلات المتعلقة بواجهة برمجة التطبيقات، اتصل بنا على api@moknah.io.