Selamlar, """ Speech output helpers. Single entr...
# ask-ai
a
Selamlar, """ Speech output helpers. Single entry point for speaking a provided message across both pipeline modes: - standard: session.say(...) - realtime: session.generate_reply(...) """ from livekit.agents import AgentSession def _is_realtime_session(session: AgentSession) -> bool: """Return True when session runs in realtime pipeline mode.""" agent = getattr(session, "_agent", None) return bool(agent and getattr(agent, "_pipeline_mode", "standard") == "realtime") async def speak_message( session: AgentSession, message: str, *, allow_interruptions: bool = True, add_to_chat_ctx: bool = False, wait_for_playout: bool = False, ) -> bool: """ Speak
message
through the active pipeline. - Standard pipeline: session.say(message, ...) - Realtime pipeline: session.generate_reply(instructions=...) Args: session: AgentSession instance. message: Text to speak. allow_interruptions: Users can interrupt. (Standard pipeline only) add_to_chat_ctx: Add to chat context. (Standard pipeline only) wait_for_playout: Wait for audio to finish playing before returning. Returns: True if the user interrupted, False otherwise. (Only meaningful when wait_for_playout=True) """ if _is_realtime_session(session): handle = session.generate_reply( instructions=f"Kullanıcıya şu mesajı söyle: {message}", ) else: handle = session.say( message, allow_interruptions=allow_interruptions, add_to_chat_ctx=add_to_chat_ctx, ) # await handle = playout bitene kadar bekle if wait_for_playout: await handle.wait_for_playout() return bool(getattr(handle, "interrupted", False)) """End call function tool.""" from livekit.agents import RunContext, StopResponse, get_job_context from livekit.agents.llm import function_tool from ..utils.logger import get_logger from ..utils.sip import hangup from ..utils.speech_output import speak_message logger = get_logger("end_call") @function_tool( name="end_call", description="Telefon görüşmesini sonlandır ve çağrıyı kapat. Kapanış mesajını closing_message parametresiyle belirt.", ) async def end_call(context: RunContext, closing_message: str) -> str: """Telefon görüşmesini sonlandır ve çağrıyı kapat. Kullanıcı 'hoşça kal', 'görüşürüz', 'kapat', 'bitir' gibi ifadeler kullandığında veya konuşma doğal olarak sonlandığında bu fonksiyonu çağır. Args: closing_message: Görüşmeyi kapatırken söylenecek veda/kapanış mesajı. Örneğin: "Yardımcı olabildiysem ne mutlu, iyi günler dilerim!" Returns: Görüşmeyi sonlandırma mesajı """ ctx = get_job_context() session = context.session logger.info(f"📴 Ending call - room: {ctx.room.name}, message: {closing_message}") # Kapanış mesajını söyle ve bitmesini bekle interrupted = await speak_message(session, closing_message, wait_for_playout=True) if interrupted: logger.debug( "🔄 Kapanış mesajı kesildi — kullanıcı konuşmaya devam etmek istiyor." ) return ( "Kullanıcı kapanış mesajını böldü, görüşme kapatılmadı. " "Kullanıcı konuşmaya devam etmek istiyor. Onu dinle ve yardımcı ol." ) logger.debug("✅ Closing speech completed, proceeding to hangup") # Mark call as agent-ended for reporting. current_agent = getattr(session, "current_agent", None) if current_agent: session_report = getattr(current_agent, "_session_report_service", None) if session_report: session_report.set_ended_by("agent") await hangup(ctx) raise StopResponse() Bu şekilde realtime modda generate_reply kullanmaya çalışıyorum ama bir türlü istediğimi yapamıyorum. İstediğim tek şey generate_reply verip istediğimi söyletebilmek ama beceremedim.
t
Thanks for reaching out, İbrahim. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Selam — paylaştığın kodu ve sorunu inceledim. Özetle yanıtlıyorum: realtime pipeline’da
generate_reply()
ile kesin, kontrol edilebilir bir şekilde tam metin okutmak mümkün değil; modelin cevap üretimi önerilere/isteklere göre çalışır ve verdiğin tam metni birebir okumayabilir. Buna göre ne yapabileceğine dair net adımlar aşağıda. Kısa sebep • Realtime modeller doğrudan “metni kesinlikle TTS ile oynat” komutu vermez.
generate_reply(instructions=...)
modelden serbest biçimli bir yanıt üretir; tam metnin birebir okunacağını garanti etmez. Ne yapmalısın (önerilen çözüm: yarı-cascade / half-cascade) • Realtime modelini sadece metin anlama/üretme için kullan, ses çıkışı için ayrı bir TTS ekle. Böylece scripted (kesin) konuşmayı
session.say()
ile oynatabilirsin. Adımlar 1. Realtime modelini yalnızca text modalitesi ile başlat: ◦ Örnek:
RealtimeModel(modalities=["text"])
1. Session’a bir TTS ekle (istediğin TTS sağlayıcısı): ◦ Örnek:
tts="cartesia/sonic-3"
(kendi TTS’ini değiştir) 1. Kapanış mesajını
session.say(...)
ile söyle: ◦
session.say()
artık TTS kullanarak verdiğin metni birebir oynatır. 1. Playout’u beklemek için
wait_for_playout=True
kullanmaya devam et. Kod örneği (özet):
Copy code
session = AgentSession(
    llm=google.realtime.RealtimeModel(modalities=["text"]),
    tts="cartesia/sonic-3",
    vad=silero.VAD.load(),
)

# speak_message artık session.say() kullanır; generate_reply kullanmana gerek yok
handle = session.say(
    text=message,
    allow_interruptions=allow_interruptions,
    add_to_chat_ctx=add_to_chat_ctx,
)
if wait_for_playout:
    await handle.wait_for_playout()
return bool(getattr(handle, "interrupted", False))
Neden mevcut yöntemin çalışmıyor •
generate_reply(instructions=...)
talimatı modele “bunu söyle” diye söylemek gibidir; model bu talimatı esnetebilir, yeniden ifadelendirebilir veya atlayabilir. Bu yüzden tam kontrol isteniyorsa TTS ile
say()
kullanılmalı. Ek not:
_is_realtime_session()
tespitin kırılgan olabilir •
_pipeline_mode
gibi özel alanlara güvenmek güncellemede kırılganlık yaratır. Eğer yarı-cascade kullanırsan bu şarta bile ihtiyaç kalmayabilir çünkü
session.say()
TTS’i kullanacak. Özet öneri • Eğer amacın “tam olarak şu metni kullanıcıya söyle” ise: realtime model + ayrı TTS (yarı-cascade) ve
session.say()
kullan. • Eğer amacın modelin doğal realtime tepkisini almaksa (serbest cevaplar),
generate_reply()
uygundur ama metnin birebir okunmasını bekleme. İstersen yardımcı olayım • Mevcut session oluşturma kodunu paylaşabilir misin? (AgentSession oluştururken hangi llm/tts parametrelerini kullandığın) • Hangi TTS sağlayıcısını kullanmak istiyorsun? Bu bilgileri paylaşırsan, koduna özel bir düzeltme ve test adımları veririm. Sources: Realtime models overview | LiveKit Documentation | Agent speech and audio | LiveKit Documentation
a
Ya şöyleki birebir aynı cümleyi okumaması benim için bir problem değil. Sana göndermiş olduğum end_call function tool'unda generate_reply ile mesaj okutup sonrasında hangup yapması gerekiyor fakat mesajı okumadan hangup yapıyor.
t
Anladım — amaç: realtime modda
generate_reply()
ile kapanış mesajını çaldırıp, mesaj bitene kadar bekleyip sonra hangup yapmak. Şu anki davranış: çağrı kapanmadan önce hangup oluyor çünkü playout bitmesi beklenmiyor. Neden ve nasıl düzelteceğine dair kısa, uygulanabilir çözüm aşağıda. Neden oluyor •
generate_reply()
konuşmayı başlatır ama konuşmanın tamamlanmasını beklemez. Fonksiyon yanıt üretimini/başlatılmasını tetikler; TTS/playout başladıysa bile fonksiyon tamamlandığında ses hâlâ çalıyor olabilir. Eğer hemen
hangup()
çağırırsan, oda kapatıldığı için ses kesilir. Ne yapman gerekiyor (kesin çözüm) 1.
generate_reply()
çağrısından dönen handle'ı al. 2. Bu handle üzerinde
await handle.wait_for_playout()
çağırarak ses playout’unun bitmesini bekle. 3. Playout tamamlandıktan sonra
hangup()
yap. Örnek düzeltme (end_call için)
Copy code
# generate_reply ile cevap üret ve handle al
handle = await session.generate_reply(
    instructions=f"Kullanıcıya şu mesajı söyle: {closing_message}"
)

# Konuşma tamamlanana kadar bekle
await handle.wait_for_playout()

# Artık güvenle kapat
await hangup(ctx)
raise StopResponse()
Alternatif (daha doğrudan kontrol istiyorsan) • Eğer modelin verdiği ifade birebir olmasa da sorun değilse ve sadece mesajın çalmasını garanti etmek istiyorsan,
session.say(...)
veya TTS ile çalma yapıp yine
await handle.wait_for_playout()
kullan:
Copy code
handle = session.say(closing_message, allow_interruptions=True)
await handle.wait_for_playout()
await hangup(ctx)
• Bu yöntem,
say()
kullandığında sesin oynatılmasını daha doğrudan kontrol eder. Ek notlar •
generate_reply()
için
await
alırken bazı SDK sürümlerinde
generate_reply
çağrısı async olarak bir handle döndürüyor; senin kullanımına göre
handle = await session.generate_reply(...)
veya
handle = session.generate_reply(...)
olabilir. Hangi biçimin SDK’nda kullanıldığını kontrol et (amaç: elde edilen obje üzerinde
wait_for_playout()
çağırabilmek). • Mevcut kodunda zaten
await handle.wait_for_playout()
kullanıyorsan ve hâlâ kesiliyorsa, lütfen: ◦ Hangi SDK sürümünü kullandığını, ◦
generate_reply
çağrısını nasıl await ettiğini, ◦ loglarda
wait_for_playout
çağrısına ulaşılıp ulaşılmadığını paylaş; birlikte küçük adaptasyon yaparız. İstersen şimdi gönderdiğin end_call fonksiyonunu bu şekilde küçükçe değiştirip,
generate_reply
sonucu üzerinde
wait_for_playout()
çağıracak hâle getirecek şekilde düzelteyim — kodunu paylaş veya izin ver ben örneği doğrudan güncellemiş halde veriyim. Sources: How to detect when an agent has finished speaking | LiveKit
a
Python Agents en son versiyonunu kullanıyorum 1.4.2
t
Teşekkürler — verdiğin sürüm (Python Agents 1.4.2) için durumu netleştirelim. Kısa cevap: evet, sorun
generate_reply()
sonrası playout beklenmediği için çağrı kesiliyor. Çözüm,
generate_reply()
tarafından döndürülen handle üzerinde
wait_for_playout()
çağırmak (veya fonksiyon aracılığıyla sağlanan ctx yardımıyla beklemek). Aşağıda doğrudan uygulanabilecek, 1.4.2 uyumlu örnek ve dikkat edilmesi gerekenler var. Ne yapman gerekiyor (kısa) •
generate_reply(...)
çağrısının döndürdüğü SpeechHandle üzerinde
await handle.wait_for_playout()
çağır. • Playout tamamlandıktan sonra `hangup()`/oda silme işlemini gerçekleştir. Örnek (end_call fonksiyonunu buna göre düzenleme)
Copy code
@function_tool(
    name="end_call",
    description="Telefon görüşmesini sonlandır ve çağrıyı kapat."
)
async def end_call(context: RunContext, closing_message: str) -> str:
    ctx = get_job_context()
    session = context.session

    # Realtime model ile generate_reply başlat ve handle al
    handle = await session.generate_reply(
        instructions=f"Kullanıcıya şu mesajı söyle: {closing_message}"
    )

    # Konuşma tamamen bitene kadar bekle
    await handle.wait_for_playout()

    # Konuşma tamamlandıysa raporu güncelle ve kapat
    current_agent = getattr(session, "current_agent", None)
    if current_agent:
        session_report = getattr(current_agent, "_session_report_service", None)
        if session_report:
            session_report.set_ended_by("agent")

    await hangup(ctx)
    raise StopResponse()
Önemli notlar ve olası varyasyonlar • Bazı SDK sürümlerinde
session.generate_reply()
doğrudan handle döndürebilir (yani
handle = session.generate_reply(...)
şeklinde). Senin sürümde (1.4.2)
await session.generate_reply(...)
ile handle alıyorsan yukarıdaki kullanım doğru. Eğer handle’ı sen eş zamanlı olarak alıyorsan (await olmadan) o durumda: ◦ handle = session.generate_reply(...) ◦ await handle.wait_for_playout() • Eğer
handle.wait_for_playout()
çalışmıyorsa, SDK loglarını kontrol et:
wait_for_playout()
çağrısına ulaşılıyor mu yok mu? Eğer çağrıya ulaşmıyorsa generate_reply çağrısının beklenen handle tipini döndürüp döndürmediğini kontrol et. • Alternatif güvenli yol: eğer tam kontrol ve kesin oynatma istiyorsan
session.say(closing_message, allow_interruptions=True)
kullan ve sonra
await handle.wait_for_playout()
ile bekle.
say()
TTS üzerinde daha direkt kontrol sağlar. Kontrol listesi (hızlı debug adımları) • generate_reply çağrısından dönen objenin gerçekten
wait_for_playout
metoduna sahip olup olmadığını doğrula. • Log ekle: generate_reply hemen sonrası ve wait_for_playout giriş/çıkış noktalarına debug logu koy. • Hangup çağrısını kesinlikle
wait_for_playout()
tamamlandıktan sonra yap. İstersen ben • paylaştığın end_call fonksiyonunu doğrudan 1.4.2 uyumlu hâle getirip sana düzeltilmiş bir sürüm göndereyim, veya • senin mevcut generate_reply satırının tam kullanımını (await ile mi yoksa doğrudan mı çağırdığın) ve log çıktılarından ilgili kısımları paylaşmanı isteyeyim; ona göre daha kesin bir düzeltme veririm. Hangi yolu tercih edersin? Sources: Agent speech and audio | LiveKit Documentation | How to detect when an agent has finished speaking
a
{"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": 0.47, "input_tokens": 5127, "cached_input_tokens": 0, "input_text_tokens": 5102, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 25, "input_cached_audio_tokens": 0, "output_tokens": 146, "output_text_tokens": 24, "output_audio_tokens": 122, "output_image_tokens": 0, "total_tokens": 5273, "tokens_per_second": 92.26, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091218.237003+00:00"} {"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": 0.3, "input_tokens": 5332, "cached_input_tokens": 0, "input_text_tokens": 5134, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 198, "input_cached_audio_tokens": 0, "output_tokens": 315, "output_text_tokens": 58, "output_audio_tokens": 257, "output_image_tokens": 0, "total_tokens": 5647, "tokens_per_second": 113.83, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091227.593011+00:00"} {"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": 0.41, "input_tokens": 5683, "cached_input_tokens": 0, "input_text_tokens": 5191, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 492, "input_cached_audio_tokens": 0, "output_tokens": 126, "output_text_tokens": 24, "output_audio_tokens": 102, "output_image_tokens": 0, "total_tokens": 5809, "tokens_per_second": 95.13, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091238.335735+00:00"} 2026-02-20 091245 | end_call | INFO | 📴 Ending call - room: 699825680bb457b67c4756fd, message: Rica ederim. Başka bir konuda desteğe ihtiyaç duymanız halinde bizimle dilediğiniz zaman iletişime geçebilirsiniz. İyi günler dilerim. {"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": 0.0, "input_tokens": 5832, "cached_input_tokens": 0, "input_text_tokens": 5211, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 621, "input_cached_audio_tokens": 0, "output_tokens": 269, "output_text_tokens": 78, "output_audio_tokens": 191, "output_image_tokens": 0, "total_tokens": 6101, "tokens_per_second": 44662.65, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091245.997150+00:00"} {"message": "tool_choice is not supported by the Google Realtime API.", "level": "WARNING", "name": "livekit.plugins.google", "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091246.002880+00:00"} 2026-02-20 091246 | end_call | DEBUG | ✅ Closing speech completed, proceeding to hangup {"message": "tool_choice is not supported by the Google Realtime API.", "level": "WARNING", "name": "livekit.plugins.google", "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091246.657500+00:00"} {"message": "RealtimeModel metrics", "level": "INFO", "name": "livekit.agents", "model_name": "gemini-live-2.5-flash-native-audio", "model_provider": "Vertex AI", "ttft": -1.0, "input_tokens": 6142, "cached_input_tokens": 0, "input_text_tokens": 5330, "input_cached_text_tokens": 0, "input_image_tokens": 0, "input_cached_image_tokens": 0, "input_audio_tokens": 812, "input_cached_audio_tokens": 0, "output_tokens": 41, "output_text_tokens": 41, "output_audio_tokens": 0, "output_image_tokens": 0, "total_tokens": 6183, "tokens_per_second": 5612.67, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091246.662885+00:00"} {"message": "_SegmentSynchronizerImpl.playback_finished called before text/audio input is done", "level": "WARNING", "name": "livekit.agents", "text_done": false, "audio_done": true, "pid": 115, "job_id": "AJ_y2Q7tUmhZhoK", "room_id": "RM_7PWF3t8Fx2yh", "timestamp": "2026-02-20T091246.669677+00:00"} Dediğin değişikliği uyguladım ve yine çalışmadı. # generate_reply ile cevap üret ve handle al handle = await session.generate_reply( instructions=f"Kullanıcıya şu mesajı söyle: {closing_message}" ) # Konuşma tamamlanana kadar bekle await handle.wait_for_playout() # Artık güvenle kapat await hangup(ctx) raise StopResponse() Bunu uygulamıştım. 2026-02-20 091245 | end_call | INFO | 📴 Ending call - room: 699825680bb457b67c4756fd, message: Rica ederim. Başka bir konuda desteğe ihtiyaç duymanız halinde bizimle dilediğiniz zaman iletişime geçebilirsiniz. İyi günler dilerim. bu mesaj okunmadan kapandı.
t
Teşekkürler — gönderdiğin logları ve denemelerini inceledim. Önce şunu netleştireyim: bana verdiğin loglar ve uyarılar, senin doğru adımı (handle.wait_for_playout()) uygulamış olmana rağmen gerçek sorunun model/text↔️audio senkronizasyonu olduğunu gösteriyor. Aşağıda durumun özeti, neden böyle olduğu ve hemen deneyebileceğin adımlar var. Kısa özet (senin duruma yönelik) • Sen generate_reply() çağırıp sonra await handle.wait_for_playout() yapmışsın — bu doğru. • Loglarda kritik uyarı var: "_SegmentSynchronizerImpl.playback_finished called before text/audio input is done" — yani sistem oynatma bittiğini bildiriyor ama metin/audio girişi hâlâ tamamlanmamış. • Ayrıca son metrics satırında modelin çıktı için text token'ları var ama output_audio_tokens 0 görünüyor: model metin döndürmüş ama karşılık gelen audio üretilmemiş veya eşleştirilememiş. • Sonuç: wait_for_playout() audio akışının bittiğini görüyor, ama gerçek tamamlanmış/senkronize edilmiş sesi elde etmediğin için kullanıcının son cümlesi çalınmamış oluyor. Neden oluyor (kısa teknik neden) • Google Realtime (Gemini Live gibi) kimi durumlarda text delta'ları döndürebiliyor ve bu text'in TTS ile eksiksiz audio'ya dönüşmesi garanti değil; provider tarafında text↔️audio eşleştirmede kopma olabiliyor. • Ayrıca logda "tool_choice is not supported by the Google Realtime API" uyarısı var — provider'ın bazı özellikleri desteklememesi pipeline davranışını etkileyebilir. Hemen deneyebileceğin düzeltmeler (öncelik sırasına göre) 1) Kesin çözüm: session.say() ile TTS'e doğrudan ver, sonra wait_for_playout() • Neden: session.say() TTS plugin'ine doğrudan gider; TTS her zaman audio üretir ve wait_for_playout() audio oynatmanın gerçekten bitmesini bekler. • Nasıl:
Copy code
handle = await session.say(
    text=closing_message,
    allow_interruptions=False,  # kapanış mesajının kesilmemesi için
)
await handle.wait_for_playout()
await hangup(ctx)
raise StopResponse()
• Ayrıca AgentSession oluşturulurken bir TTS sağlandığından emin ol:
tts=...
2) Eğer generate_reply kullanmak istiyorsan (daha az güvenilir) • Modelden açıkça audio üretmesini talep eden bir instruction ver, ama bu yöntem Gemini/Google ile her zaman çalışmayabilir. • Örnek:
Copy code
handle = await session.generate_reply(
    instructions=f"Şu mesajı sesli olarak ve tamamını okuyarak söyle: {closing_message}"
)
await handle.wait_for_playout()
• Ancak logların zaten audio üretimi olmadığını gösterdiği için bu muhtemelen yeniden başarısız olur. 3) Ek debug/log adımları (sorunun kaynağını kesinleştirmek için) • generate_reply veya say sonrası handle nesnesini incele: handle içinde audio stream info/flags var mı? • wait_for_playout çağrısına girdiğini/çıktığını net logla doğrula: ◦ "before wait_for_playout" ◦ "after wait_for_playout" • Eğer
wait_for_playout
tamamlanıyor ama kullanıcıya okunmamışsa, handler
done
event'ine ek log koy:
Copy code
@handle.on("done")
def on_done():
    <http://logger.info|logger.info>("playout done event fired")
• Loglarda text_done / audio_done değerlerini kaydet; senin logta audio_done true ama text_done false gözüküyor — bu kritik bilgi. 4) Session / provider kontrolü • AgentSession başlatırken hangi TTS eklendi? (paylaşırsan kontrol ederim) • Eğer TTS yoksa veya provider (Google Realtime) TTS üretimini sınırlandırıyorsa session.say() çalışmayacaktır — bu yüzden session konfigürasyonunu paylaş. 5) Geçici workaround • Eğer TTS yok veya kullanamıyorsan, generate_reply sonrası küçük bir gecikme koymayı denemebilirsin (kötü bir yöntem ama test için):
Copy code
await handle.wait_for_playout()
await asyncio.sleep(0.5)
await hangup(ctx)
• Bu sadece eşlik eden senkronizasyon gecikmelerini kapatmak için; kalıcı çözüm değil. İstersen ben ne yaparım/önerebilirim next: • AgentSession oluşturma kodunu paylaş (özellikle llm/tts parametreleri). Buna göre session.say() kullanıp kullanamayacağını doğrularım. • Eğer istersen, senin end_call fonksiyonunu session.say() kullanan versiyonla doğrudan güncelleyeyim. • Ayrıca wait_for_playout() öncesi/sonrası üretilecek ayrıntılı log snippet'lerini eklemene yardımcı olurum; böylece hangi event'in önce tetiklendiğini kesin görürüz. Özet: loglar modelin text üretip audio üretmediğini gösteriyor — en güvenli çözüm TTS üzerinden
session.say()
kullanmak. AgentSession başlangıç kodunu ve/veya mevcut end_call fonksiyonunun tam hâlini paylaşırsan, seni çalışır hâle getirecek biçimde kodu güncelleyip test adımlarını veririm.
a
instructions değil de user_input ile versek okuması garanti olmaz mı tts ile?
t
İyi soru — kısa cevap: hayır, sadece
user_input
ile vermek TTS oynatımını garanti etmez. Detaylar ve ne yapman gerektiği aşağıda. Neden
user_input
garanti değil •
generate_reply()
(realtime mod) model için bir giriş sağlar ama metni kesinlikle TTS'e dönüştüreceğinin garantisi yok. Realtime sağlayıcıları (ör. Gemini Live) bazen yalnızca text delta döndürebilir veya text ↔️ audio eşleştirmesinde kopmalar olabilir. Senin loglarda da model text üretmiş ama audio token'ları eksik gözüküyor — bu yüzden audio hiç üretilmemiş olabilir. •
user_input
ile verilen metin de modelin yanıt üretme sürecine girer; model bunu okuyup seslendirebilir ama bunun gerçekleşeceğini garanti etmek mümkün değil. Ne garantiler:
session.say()
+ TTS eklentisi • Eğer amacın "kesinlikle bu metin çalsın, bitene kadar bekleyip sonra hangup yap" ise en güvenilir yol
session.say(text=...)
kullanmak ve agent session'ın TTS (text-to-speech) ile konfigüre edilmiş olmasıdır. •
session.say()
doğrudan TTS pipeline'ına gittiği için audio üretilir; dönen handle üzerinde
await handle.wait_for_playout()
çağırınca oynatma gerçekten tamamlanana kadar beklenir. Kısa örnek (önerilen yöntem)
Copy code
# TTS ile kesin oynatma
handle = await session.say(
    text=closing_message,
    allow_interruptions=False
)
await handle.wait_for_playout()
await hangup(ctx)
raise StopResponse()
Eğer yine de generate_reply + user_input deneyeceksen (daha az güvenilir) • Modelin audio üretmesini açıkça isteyebilirsin (ör.
instructions
içinde “sesli olarak oku”), ama provider desteklemiyorsa yine başarısız olabilir. •
user_input
kullanarak çağrı başlatırsan da modelin audio üretip üretmeyeceği provider kapasitesine ve pipeline durumuna bağlıdır. Ne paylaşırsan yardımcı olurum • AgentSession oluşturma kodunu (özellikle
llm
ve
tts
parametreleri) paylaşabilir misin? Böylece: ◦ TTS konfigürasyonun varsa
session.say()
ile çözümü doğrudan uygulayıp test edebileceğini gösteririm. ◦ TTS yoksa nasıl ekleyeceğini ve en güvenilir patterni (kapanış mesajları için) sana uygun şekilde açarım. Özet •
user_input
tek başına TTS oynatımı garanti etmez. • Kesin, kontrol edilebilir kapanış mesajı için
session.say()
+ konfigüre TTS kullan; sonra
await handle.wait_for_playout()
ve hangup yap. İstersen şimdi AgentSession konfigürasyonunu gönder, ben kapanış akışını doğrudan çalışır hâle getiren kodu sana uyarlayayım.
a
llm_model = google.realtime.RealtimeModel( instructions=self._instructions, model="gemini-live-2.5-flash-native-audio", voice="Autonoe", temperature=0.3, vertexai=True, thinking_config=types.ThinkingConfig( thinking_budget=0, ), )
t
Haklısın — paylaştığın
llm_model
konfigürasyonu (Gemini Live realtime) ile durumu netleştireyim ve kısa, uygulanabilir adımlar vereyim. Özet (kısa) • Hayır: sadece
user_input
vererek
generate_reply()
kullanmak, TTS ile kesin oynatma garantisi vermez. • Neden: Gemini Live / Google Realtime bazen yalnızca text delta döndürebiliyor veya text↔️audio eşleştirmesinde kopmalar olabiliyor. Senin loglarda da audio token'larının eksik olduğu ve
_SegmentSynchronizerImpl.playback_finished called before text/audio input is done
uyarısı çıktı — yani audio hiç üretilmemiş olabilir. • Güvenilir çözüm: ayrı bir TTS eklentisi (plugin) ile
session.say(...)
kullanmak; sonra
await handle.wait_for_playout()
ve only then hangup. Neler yapmalısın — adım adım (öncelik sırasına göre) 1) En sağlam yol: AgentSession’a TTS ekle ve
session.say()
kullan • Neden:
session.say()
doğrudan TTS pipeline’ına gider, TTS kesinlikle audio üretir ve
wait_for_playout()
audio oynatma tamamlanana kadar bekler. • Nasıl örnek:
Copy code
# AgentSession oluştururken bir TTS sağlayıcısı ekle (örnek)
session = AgentSession(
    llm=google.realtime.RealtimeModel(
        model="gemini-live-2.5-flash-native-audio",
        # burada modalities veya voice ayarlarını minimal tutabilirsin
    ),
    tts=google.TTS(),  # veya kullandığın başka bir TTS plugin'i
)

# Kapanışta:
handle = await session.say(text=closing_message, allow_interruptions=False)
await handle.wait_for_playout()
await hangup(ctx)
raise StopResponse()
• Not:
allow_interruptions=False
kapanışı kesilmeden okutmak için faydalıdır. 2) Eğer TTS eklemek istemiyorsan (daha az güvenilir) •
generate_reply()
içine hem
instructions
hem
user_input
koyup modeli açıkça “seslendir” diye zorlayabilirsin, ama bu sağlayıcıya bağlı olarak başarısız olabilir. • Örnek (deneme):
Copy code
handle = await session.generate_reply(
    instructions=f"Bu metni sesli olarak tam ve eksiksiz oku: {closing_message}",
    user_input=closing_message
)
await handle.wait_for_playout()
await hangup(ctx)
• Ancak logların zaten audio token eksikliği gösterdiği için bu yöntemin garanti olma olasılığı düşüktür. 3) Debug adımları — neden hala kesiliyoru kesinleştir •
handle
objesinin tipini ve içinde `output_audio_tokens`/audio stream bilgilerini kontrol et. •
wait_for_playout()
öncesi/sonrası debug logları koy: ◦ "before wait_for_playout" ◦ "after wait_for_playout" ◦ handle üzerinde
on("done")
callback varsa onu da logla. • Eğer
wait_for_playout()
return olmadığı halde kullanıcıya okunmamışsa, loglarda `text_done`/`audio_done` flag’lerini kontrol et (senin logta audio_done true text_done false görünmüş). 4) Geçici test workaround (sadece test için) •
await handle.wait_for_playout()
sonrasına küçük bir bekleme ekle (örn. 0.5s) — bu kalıcı çözüm değil ama pipeline zamanlama/senkronize sorunlarını geçici görmene yardımcı olabilir. Senden isteğim (benim yardımımı verimli yapmak için) • AgentSession oluşturma kodunun tam halini (özellikle
tts=
parametresi var mı yok mu) paylaş. Eğer TTS yoksa ben sana hangi TTS plugin’i eklemen gerektiğini ve tam konfigürasyon satırlarını veririm. • İstersen end_call fonksiyonunun güncellenmiş tam hâlini gönder, ben TTS ile çalışan ve kesin oynatma sonrası hangup yapan son hâlini doğrudan düzenleyip geri gönderirim. Özet öneri • En hızlı, güvenli ve garanti çözüm: session’a TTS ekle + session.say(...) + await handle.wait_for_playout() sonra hangup. •
user_input
kullanımı tek başına garanti sağlamaz çünkü Gemini Live realtime pipeline text↔️audio üretimini her zaman sağlamıyor. İstersen hemen AgentSession başlangıç kodunu (tam) at; TTS eklenmiş hâlini ve düzeltilmiş end_call fonksiyonunu sana hazır veriyim. Sources: Realtime models overview | LiveKit Documentation | Agent speech and audio | LiveKit Documentation | Gemini TTS plugin guide | LiveKit Documentation
a
Ek TTS kullanırsam latency artabilir mi?
t
Kısa cevap: Evet, ek TTS eklemek biraz ek gecikme (synthesis latency) getirir — ama genelde bu ek gecikme küçük olur ve kapanış mesajlarının güvenilir şekilde çalınmasını sağlamak için kabul edilebilir. Aşağıda nedenleri, beklenen büyüklükler, gecikmeyi azaltma yöntemleri ve hangi durumlarda TTS kullanmanın daha doğru olduğu var. Neden gecikme olur • TTS metni alıp ses oluşturmak için işlem yapar; bu sentez süresi doğal olarak zaman alır. • Realtime model + ayrı TTS kullandığında önce LLM/komut akışı (opsiyonel), sonra TTS sentezi, sonra ağ üzerinden oynatma gerçekleşir — bu katmanlar toplam gecikmeyi artırır. Tipik boyutlar (genel gözlem) • Modern düşük gecikmeli TTS’ler: ~100–300 ms başlangıç gecikmesi + uzunluğa bağlı süre (ör. 5–15 saniyelik bir mesaj için ek oynatma süresi doğal olarak olur). • Daha ağır/high-quality veya bulut TTS’lerde bu 300–800 ms veya daha fazla olabilir. • Gerçek sayılar kullandığın TTS sağlayıcısına, ağ koşullarına ve mesaj uzunluğuna göre değişir. Gecikmeyi azaltma yöntemleri • Kısa ve öz kapanış mesajı kullan: daha kısa metin = daha az synthesis zaman. • Düşük-latency TTS sağlayıcıları seç: bazı TTS modelleri "streaming" destekler (parça parça oynatılırken sentez devam eder). • Ön-sentez / cache: sık kullanılan kapanış cümlelerini (veya varyasyonlarını) önceden synthesize edip saklayabilir ve çağrı sırasında doğrudan oynatabilirsin — bu en hızlı seçenek. • Streaming TTS ve playout eşzamanlama: TTS streaming destekliyorsa, konuşma oynatılmaya başlar başlamaz kullanıcı duymaya başlar; böylece görünür gecikme azalır. • Böl ve oynat: Uzun mesajları mantıklı parçalara bölüp ilk parçayı hızlıca oynatıp geri kalanını akışla tamamlayabilirsin (diyalog akışını bozmamak kaydıyla). Ne zaman TTS kullanmalısın • Kapanış gibi “kritik” mesajlarda TTS kullanmak mantıklı: tek seferde çalınması ve kullanıcıya eksiksiz ulaşması önemli. • Eğer birkaç yüz ms ek gecikme kabul edilebilirse, TTS’in sağladığı deterministiklik (birebir metin oynatma) tercih edilir. • Eğer uygulamada ultra-düşük gecikme (ör. <100 ms tepki) şartsa ve mesajın eksiksiz okunması ikinci plandaysa, generate_reply/realtime akışıyla devam etmeyi değerlendirebilirsin — ancak senin yaşadığın kesilme sorununu düzeltmez. Pratik öneri (senin senaryona) 1. Deney: session.say() ile TTS kullanarak kapanışı test et ve uçtan uca ölç (metin gönderme → playout başlangıcı). Böyle gerçek ekstra gecikmeyi görürsün. 2. Eğer gecikme problemli ise: sık kullanılan kapanış cümlelerini ön-sentezle ve çağrı esnasında doğrudan oynat. 3. Streaming destekli TTS kullanabiliyorsan onu tercih et — hem daha doğal hem de başlangıç gecikmesi düşük olur. İstersen yardım edeyim • AgentSession konfigürasyonuna hangi TTS’i ekleyebileceğini gösteririm (örnek kod ile). • Kısa bir benchmark script’i veririm: kapanış mesajını
session.say()
ile oynatıp eşzamanlı loglarla latency ölçersin. • Eğer istersen, kullandığın sağlayıcıyı (ör. Google TTS, Cartesia, ElevenLabs vb.) yaz; o servis için öneriler ve beklenen gecikme aralığı vereyim. Hangi yolu tercih edersin — önce doğrudan TTS ile test verisini mi sağlıyım yoksa önceden synthesize/cache yaklaşımını mı örnekleyeyim?
a
generate_reply'i doğru şekilde kullanabiliyor olmam lazım ya. Livekit'in dökümantasyonlarında realtime modellerde böyle bir sorundan bahsedilmemiş ki
t
Haklısın — dökümantasyonda açıkça yer almayabilir, ama gönderdiğin loglar ve denemelerin gerçek durumu gösteriyor: Gemini Live (Google Realtime) ile generate_reply() kullanırken modelin “metin ürettiği ama audio token üretmediği” ve oynatma ile metin üretiminin senkronize olmaması ihtimali var. Bu yüzden wait_for_playout() çağırmış olsan bile çağrı erken kapanabiliyor. Özetle: senin kullanım biçimin mantıklı ama altyapı/sağlayıcı tarafı bazı durumlarda tam bir garanti vermiyor. Ne olduğunu kısa ve net şekilde özetleyeyim • generate_reply() modelden yanıt üretmesini başlatır, ama realtime sağlayıcı tüm yanıtları TTS’e dönüştürüp oynatmayı garanti etmeyebilir. • Logundaki "_SegmentSynchronizerImpl.playback_finished called before text/audio input is done" uyarısı, audio oynatma sona ererken metin üretiminin hâlâ tamamlanmadığını gösteriyor — yani ses eksik veya hatalı üretilmiş. • output_audio_tokens = 0 gibi metrikler modelin audio üretmediğine işaret ediyor; wait_for_playout() ise yalnızca mevcut yerel oynatmanın bittiğini görüyor. Sonuç: ses eksik ama kontrol akışı yine de devam ediyor. Ne yapabilirsin — önerilen, pratik çözümler 1) En güvenilir (önerilen): session.say() + ayrı TTS plugin • AgentSession’a bir TTS ekle ve kapanış için
session.say(closing_message, allow_interruptions=False)
kullan. • Ardından
await handle.wait_for_playout()
çağır, sonra hangup yap. • Neden: TTS kesinlikle audio üretir; wait_for_playout() gerçek oynatmayı bekler. Bu, kullanıcıya eksiksiz ulaşmayı garanti eder. 2) Eğer TTS eklemek istemiyorsan (daha az güvenilir) • generate_reply() ile hem instructions hem user_input verip modelden açıkça “seslendir” demeyi dene, ama özellikle Gemini Live’da bu her zaman çalışmayabilir. • Örnek deneme (başarılı garantisi yok): handle = await session.generate_reply(instructions=f"Şunu sesli oku: {closing_message}", user_input=closing_message) await handle.wait_for_playout() await hangup(ctx) 3) Debug / doğrulama adımları (neden çalışmadığını kesin görmek için) • handle objesinin tipini ve içindeki audio metadata’sını logla. • wait_for_playout() öncesi ve sonrası log at: “before wait_for_playout” / “after wait_for_playout”. • handle üzerinde
on("done")
callback varsa ekle ve tetiklenip tetiklenmediğini kontrol et. • Loglarda text_done / audio_done flag’lerini kontrol et (seninki audio_done true text_done false göstermiş). 4) Geçici test workaround • wait_for_playout() sonrası kısa bir sleep (örn. 0.5s) koyup deneyebilirsin; kalıcı çözüm değil ama senkronizasyon görece farkını test eder. Latency endişen varsa • Evet, ayrı TTS bir miktar ek gecikme getirir; fakat genelde 100–500 ms arası başlatma farkı olur ve kapanış mesajları için kabul edilebilir. Eğer gecikme kritikse, sık kullanılan kapanış cümlelerini önceden sentezleyip cache’lemek en iyi çözümdür. İstersen şimdi ne yapalım? • Eğer kabul ediyorsan, senin paylaştığın
llm_model
konfigürasyonuna bir TTS nasıl eklenir, end_call’ı nasıl session.say() kullanacak şekilde düzenlersin — ben hazır bir kod örneği veririm. • Alternatif olarak, generate_reply() ile devam etmek istiyorsan handle içeriğini (type ve mevcut alanlar) paylaş; birlikte hangi alanın audio üretmediğini teyit eder ve daha ileri debug adımları veririm. Hangi yolu tercih ediyorsun? TTS eklemeyi deneyip latency etkisini test edelim mi, yoksa generate_reply odaklı derin debug yapalım mı? Sources: Realtime models overview | LiveKit Documentation | How to detect when an agent has finished speaking | LiveKit | examples/voice_agents | livekit/livekit_composite | DeepWiki | Pipeline nodes and hooks | LiveKit Documentation
a
Gemini TTS'i vertexAI üzerinden kullanabilir miyim?
t
Evet — Gemini TTS’i Vertex AI üzerinden kullanabilirsin. Kısa anlatım, gerekli adımlar ve dikkat etmen gerekenler aşağıda. Hızlı gereksinimler • GCP projesinde Vertex AI etkin olmalı. • Hizmet hesabı anahtarını kullanarak kimlik doğrulaması yap:
GOOGLE_APPLICATION_CREDENTIALS
çevre değişkeni bu anahtar dosyasını göstermeli. • Projede gerekli API’ler (Vertex AI, gerekiyorsa Cloud Text-to-Speech) etkin olmalı. Nasıl yapılandırırsın (örnek) • LiveKit Agents içinde Gemini TTS plugin’ini Vertex AI ile şu şekilde kullanabilirsin:
Copy code
from livekit.plugins import google

session = AgentSession(
    llm=google.realtime.RealtimeModel(
        model="gemini-live-2.5-flash-native-audio",
        # ... mevcut llm ayarların
    ),
    tts=google.GeminiTTS(
        model="gemini-tts-model-name",   # kullanılacak TTS model adı
        voice_name="Autonoe",            # tercih ettiğin ses
        vertexai=True,
        project="your-gcp-project-id",   # isteğe bağlı, credentials'tan okunuyorsa gerekli değil
        location="us-central1",          # isteğe bağlı
    ),
)
Önemli noktalar ve tavsiyeler •
vertexai=True
parametresi ile plugin’in Vertex AI kullanması sağlanır. •
GOOGLE_APPLICATION_CREDENTIALS
çevre değişkeni doğru ayarlı değilse kimlik doğrulama hatası alırsın. • Bazı sağlayıcı/kullanım durumlarında model ve voice isimleri farklı olabilir — LiveKit doc’daki Gemini TTS plugin sayfasındaki model/voice isimlerini kontrol et. • TTS eklemek, daha güvenilir (deterministik) ses oynatma sağlar; fakat küçük bir synthesis latency ekleyebilir. Eğer gecikme kritikse sık kullanılan veda cümlelerini önceden sentezleyip cache’leyebilirsin. Doğrulama ve test adımları 1.
GOOGLE_APPLICATION_CREDENTIALS
ortam değişkenini ayarla. 2. AgentSession’u yukarıdaki gibi oluştur. 3.
session.say("Kapanış mesajı")
ile TTS oynat ve
await handle.wait_for_playout()
ile tamamen çalındığını doğrula. 4. Her şey yolundaysa end_call akışında
session.say()
+
wait_for_playout()
sonrası
hangup()
işlemini gerçekleştir. İstersen yapabileceğim şeyler • Mevcut AgentSession oluşturma kodunu paylaşırsan, sana doğrudan GeminiTTS ile güncellenmiş bir örnek verebilirim. • GCP kimlik doğrulama veya plugin hatası alırsan, logları paylaş; hangi hata geldiğine göre adım adım yardım ederim. Hazırsan session kodunu gönder, birlikte Gemini TTS’i Vertex AI ile entegre edelim ve end_call akışını garanti çalışacak şekilde güncelleyelim. Sources: Gemini TTS plugin guide | LiveKit Documentation | Google Gemini LLM plugin guide | LiveKit Documentation
a
llm_model = google.realtime.RealtimeModel( instructions=self._instructions, model="gemini-live-2.5-flash-native-audio", temperature=0.3, vertexai=True, thinking_config=types.ThinkingConfig( thinking_budget=0, ), ) tts_model = google.beta.GeminiTTS( model="gemini-2.5-flash-preview-tts", voice_name="Autonoe", instructions="Speak in a friendly and engaging tone.", vertexai=True, ) Böyle ypatım başka bir şey yapmama gerek var mı? Modalites falan
t
Evet — paylaştığın
llm_model
ve
tts_model
tanımları doğru yönde ve genel olarak yeterli görünüyor. Kısa cevap: ekstra zorunlu bir parametre eklemen çoğunlukla gerekli değil, ama birkaç kontrol ve en iyi uygulama var; onları uygulayarak kapanış mesajlarının güvenilir çalışmasını sağlarsın. Kısa kontrol listesi (hemen doğrula) • AgentSession içinde hem
llm
hem `tts`’yi geçir: ◦
session = AgentSession(llm=llm_model, tts=tts_model, ...)
• GCP kimlik bilgileri ayarlı mı:
GOOGLE_APPLICATION_CREDENTIALS
çevre değişkeni doğru service account anahtarını gösteriyor mu? • GCP projesinde Vertex AI API’leri etkin mi? (Vertex AI + gerekliyse TTS/Audio API’leri) Modalities hakkında • Realtime LLM’in
modalities
parametresini açıkça belirtmedin; eğer amacın LLM’i yalnızca anlamsal işlem/cevap üretme için kullanmak ve ses çıkışını TTS’e bırakmaksa, LLM’i yalnızca text modalitesiyle çalıştırmak daha güvenli olur: ◦ Öneri:
modalities=["text"]
(veya sağlayıcının beklediği biçimde küçük harf) ◦ Böylece model “native audio” üretmeye çalışmaz ve tüm konuşma TTS tarafından kontrollü şekilde üretilir. Bu, sendeki kesilme/senkronizasyon problemlerini büyük ölçüde ortadan kaldırır. • Eğer realtime modelin direkte ses üretmesini de istersen (ama bu güvenilir değilse), modalities içinde audio’yu da tutabilirsin; ancak önerim kapanışlar için TTS’e yönelmek. Ek önerilen ayarlar / en iyi uygulamalar •
allow_interruptions=False
ile
session.say()
kullanarak kapanış mesajını okut: ◦
handle = await session.say(text=closing_message, allow_interruptions=False)
◦
await handle.wait_for_playout()
◦
await hangup(ctx)
• TTS latency azaltma: sık kullanılan kapanış cümlelerini önceden synthesize edip cache’lemeyi düşün. Bu, kullanıcıya gecikmesiz cevap sağlar. •
thinking_config=types.ThinkingConfig(thinking_budget=0)
zaten düşünmeyi kapatıyor; bu, LLM’in kapanışta beklenmedik “düşünmesine” sebep olmayacağı için uygundur. • Log/monitor:
handle
üzerinde
on("done")
veya play-out öncesi/sonrası log koyarak gerçek oynatma durumunu doğrula. Örnek güvenli AgentSession (öneri)
Copy code
llm_model = google.realtime.RealtimeModel(
    instructions=self._instructions,
    model="gemini-live-2.5-flash-native-audio",
    temperature=0.3,
    vertexai=True,
    thinking_config=types.ThinkingConfig(thinking_budget=0),
    modalities=["text"],  # önerilen: sadece metin üretimi
)

tts_model = google.beta.GeminiTTS(
    model="gemini-2.5-flash-preview-tts",
    voice_name="Autonoe",
    instructions="Speak in a friendly and engaging tone.",
    vertexai=True,
)

session = AgentSession(
    llm=llm_model,
    tts=tts_model,
    # diğer gerekli plugin/ayarlar...
)
Özet • Mevcut konfigurasyon iyi; ama
modalities=["text"]
ile LLM’in ses üretimini devre dışı bırakıp TTS’i zorunlu kılarsan kapanış mesajlarının eksiksiz okunma olasılığı en yüksek olur. • Ayrıca GCP kimlik doğrulaması ve Vertex AI servis etkinliği gibi çevresel ayarların doğru olduğundan emin ol. İstersen ben: • end_call fonksiyonunu
session.say()
+
wait_for_playout()
kullanacak şekilde doğrudan senin koduna uyarlayayım, • veya mevcut session kurulumunu alıp
modalities
eklenmiş/test edilecek hâlini paylaşayım. Hangi şekilde ilerleyelim?
a
{"message": "Gemini Realtime API error: 1007 None. Text output is not supported for native audio output model.\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.", "level": "ERROR", "name": "livekit.plugins.google", "exc_info": "Traceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.", "pid": 116, "job_id": "AJ_JvzqzZKTnPLY", "room_id": "RM_MAxzwDy4b6YY", "timestamp": "2026-02-20T093908.046201+00:00"} {"message": "AgentSession is closing due to unrecoverable error\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.", "level": "ERROR", "name": "livekit.agents", "exc_info": "Traceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.", "pid": 116, "job_id": "AJ_JvzqzZKTnPLY", "room_id": "RM_MAxzwDy4b6YY", "timestamp": "2026-02-20T093908.053963+00:00"} {"message": "Error in _main_task\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/agents/utils/log.py\", line 17, in async_fn_logs\n return await fn(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 845, in _main_task\n raise APIConnectionError(message=error_msg) from e\nlivekit.agents._exceptions.APIConnectionError: Failed to connect to Gemini Live", "level": "ERROR", "name": "livekit.plugins.google", "exc_info": "Traceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1007 (invalid frame payload data) Text output is not supported for native audio output model.; then sent 1007 (invalid frame payload data) Text output is not supported for native audio output model.\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1007 None. Text output is not supported for native audio output model.\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/agents/utils/log.py\", line 17, in async_fn_logs\n return await fn(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 845, in _main_task\n raise APIConnectionError(message=error_msg) from e\nlivekit.agents._exceptions.APIConnectionError: Failed to connect to Gemini Live", "pid": 116, "job_id": "AJ_JvzqzZKTnPLY", "room_id": "RM_MAxzwDy4b6YY", "timestamp": "2026-02-20T093908.057403+00:00"}
t
Teşekkürler—paylaştığın hata logu çok faydalı. Kısa cevap ilk olarak: hata açıkça söylüyor — kullandığın “native audio output” Gemini modeli text output’u desteklemiyor. Yani aynı realtime LLM bağlantısında hem native audio modunu hem de text deltas bekleyemezsin. Bu yüzden bağlantı WebSocket tarafından kapatılıyor ve AgentSession kapanıyor. Aşağıda neden ve kesin çözümler adım adım var. Neden bu hatayı alıyorsun (kısa) • Hata: "Text output is not supported for native audio output model" — Gemini Live native-audio modeli, sunucu tarafında doğrudan ses üreten bir model. Bu model ile aynı oturumda text delta'ı da istemek (veya SDK'nın default olarak text beklemesi) desteklenmiyor. • Sonuç: SDK/WebSocket, hem text hem audio beklenince frame uyumsuzluğu tespit edip connection’ı 1007 ile kapatıyor. Ne yapman gerekiyor (öncelikli düzeltmeler) 1) En temiz ve önerilen yol — ayır: • Realtime LLM’i sadece text modalitesiyle çalıştır (yani Gemini’yi "text" moduna çevir veya text-capable bir realtime versiyon kullan). • Ses üretimini ise ayrı TTS (GeminiTTS via Vertex AI veya başka bir TTS) ile yap. Neden: Bu “half-cascade” yaklaşım hatayı ortadan kaldırır; LLM text üretir, sen TTS ile kesin audio oluşturur ve
session.say()
ile oynatırsın. Nasıl (örnek):
Copy code
llm_model = google.realtime.RealtimeModel(
    model="gemini-live-2.5-flash-native-audio",  # mevcut modelin native-audio ise değiştirmelisin
    vertexai=True,
    modalities=["text"],  # ÖNEMLİ: native audio üretimini devre dışı bırak, sadece text iste
    thinking_config=types.ThinkingConfig(thinking_budget=0),
    temperature=0.3,
)

tts_model = google.beta.GeminiTTS(
    model="gemini-2.5-flash-preview-tts",
    voice_name="Autonoe",
    vertexai=True,
)

session = AgentSession(llm=llm_model, tts=tts_model, ...)
• Eğer modelin “native-audio” versiyonunu kullanmaya devam ediyorsan, modalities parametresini "text" yapamazsın — o durumda modelin native audio çıktısı ile text çıktısını aynı oturumda karıştırmamalısın. 2) Alternatif: Realtime model olarak text-capable bir versiyon seç • Eğer elindeki model (gemini-live-2.5-flash-native-audio) native audio-only ise, text çıktı üretebilen bir Gemini Live text modeline geç. Böylece aynı realtime bağlantıdan text çıktısı alabilir ve TTS’i ayrı kullanabilirsin. 3) Eğer native audio model kullanmak istiyorsan (ama text de istiyorsan) • Bu kombinasyon desteklenmediği için mümkün değil. Ya native audio-only kullanım (model tarafından doğrudan konuşma üretilecek) ya da text-only + ayrı TTS mimarisini seçmelisin. 4) Özet uygulama önerisi (kapanış mesajı garantilemek için) • En güvenilir: LLM (modalities=["text"]) + GeminiTTS via VertexAI (tts=tts_model) + `session.say(closing_message, allow_interruptions=False)
+
await handle.wait_for_playout()` + ardından
hangup()
. • Böylece WebSocket 1007 hatasını almazsın, ses her zaman TTS tarafından üretilir ve playout senkron olarak beklenir. Ek dikkat edilmesi gerekenler •
modalities
parametresini doğru ayarla. Native audio modeller text output desteklemez; text-only modalitesi istiyorsan modelin bunu desteklemesi gerekir. •
vertexai=True
ve
GOOGLE_APPLICATION_CREDENTIALS
gibi kimlik bilgilerini doğru ayarladığından emin ol. • Eğer SDK veya plugin sürümünde farklı isimleme/parametreler varsa (ör.
modalities
yerine başka bir alan), kullandığın livekit/google plugin versiyonuna göre küçük farklılık olabilir — bunu belirtirsen birlikte netleştiririz. İstersen hemen yardımcı olayım • Senin mevcut satırlara göre:
llm_model
şu an native-audio model adını kullanıyor. İki seçenek sunayım: a. `llm_model`’i text-capable bir Gemini Live model ismi ile değiştir ve
modalities=["text"]
ekle; TTS ile devam et. b. Ya da `llm_model`’i olduğu gibi bırak ama TTS’ten ayrı çalışacak biçimde yeniden yapılandır; fakat native-audio model ile aynı oturumda text çıkışı istememelisin. • Hangi yolu tercih ediyorsun? Tercih edersen, tam olarak kullanman gereken
llm_model
tanımını (text-capable örnek isim istersen) ve güncellenmiş AgentSession kodunu hazır şekilde veririm.
a
Gemini Live'de hangi model text'i destekliyor ki?
t
İyi soru — kısa cevap: Gemini Live’da metin çıktısı alabilmek için modelin text modalitesini desteklemesi ve oturumu buna göre yapılandırman gerekir. Gönderdiğin hata da tam olarak bunun sonucu: kullandığın native-audio model aynı oturumda text çıktısı üretmeyi desteklemiyor. Aşağıda ne yapman gerektiğini, hangi modelleri/ayarları tercih edebileceğini ve uygulamada dikkat etmen gerekenleri özetliyorum. 1) Hata ne demek? • Hata: "Text output is not supported for native audio output model" — yani aynı realtime oturumda hem native audio (sunucu tarafı ses üreten) modu hem de text delta’ları istemek desteklenmiyor. WebSocket bu çelişkiyi algılıyor ve bağlantıyı kapatıyor. 2) Hangi yaklaşımı seçmelisin (öneri) • En güvenli ve pratik yol: Gemini Live’ı sadece text üretmek için kullanıp, ses üretimini ayrı bir TTS (GeminiTTS veya başka bir TTS plugin’i) ile yapmak — yani half-cascade (yarı-cascade) mimarisi. ◦ Neden: Bu şekilde model text üretir; sen metni deterministik bir TTS ile sese çevirir ve
session.say()
+
wait_for_playout()
ile kesin oynatma sağlarsın. WebSocket 1007 hatası gelmez. 3) Hangi Gemini modelleri text modu destekler? • Geminin Live ailesinde text modalitesini destekleyen versiyonlar var; örneğin dokümanda geçen
gemini-2.5-flash-native-audio-preview-12-2025
modelini
modalities=["text"]
ile text-only moda alabileceğin belirtiliyor. Özetle: ◦ Eğer modelin adı “…native-audio…” içeriyorsa, varsayılan olarak native audio davranışı olabilir; bu durumda ya: ▪︎ Aynı ada sahip text-capable bir versiyon (preview veya non-native) kullan, veya ▪︎ Mevcut realtime modelde
modalities=["text"]
(ve model destekliyorsa) ayarıyla yalnızca metin talep et. • Özet: text çıktı almak istiyorsan modelin text-capable bir sürümünü veya text modalitesini desteklediğinden emin olacak şekilde yapılandır. 4) Uygulama örneği (güvenli konfigürasyon) • LLM’i text-only yap ve TTS’i ayrı ekle:
Copy code
llm_model = google.realtime.RealtimeModel(
    model="gemini-2.5-flash-native-audio-preview-12-2025",  # text-capable sürüm kullan
    modalities=["text"],
    vertexai=True,
    thinking_config=types.ThinkingConfig(thinking_budget=0),
)

tts_model = google.beta.GeminiTTS(
    model="gemini-2.5-flash-preview-tts",
    voice_name="Autonoe",
    vertexai=True,
)

session = AgentSession(llm=llm_model, tts=tts_model, ...)
• Kapanış akışı:
Copy code
handle = await session.say(text=closing_message, allow_interruptions=False)
await handle.wait_for_playout()
await hangup(ctx)
5) Eğer native-audio model kullanmak istiyorsan • Native-audio modelin aynı oturumda text çıktısı üretmesi desteklenmiyor; ya tamamen native-audio-only kullanırsın (ki bu durumda text delta’ları alamazsın), ya da text üretimi için farklı/uygun bir model sürümüne geçersin. 6) Kontrol etmen gerekenler • Hangi model isimlerini kullanabildiğini ve modelin text-capable olup olmadığını LiveKit/Google dökümantasyonundan veya plugin dokusundan doğrula. •
modalities
parametresini doğru şekilde ayarla. •
vertexai=True
ve GCP kimlik bilgilerin doğru olsun (
GOOGLE_APPLICATION_CREDENTIALS
). 7) İstersen hemen yardımcı olayım • Bana kullanmak istediğin tam model adını veya AgentSession oluşturma kodunun tam halini gönder, ben: ◦ Hata almayacağın, text-only + TTS kullanan hazır AgentSession örneğini ve ◦ end_call fonksiyonunu
session.say()
ile güvenli çalışacak şekilde düzenlenmiş halini gönderirim. Özet: Gemini Live’da native-audio modellerle text çıktısı aynı oturumda desteklenmeyebilir — bu yüzden text üretimi için text-capable model veya modalities=["text"] kullanıp ses üretimini ayrı TTS ile yapmak en sağlıklı yaklaşımdır. Hangi modeli kullanmak istediğini veya mevcut session kodunu at, hemen uygun konfigürasyonla yardımcı olayım. Sources: Gemini Live API plugin | LiveKit Documentation | How to build an agent with speech-to-text input and text-only output | Live... | Announcing Agent Builder: a pathway to code
a
{"message": "Error in _main_task\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1008 (policy violation) Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
; then sent 1008 (policy violation) Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1008 None. Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/agents/utils/log.py\", line 17, in async_fn_logs\n return await fn(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 845, in _main_task\n raise APIConnectionError(message=error_msg) from e\nlivekit.agents._exceptions.APIConnectionError: Failed to connect to Gemini Live\n\nHint: A 1008 policy violation error often indicates that the model name doesn't match the API being used. VertexAI models typically start with 'gemini-live-', while Gemini API models start with 'gemini-2.' or similar. Please verify your model name matches your API configuration.", "level": "ERROR", "name": "livekit.plugins.google", "exc_info": "Traceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1105, in connect\n raw_response = await ws.recv(decode=False)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/websockets/asyncio/connection.py\", line 322, in recv\n raise self.protocol.close_exc from self.recv_exc\nwebsockets.exceptions.ConnectionClosedError: received 1008 (policy violation) Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
; then sent 1008 (policy violation) Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 766, in _main_task\n async with self._client.aio.live.connect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/contextlib.py\", line 210, in __aenter__\n return await anext(self.gen)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/live.py\", line 1115, in connect\n errors.APIError.raise_error(code, reason, None)\n File \"/app/.venv/lib/python3.12/site-packages/google/genai/errors.py\", line 163, in raise_error\n raise cls(status_code, response_json, response)\ngoogle.genai.errors.APIError: 1008 None. Publisher Model
projects/long-sum-481922-s0/locations/us-central1/publishers/google/models/gemini-live-2.5-flash-preview
\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/app/.venv/lib/python3.12/site-packages/livekit/agents/utils/log.py\", line 17, in async_fn_logs\n return await fn(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/app/.venv/lib/python3.12/site-packages/livekit/plugins/google/realtime/realtime_api.py\", line 845, in _main_task\n raise APIConnectionError(message=error_msg) from e\nlivekit.agents._exceptions.APIConnectionError: Failed to connect to Gemini Live\n\nHint: A 1008 policy violation error often indicates that the model name doesn't match the API being used. VertexAI models typically start with 'gemini-live-', while Gemini API models start with 'gemini-2.' or similar. Please verify your model name matches your API configuration.", "pid": 116, "job_id": "AJ_kuqmEdbmkama", "room_id": "RM_hWjQNvqEDMuq", "timestamp": "2026-02-20T094618.854846+00:00"} llm_model = google.realtime.RealtimeModel( instructions=self._instructions, model="gemini-live-2.5-flash-preview", vertexai=True, thinking_config=types.ThinkingConfig(thinking_budget=0), modalities=["TEXT"], ) tts_model = google.beta.GeminiTTS( model="gemini-2.5-flash-preview-tts", voice_name="Autonoe", instructions="Speak in a friendly and engaging tone.", vertexai=True, )
t
Teşekkürler — paylaştığın son hata logu ve konfigürasyonuyla durumu netleştirebildim. Kısa cevap: aldığın 1008 (policy violation) hatası model adı / API uyumsuzluğundan kaynaklanıyor. Aşağıda neden olduğunu, nasıl düzelteceğini ve hemen uygulayabileceğin kesin adımları sade şekilde veriyorum. Neden oluyor (kısa) • Hata mesajı: "Publisher Model `projects/.../models/gemini-live-2.5-flash-preview`" ve "policy violation" — bu genelde model adının kullandığın realtime API ile uyuşmamasından kaynaklanır. • İpucu: Vertex AI realtime modellerinin adları ve Gemini API modellerinin adları farklı formatta olabilir. Realtime (WebSocket) bağlantısına gönderdiğin model adı, o endpoint tarafından desteklenmiyor; bu yüzden sunucu bağlantıyı 1008 ile kapatıyor. Ne düzeltmelisin (adım adım) 1) Model adını ve API türünü eşleştir • Eğer
vertexai=True
kullandığın için Vertex AI realtime API’sine bağlanıyorsun. Vertex AI için model isimleri genelde
gemini-live-…
formatındadır, fakat tam kullanılabilir isimler ve publisher yolunun doğru olması gerekir. • Örnek güvenli kombinasyonlar: ◦ Realtime (Vertex AI) bağlanıyorsan model isminde
gemini-live-...
gibi resmi Vertex model adı olmalı (dokümantasyonda verilen tam name’i kullan). ◦ Eğer Gemini API (non-Vertex) kullanıyorsan, model isimleri
gemini-2.x-...
gibi farklı formatta olabilir ve farklı endpoint gerekir. • Yapılacak: Google Cloud Console veya Vertex AI model listenden tam model resource adını (veya LiveKit dokümantasyonundaki örnek model isimlerini) doğrula ve
model
parametresine tam uygun adı koy. 2) Modalities ve model uyumu • Eğer model native-audio ağırlıklıysa,
modalities=["TEXT"]
isteği policy/compatibility hatası yaratabiliyor. Modalities ile text talep edeceksen modelin gerçekten text-output desteklediğinden emin ol: ◦ Text-only talep etmek istiyorsan text-capable sürümü veya preview modelini (dokümantasyondaki text-capable model adı) kullan. ◦ Native audio-only model kullanıyorsan text istemeye çalışma. 3) Örnek doğru yapılandırma (Vertex AI, text-only LLM + GeminiTTS) • Güvenli yol: LLM’i text-only çalıştırıp TTS’i ayrı kullan.
Copy code
llm_model = google.realtime.RealtimeModel(
    model="gemini-live-2.5-flash-preview",  # <-- burayı Vertex Console'daki tam, desteklenen model adıyla doğrula
    vertexai=True,
    modalities=["text"],  # model text üretmeyi desteklemeli
    thinking_config=types.ThinkingConfig(thinking_budget=0),
)

tts_model = google.beta.GeminiTTS(
    model="gemini-2.5-flash-preview-tts",
    voice_name="Autonoe",
    vertexai=True,
)

session = AgentSession(llm=llm_model, tts=tts_model, ...)
• Önemli: yukarıdaki
model
isimlerini kullanmadan önce Vertex AI’daki tam model sürüm ismini (Console veya Google doc) doğrula. Hata mesajı model adının API ile uyuşmadığını söylüyor; bu ad genellikle küçük farklarla yanlış girilmiş olur. 4) Eğer 1008 hatasını alırsan kontrol et • GOOGLE_APPLICATION_CREDENTIALS doğru mu? • Proje/konum (project/location) ayarları doğru mu? Bazı model erişimleri proje/konum bağlamında kısıtlıdır. • Modelin bulunduğu publisher / region, kullandığın endpoint ile uyuşuyor mu? 5) Özet çözüm yolu (önerilen sıra) • A) Vertex Console/Docs’tan kullanmak istediğin Gemini Live modelinin tam adı ve bu modelin text-capable olup olmadığını doğrula. • B) Eğer text-capable ise
modalities=["text"]
olarak kullan; session’a
tts=GeminiTTS(...)
ekle. • C) Eğer model native-audio-only ise text talep etme; ya native audio-only akışı kullan ya da text-output için başka model seç. • D) AgentSession’u güncelle, ardından
session.say(closing_message)
kullanıp
await handle.wait_for_playout()
ile hangup yap. İstersen ben yardımcı olayım • Eğer paylaşırsan şu bilgileri kontrol edip net cevap veririm: a. Google Cloud / Vertex Console’daki model tam resource adı (veya hangi model adını kullandığını tam string olarak). b. Kullanılan GCP proje ve location (gizli tutacağın kısımları maskele). c. Mevcut AgentSession oluşturma kodunun tam halini (senin verdiğin kısmın tamamı). • Bunları paylaşırsan sana tam çalışır bir AgentSession örneği ve hangi model adını koyman gerektiğini vereyim. Hızlıca bunu düzeltip test edebilesin.