Gerçek zamanlı metinden konuşmaya (TTS)
Metni aşamalı olarak akıtın ve ham PCM veya MP3 ses baytlarını anında alın.
Gerçek zamanlı metinden konuşmaya (TTS) akışı için çift yönlü bir WebSocket bağlantısı kurar. Metin parçalarını aşamalı olarak gönderin (LLM çıktıları için idealdir) ve ikili (binary) ses akışlarını kesintisiz olarak alın. Kredi hesaplaması, HTTP uç noktasıyla aynı şekilde yapılır.
Ultra düşük gecikme süresi (~200 ms İlk Bayt Süresi) elde etmek için, metin parçalarınızın kesin noktalama işaretleriyle (nokta ., ünlem ! veya soru işareti ؟) bittiğinden emin olun. Yapay zeka, kusursuz ve insani bir tonlama sağlamak amacıyla, bir cümle sınırını tespit edene kadar metni doğal bir şekilde arabelleğe alır.
Kimlik Doğrulama
WebSocket el sıkışması sırasında Authorization başlığını kullanarak kimlik doğrulaması yapın:
Authorization: Bearer YOUR_API_KEY
Bağlantı Kurulumu
Bağlantı kurduktan sonra, istediğiniz yapılandırmayı içeren bir başlatma mesajı gönderin:
{
"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
}
}
Başlatma Parametreleri
| Parametre | Gerekli | Tür | Açıklama |
|---|---|---|---|
| type | gerekli | ip | Başlatma mesajı için "init" olmalıdır. |
| voice_id | gerekli | tam sayı | ...-dan gelen ses kimliği ses listesi. |
| output_format | isteğe bağlı | ip | İstenen ses formatı. Varsayılan değer pcm_24000’dir. Seçenekler şunlardır:
|
| prerecording | isteğe bağlı | tam sayı | 1 (normal, varsayılan) veya 2 (yapay zeka iyileştirmesi). Kredi maliyetini etkiler. |
| voice_settings | isteğe bağlı | nesne | Ses özelleştirme seçenekleri. Aşağıdaki Ses Ayarları bölümüne bakın. |
Ses Ayarları Nesnesi
| Parametre | Tür | Menzil | Varsayılan | Açıklama |
|---|---|---|---|---|
| temperature | tam sayı | 0 – 100 | 25 | Düşük = istikrarlı ve öngörülebilir, Yüksek = yaratıcı ve çeşitli. |
| similarity | tam sayı | 0 – 100 | 100 | Konuşmanın, orijinal ses klonuyla ne kadar örtüştüğü. |
| speed | yüzmek | 0.5 – 2.0 | 1.0 | Oynatma hızı çarpanı. |
| fast_mode | tam sayı | 0, 1, or 2 | 0 |
Gecikmeyi önemli ölçüde azaltır.
|
Akış İşlem Hattı
1. Metin Parçaları Gönder
LLM’niz metni oluşturdukça, metni kademeli olarak gönderin:
{"type": "text", "data": "مرحبا بكم."}
Sunucu, veri parçasını anında işleyecek, ilgili süreye karşılık gelen kredileri düşecek ve ses akışını geri göndermeye başlayacaktır.
2. Tamamlama Sinyali (Dur)
Metin oluşturma işleminiz tamamen bittiğinde, durdurma sinyalini gönderin:
{"type": "stop"}
Sunucu, arabelleğindeki kalan metni sentezlemeyi tamamlayacak, son ses baytlarını size iletecek ve Akış Sonu sinyalini gönderecektir.
Mesaj Alma
Sunucu, WebSocket üzerinden iki tür çerçeve gönderir:
1. İkili Ses Parçaları (PCM / MP3)
Ham ses baytları, oluşturuldukları anda akış olarak iletilir. Format, talep ettiğiniz `output_format` değerine bağlıdır (varsayılan olarak 24kHz’de 16-bit PCM kullanılır). Eğer MP3 talep ettiyseniz, bu baytları doğrudan bir dosyaya yazabilirsiniz.
2. JSON Kontrol Mesajları
Başlatma Hazır:
{"status": "ready", "message": "Başlatıldı ve metin almaya hazır."}
Akış Sonu (Güvenli Kapatma Sinyali):
{"type": "end_of_stream"}
Bu mesajı aldığınızda, ses parçalarının %100’ünün teslim edildiği matematiksel olarak garanti edilir. Artık istemci tarafında WebSocket bağlantısını güvenle kapatabilirsiniz.
İşlem Sırasında Hata:
{"error": "Yayın sırasında yetersiz kredi"}
Canlı Ortama Hazır Örnekler
# 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"}
Kodları ve Hataları Kapat
WebSocket bağlantısı, bu standart kodlardan biriyle kapanabilir:
| Kod | Tür | Açıklama |
|---|---|---|
1000 |
BAŞARI | Akış doğal bir şekilde tamamlandı. |
3011 |
OLUŞTURMA_HATASI | Üst API’de ses oluşturma başarısız oldu. İsteği yeniden deneyin. |
4001 |
API_ANAHTARI_EKSİK | Authorization başlığında API anahtarı sağlanmadı. |
4002 |
Kimlik doğrulama başarısız | Geçersiz anahtar, etkin olmayan hesap, yetersiz başlangıç kredisi veya IP kısıtlaması. |
4290 |
EŞ ZAMANLILIK SINIRI | Kullanıcının halihazırda aktif bir TTS WebSocket bağlantısı bulunuyor. Kullanıcı başına sınır 1’dir. |
API ile ilgili soru veya sorunlarınız için bizimle şu adresten iletişime geçin: api@moknah.io.