🎙 Realtime API — Gerçek Zamanlı Sesli Konuşma
WebSocket üzerinden düşük gecikmeli sesli asistan. Ses girer, ses çıkar; arada yazıya çevirmeye gerek yok.
Realtime API, telefon santralinizle veya web uygulamanızla model arasında çift yönlü bir ses kanalı kurar. Kullanıcı konuşurken model dinler, sözü bittiğinde kendiliğinden yanıt üretir ve sesi parça parça geri gönderir. Klasik "kaydet, yazıya çevir, cevap üret, seslendir" zincirinde her adım sıraya girdiği için gecikme birikir; burada tek bağlantı üzerinden aktığı için kullanıcı cevabın başını çok daha erken duyar.
Ne zaman kullanmalı
Telefonda karşılama ve yönlendirme, çağrı merkezi ön eleme, sesli sipariş alma, araç içi asistan, engelli erişimi — kullanıcının konuşup anında cevap beklediği her yer.
Tek seferlik metin işleri, toplu üretim, uzun doküman analizi veya sesin önceden hazırlanıp saklandığı senaryolar için uygun değildir; onlar için /v1/chat/completions ve /v1/audio/generate daha ucuz ve basittir.
Bağlantı
/v1/realtime?model=openai/gpt-realtime-1.5
Standart bir WebSocket bağlantısıdır. API anahtarınızı Authorization başlığında gönderirsiniz, başka bir adım yoktur. Anahtarınız yalnızca bizde kalır; arka taraftaki sağlayıcı bilgileri istemciye hiçbir zaman gönderilmez.
GET /v1/realtime?model=openai/gpt-realtime-1.5 HTTP/1.1
Host: api.onysoft.com
Upgrade: websocket
Connection: Upgrade
Authorization: Bearer sk-ony-...Tarayıcı içinden doğrudan bağlanmayın: WebSocket API'si özel başlık göndermeye izin vermez ve anahtarınız istemciye düşer. Bağlantıyı kendi sunucunuzdan kurun, sesi kendi istemcinize oradan aktarın.
Olay Akışı
Bağlantı kurulduktan sonra her şey JSON olay mesajlarıyla yürür. Tipik bir tur şöyle işler:
- Bağlanırsınız; sunucu ilk mesaj olarak session.created gönderir.
- session.update ile ses formatı, ses tonu, konuşma sonu algılama ve transkripsiyon ayarlarını bildirirsiniz.
- Mikrofondan gelen sesi base64 kodlayıp input_audio_buffer.append ile parça parça akıtırsınız.
- Sunucu konuşmanın bittiğini algılar (server VAD), input_audio_buffer.speech_stopped gönderir ve yanıt üretmeye başlar.
- Yanıt sesi response.output_audio.delta olaylarıyla parça parça gelir; siz bunları çalarsınız.
- response.done olayı turu kapatır ve o turda tüketilen tokenları bildirir — faturalandırma buradan yapılır.
Oturum Ayarları
Bağlandıktan sonra göndereceğiniz ilk mesaj session.update olmalıdır. Aşağıdaki alanlar en çok kullanılanlardır:
| Alan | Açıklama | Öneri |
|---|---|---|
audio.input.format | Giriş sesi formatı. Telefon hattı için G.711, web için pcm16. | audio/pcmu |
audio.output.format | Çıkış sesi formatı. Girişle aynı olması gerekmez ama telefonda aynı tutmak en kolayı. | audio/pcmu |
audio.output.voice | Modelin sesi. marin kadın, cedar erkek tonlu; Türkçede ikisi de doğal okur. | marin |
audio.input.turn_detection | Konuşma sonu algılama. server_vad sessizliği sunucuda ölçer, create_response true ise yanıtı kendiliğinden başlatır. | server_vad |
audio.input.transcription | Kullanıcının söylediğinin yazıya dökülmesi. Kayıt tutmak veya CRM'e yazmak için gerekir. | whisper-1 / tr |
instructions | Modelin davranış talimatı. Dili, üslubu ve sınırları burada belirtin. | — |
max_output_tokens | Model bir turda en fazla kaç çıkış tokenı üretebilir. Maliyeti sınırlamak için kullanışlıdır. | 4096 |
{
"type": "session.update",
"session": {
"type": "realtime",
"audio": {
"input": {
"format": { "type": "audio/pcmu" },
"turn_detection": { "type": "server_vad", "create_response": true },
"transcription": { "model": "whisper-1", "language": "tr" }
},
"output": {
"format": { "type": "audio/pcmu" },
"voice": "marin"
}
},
"instructions": "Türkçe konuş. Kısa ve net yanıt ver.",
"max_output_tokens": 4096
}
}Ses Formatları
Yanlış format en sık karşılaşılan sorundur: ses gider ama karşı taraf gürültü duyar. Hattınıza uygun olanı seçin.
| Format | Nerede | Not |
|---|---|---|
audio/pcmu | Telefon (SIP/PSTN, G.711 µ-law) | Türkiye ve Kuzey Amerika telefon hatlarında yaygın. 8 kHz. |
audio/pcma | Telefon (G.711 A-law) | Avrupa telefon hatlarında yaygın. 8 kHz. |
audio/pcm (16-bit) | Web, mobil uygulama | 24 kHz, sıkıştırmasız. Ses kalitesi en yüksek olan seçenek. |
Sık Kullanılan Olaylar
Tam liste uzundur; günlük işte gereken olaylar bunlardır.
| Olay | Yön | Ne işe yarar |
|---|---|---|
session.update | Gönderilen | Oturum ayarlarını günceller. Bağlantıdan sonraki ilk mesaj olmalıdır. |
input_audio_buffer.append | Gönderilen | Ses parçası ekler. Ses base64 kodlanmış olarak gönderilir. |
response.create | Gönderilen | Yanıtı elle başlatır. server_vad kullanıyorsanız gerekmez. |
response.cancel | Gönderilen | Süren yanıtı keser. Kullanıcı modelin sözünü kestiğinde bunu gönderin. |
session.created | Gelen | Oturum hazır. İçinde geçerli ayarlar döner. |
input_audio_buffer.speech_started | Gelen | Kullanıcı konuşmaya başladı. Çalan sesi durdurmak için iyi bir işaret. |
input_audio_buffer.speech_stopped | Gelen | Kullanıcı sustu; model yanıt üretmeye başlıyor. |
response.output_audio.delta | Gelen | Yanıt sesinin bir parçası. Base64 çözülüp çalınır. |
conversation.item.input_audio_transcription.completed | Gelen | Kullanıcının söylediğinin yazıya dökülmüş hâli. |
response.done | Gelen | Tur bitti. usage alanında o turun token dökümü bulunur. |
error | Gelen | Bir şeyler ters gitti. error.message alanına bakın. |
Örnek
Bağlanan, ayarları gönderen ve gelen olayları işleyen en küçük çalışan örnek.
import WebSocket from "ws";
const ws = new WebSocket(
"wss://api.onysoft.com/v1/realtime?model=openai/gpt-realtime-1.5",
{ headers: { Authorization: "Bearer sk-ony-..." } } // anahtar SUNUCUDA kalir
);
ws.on("open", () => console.log("bagli"));
ws.on("message", (raw) => {
const e = JSON.parse(raw);
switch (e.type) {
case "session.created":
ws.send(JSON.stringify(sessionUpdate)); // ilk mesaj
break;
case "input_audio_buffer.speech_started":
stopPlayback(); // soz kesme
ws.send(JSON.stringify({ type: "response.cancel" }));
break;
case "response.output_audio.delta":
play(Buffer.from(e.delta, "base64"));
break;
case "response.done":
console.log("token:", e.response.usage); // faturalama bu
break;
case "error":
console.error(e.error.message);
}
});
// mikrofon sesini base64 kodlayip akit
ws.send(JSON.stringify({ type: "input_audio_buffer.append", audio: chunk.toString("base64") }));import json, base64, websocket
ws = websocket.create_connection(
"wss://api.onysoft.com/v1/realtime?model=openai/gpt-realtime-1.5",
header=["Authorization: Bearer sk-ony-..."],
)
while True:
e = json.loads(ws.recv())
if e["type"] == "session.created":
ws.send(json.dumps(session_update))
elif e["type"] == "response.output_audio.delta":
hoparlore_yaz(base64.b64decode(e["delta"]))
elif e["type"] == "response.done":
print(e["response"]["usage"]) # token dokumu
elif e["type"] == "error":
print("HATA:", e["error"]["message"])Söz Kesme (Barge-in)
Gerçek bir konuşmada kullanıcı modelin sözünü keser. Bunu doğru yönetmezseniz iki ses üst üste biner. Doğru davranış: input_audio_buffer.speech_started olayını aldığınız anda çalmakta olan sesi durdurun, kuyruğunuzu boşaltın ve response.cancel gönderin. server_vad açıkken sunucu yeni turu kendiliğinden başlatır.
Fonksiyon Çağırma
Asistanın sipariş sorgulaması, randevu açması veya CRM'e yazması gerekiyorsa session.update içinde tools tanımlarsınız. Model gerektiğinde response.function_call_arguments.done olayıyla çağrıyı bildirir; siz işlemi yapıp sonucu conversation.item.create ile geri verirsiniz, ardından response.create ile modelin devam etmesini sağlarsınız.
Süre ve Sınırlar
| Sınır | Değer | Açıklama |
|---|---|---|
| Sınır — oturum | 30 dakika | Bir oturumun azami süresi. Daha uzun görüşmelerde istemci yeniden bağlanmalı ve gerekiyorsa konuşma özetini yeni oturuma taşımalıdır. |
| idle | 10 dakika | Hiç veri akmayan bağlantı kapatılır. Normal bir görüşmede ses sürekli aktığı için tetiklenmez. |
| concurrency | Anlaşmaya bağlı | Eşzamanlı oturum sayısı için bizimle iletişime geçin. |
| access | Anahtar bazında | Realtime erişimi her anahtarda açık değildir; kapalıysa bağlantı 403 ile reddedilir. |
Faturalandırma
Ücretlendirme gerçek token kullanımına göredir. Oturum kapandığında o oturumda tüketilen giriş ve çıkış tokenları bakiyenizden düşülür; bağlantı süresi için ayrıca bir ücret alınmaz. Ses tokenları metin tokenlarından belirgin biçimde pahalıdır, çünkü bir saniyelik ses birkaç kelimelik metinden çok daha fazla token tutar.
Maliyeti düşürmek için: talimatı kısa tutun, max_output_tokens ile tur başına tavan koyun, uzun sessizliklerde bağlantıyı kapatın ve gereksiz yere açık oturum bekletmeyin.
Hata Kodları
| Kod | Anlamı | Ne yapmalı |
|---|---|---|
401 | Anahtar geçersiz, pasif veya süresi dolmuş. | Anahtarı panelden kontrol edin. |
402 | Bakiye yetersiz. | Bakiye yükleyip tekrar bağlanın. |
403 | Bu anahtar realtime modeli için yetkili değil. | Destek ekibinden erişim açtırın. |
502 | Sağlayıcıya bağlanılamadı. | Kısa bir bekleyip tekrar deneyin; sürerse bize bildirin. |
503 | Model veya sağlayıcı yapılandırılmamış. | Model adını kontrol edin. |
Sık Yapılan Hatalar
- Sesi base64 kodlamadan göndermek — sunucu çözemez, ses gitmemiş sayılır.
- Giriş ve çıkış formatını hattınıza uydurmamak; telefonda pcm16 kullanmak cızırtıya yol açar.
- Söz kesmeyi yönetmemek; model konuşurken kullanıcı araya girince iki ses üst üste biner.
- Oturumu 30 dakika sınırına kadar açık tutup yeniden bağlanmayı planlamamak.
- Anahtarı tarayıcıya gömmek. Bağlantıyı daima kendi sunucunuzdan kurun.