Gerçek zamanlı konuşmadan metne dönüştürme (STT)
WebSockets kullanarak canlı ses akışını gerçek zamanlı olarak metne dönüştürün.
Ham ses verisini sunucularımıza aktarın ve çift yönlü, gerçek zamanlı dökümler alın. Sunucu; kısmi sonuçlar (kullanıcı konuşurken anlık metin) ve nihai sonuçlar (kelime düzeyinde zaman damgaları içeren tamamlanmış cümleler) ile yanıt verir.
Yayınlar canlı ve öngörülemez nitelikte olduğundan, ön ödemeli bir kullanım sistemi kullanıyoruz. Bağlantı kurulduğu anda, (ilk 60 saniyenin ücretini karşılayacak şekilde) 83 krediyi hemen rezerve ediyoruz. Bağlantıyı sonlandırdığınızda ise kullanımınızı saniyesi saniyesine hesaplıyor ve kullanılmayan kredileri otomatik olarak hesabınıza iade ediyoruz!
Kimlik Doğrulama ve Bağlantı
WebSocket bağlantınızın kimlik doğrulamasını yapmalısınız. Yöntem, istemci ortamınıza bağlıdır:
- Frontend Tarayıcıları: Standart tarayıcı WebSocket’leri özel HTTP başlıklarını desteklemez. API anahtarınızı bir sorgu parametresi (?api_key=YOUR_KEY) olarak eklemelisiniz.
- Backend / Python / Node.js: Standart HTTP başlığı olan Authorization: Bearer YOUR_API_KEY’i kullanabilirsiniz.
| Sorgu Parametresi | Gerekli | Tür | Açıklama |
|---|---|---|---|
| api_key | Koşullu | ip | Moknah API anahtarınız. (Authorization başlığı aracılığıyla iletilmediği takdirde burada gereklidir). |
| language | İsteğe bağlı | ip | Transkripsiyonu yapılacak dil kodu. Varsayılan değer ar-JO’dur. Desteklenen kodlar arasında ar-SA, ar-EG, en-US vb. yer alır. |
Ses Özellikleri
WebSocket üzerinden sıkıştırılmış ses dosyaları (.mp3, .m4a gibi) veya başlık (header) içeren standart .wav dosyaları göndermeyin. Aksi takdirde yapay zeka rastgele gürültü veya boş dizeler üretecektir. WebSocket yalnızca ham ikili (raw binary) PCM karelerini kabul eder.
Soket üzerinden ikili (binary) çerçeveler göndermeden önce, ses akışınızın şunlarla tam olarak eşleştiğinden emin olun:
- Örnekleme Hızı: 16.000 Hz (16 kHz)
- Bit Derinliği: 16-bitlik tamsayı (Int16)
- Kanallar: 1 (Mono)
- Parça Boyutu: Küçük parçalar halinde gönderin (ör. 100 ms / 3200 bayt). 256 KB’tan büyük parçalar reddedilecektir.
Sunucu Yanıtları (JSON Olayları)
Sunucuya ikili (binary) ses akışı gönderdiğinizde, sunucu JSON metin çerçeveleriyle asenkron olarak yanıt verecektir.
| Etkinlik Türü | Yük Örneği |
|---|---|
|
Bağlantı Başarılı Başarılı kimlik doğrulamanın hemen ardından gönderilir. |
{"status": "connected", "message": "Ses akışına hazır..."} |
|
Kısmi Sonuç Kesintisiz olarak gönderilir. Canlı, yazılan altyazıları görüntülemek için kullanılır. |
{"type": "partial", "text": "Platforma hoş geldiniz"} |
|
Nihai Sonuç Bir cümle tamamlandığında gönderilir. Zaman damgaları içerir. |
{
"type": "final",
"text": "Makana platformuna hoş geldiniz.",
"words": [
{"word": "مرحبا", "start_time_ms": 150, "duration_ms": 300},
{"word": "بك", "start_time_ms": 460, "duration_ms": 200}
]
}
|
Yayın sonlandırılıyor: When the user stops speaking, send a JSON text frame: {"command": "stop"} to safely close the connection and calculate the final refund.
Örnek Entegrasyon
# 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" }));
}
Bağlantı Kesilmesi ve Hata Kodları
Bağlantı reddedilir veya kesilirse, WebSocket bu belirli kodlardan biriyle kapanacaktır:
| Kodu Kapat | İsim | Açıklama |
|---|---|---|
| 1000 | NORMAL_CLOSURE |
Yayın başarıyla sona erdi. Kullanım kaydı oluşturuldu ve gerekli iade işlemi yapıldı. |
| 4001 | MISSING_API_KEY |
?api_key= parametresi sağlanmadı veya geçersiz. |
| 4002 | UNAUTHORIZED |
Geçersiz API anahtarı, kısıtlanmış IP veya yayını başlatmak/sürdürmek için yetersiz kredi. |
| 4009 | PAYLOAD_TOO_LARGE |
256 KB’tan daha büyük bir ses parçası gönderdiniz. Daha küçük arabellekler kullanarak akış gerçekleştirin. |
| 4290 | CONCURRENT_LIMIT |
Hesabınızda çok fazla aktif WebSocket bağlantısı bulunuyor. Sınır, 1 aktif akıştır. |
API ile ilgili soru veya sorunlarınız için bizimle şu adresten iletişime geçin: api@moknah.io.