"""Real-time two-way meeting translation via Gemini Live API. Architecture based on livekit-examples/gemini-live-translate: - Each participant sets `lang` attribute - Agent opens one Gemini Live session per (speaker, target_lang) pair - Publishes audio tracks named tx:{speaker}:{target_lang} - Publishes captions on lk.translation text stream """ from __future__ import annotations import logging import os from dotenv import load_dotenv from livekit.agents import AgentServer, AutoSubscribe, JobContext, cli from gemini.router import TranslationRouter load_dotenv() logger = logging.getLogger("gemini.agent") AGENT_NAME = os.getenv("LIVEKIT_TRANSLATOR_AGENT", "gemini-translator") server = AgentServer() @server.rtc_session(agent_name=AGENT_NAME) async def translator_entrypoint(ctx: JobContext) -> None: api_key = os.environ.get("GEMINI_API_KEY") if not api_key: logger.error("GEMINI_API_KEY is not set; refusing to start") return await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY) try: await ctx.room.local_participant.set_attributes({"lk.agent.state": "listening"}) except Exception as exc: logger.debug("set agent state attr failed: %s", exc) router = TranslationRouter(ctx.room, gemini_api_key=api_key) router.start() ctx.add_shutdown_callback(router.aclose) logger.info("Gemini translation router ready for room=%s", ctx.room.name) if __name__ == "__main__": cli.run_app(server)