If yes can you give me an exemple in python is it...
# ask-ai
g
If yes can you give me an exemple in python is it possible to replace sst with an audio-LLMs and directly use it to receive audio and execute the prompt?
t
Thanks for reaching out, Michael. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’ll help with a Python example and a short explanation. You asked whether you can replace STT with an audio-LLM that accepts raw audio and executes prompts directly — yes, you can. LiveKit supports realtime multimodal models via the
RealtimeModel
plugins so you can stream audio straight to a model that does audio understanding and response generation without a separate STT step. Before I give code: could you tell me which provider you want to use (OpenAI Realtime, Azure OpenAI Realtime, Google Gemini Live, or a self-hosted audio-LLM)? If you don’t have a preference, I’ll show a concise example using OpenAI’s Realtime plugin for LiveKit. Below is a minimal Python example using LiveKit’s agent APIs and OpenAI’s Realtime model to receive audio directly, have the model process it, and speak back. This example assumes you already have LiveKit agent libraries installed and credentials configured. 1) Minimal async worker that attaches a realtime audio-capable model and streams audio in/out
Copy code
import asyncio
from livekit.agents import AgentSession, JobContext, WorkerOptions, cli
from livekit.plugins.openai import realtime

# Configure the realtime model to accept audio and produce audio/text
realtime_model = realtime.RealtimeModel(
    voice="alloy",                 # model TTS voice (audio out)
    temperature=0.2,
    instructions="You are a helpful assistant. Answer concisely.",
    # modalities default to audio+text for audio-LLMs that support it
)

async def entrypoint(ctx: JobContext):
    # connect to the LiveKit room and subscribe only to audio
    await ctx.connect(auto_subscribe=ctx.AutoSubscribe.AUDIO_ONLY)

    # create an AgentSession which will route incoming audio to the realtime model
    session = AgentSession(llm=realtime_model)

    # start handling the room (this wires audio in → model and model audio/text → room)
    session.start(ctx.room)

    # Optional: send an initial spoken prompt from the model (TTS)
    await session.generate_reply("Hello — I'm listening. Ask me anything.")

    # Keep the worker running while the room is active
    await ctx.wait_for_room_end()

if __name__ == "__main__":
    cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
2) How this works — short summary • Incoming participant audio is forwarded to the realtime audio-LLM plugin. No separate STT step is required. • The realtime model understands audio directly (so it can use prosody, intent, etc.) and can return text and/or synthesized audio. • You can force the model to return text-only (e.g., if you want to use your own TTS) by configuring the model to output text modalities only. 3) If you want text-only output (use your own TTS)
Copy code
realtime_model = realtime.RealtimeModel(
    modalities=["text"],   # force text responses only
    instructions="Answer in short text form."
)

# Then run TTS (your chosen engine) on the returned text and play into the room.
Next steps / quick questions so I can tailor the example: • Which provider/plugin do you want (OpenAI Realtime, Azure, Gemini Live, or self-hosted)? • Do you want the model to return audio responses directly, or do you prefer the model return text and then use a separate TTS engine? • Are you integrating with an existing LiveKit room or building a new agent worker from scratch? Tell me those details and I’ll provide a focused example (including any required config snippets) for your exact provider and desired flow. Sources: Realtime models overview | LiveKit Documentation | OpenAI Realtime API plugin guide | LiveKit Documentation | Azure OpenAI Realtime API and LiveKit | LiveKit Documentation | Gemini Realtime Agent with Live Vision | LiveKit Documentation | xAI LLM plugin guide | LiveKit Documentation
g
Je prends dans mon cas qwen3 Omni pour audio text et qwentts
t
Super — merci pour la précision. Vous voulez utiliser Qwen3 Omni pour la reconnaissance vocale (audio → texte) et QwenTTS pour la synthèse vocale (texte → audio). Voici comment vous pouvez procéder avec LiveKit et des exemples/conseils en Python. Résumé rapide : Qwen3 Omni et QwenTTS ne figurent pas parmi les plugins TTS/STT fournis en standard. Vous pouvez soit • implémenter des nœuds personnalisés dans le pipeline Agent (intégrer directement les SDK/API Qwen), soit • traiter Qwen3 Omni/QwenTTS en externe et injecter/récupérer l’audio depuis LiveKit (flux entrant/sortant). Avant d’entrer dans un exemple, quelques questions pour adapter la solution : • Avez-vous des SDK Python ou des endpoints HTTP prêts pour Qwen3 Omni et QwenTTS ? • Souhaitez-vous que la reconnaissance soit en temps réel (streaming) ou en segments (upload de petits fichiers) ? • Voulez-vous que la réponse vocale sorte directement dans la salle LiveKit (playback en temps réel) ou soit fournie comme fichier à jouer après génération ? Si vous n’avez pas de contrainte différente, voici deux approches avec exemples succincts en Python. Option A — Intégration via nœuds personnalisés (pipeline Agent) • Idée : étendre/implémenter
stt_node
et
tts_node
dans un Agent pour appeler Qwen3 Omni en streaming et QwenTTS pour synthèse. Cela s’intègre proprement dans le cycle audio de LiveKit. Exemple schématique (structure — à compléter avec vos appels Qwen) :
Copy code
from livekit.agents import Agent, ModelSettings
from typing import AsyncIterable, Optional
import asyncio

class QwenAgent(Agent):
    async def stt_node(self, audio_frames: AsyncIterable, model_settings: ModelSettings) -> Optional[AsyncIterable]:
        # 1) Convertir audio_frames en chunks/support attendu par Qwen3 Omni
        # 2) Stream/POST les chunks à Qwen3 Omni SDK/endpoint
        # 3) Yield/retourner des événements de parole/text à la pipeline LiveKit
        pass

    async def tts_node(self, text_stream: AsyncIterable[str], model_settings: ModelSettings) -> AsyncIterable:
        # 1) Appeler QwenTTS pour chaque texte reçu
        # 2) Récupérer l'audio généré (PCM/opus etc.)
        # 3) Convertir en AudioFrames et yield vers LiveKit pour playback
        pass
Points à implémenter : • Conversion audio <-> format attendu (échantillonnage, PCM, encodage). • Gestion du streaming (si Qwen propose websocket/streaming). • Latence/VAD pour détection de fin de parole si vous voulez réponses rapides. Option B — Pipeline externe + injection audio dans LiveKit • Idée : Recevoir l’audio depuis la room, bufferer/segmenter, appeler Qwen3 Omni (stream ou batch), obtenir texte, envoyer au LLM ou logique métier, générer TTS via QwenTTS, puis jouer l’audio résultant dans la room (publier un track ou streamer dans la session). • Utile si vous préférez garder Qwen hors du runtime Agent ou si vous n’avez pas besoin d’intégration profonde côté nœuds. Schéma minimal pour playback : 1. Subscriber audio → sauvegarde/chunks 2. Appel Qwen3 Omni → texte 3. Traitement / génération réponse 4. Appel QwenTTS → audio (wav/pcm) 5. Publisher audio dans la room (nouveau track) pour que tous entendent Questions pratiques pour fournir code concret • Pouvez-vous partager le type d’API Qwen (HTTP REST, websocket, SDK Python) et exemples d’authentification ? • Souhaitez-vous un exemple complet pour le streaming low-latency (websocket/stream) ou un exemple plus simple en mode “segment/poll” (upload de petits fichiers) ? • Avez-vous besoin d’un exemple montrant la conversion audio (PCM ↔️ LiveKit AudioFrame) ou la manière de publier un track TTS dans la room ? Si vous confirmez que vous avez un SDK HTTP/REST pour Qwen3 Omni et QwenTTS, je peux : • fournir un exemple concret de
stt_node
et
tts_node
en Python en utilisant requests/asyncio (upload de chunks), • ou fournir un exemple de streaming WebSocket si Qwen le propose (basé sur votre info). Dites-moi quelle méthode vous préférez (streaming vs batch) et si vous avez les endpoints/SDK — je vous écris l’exemple adapté. Sources: Speech-to-text (STT) models overview | LiveKit Documentation | Text-to-speech (TTS) models overview | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentation
g
J utilise vllm donc openai compatible et en streaming Je veux le Moins de la latence
t
Parfait — merci pour la précision. Vous utilisez vLLM (OpenAI‑compatible) en streaming et vous voulez la latence la plus faible possible en combinant Qwen3 Omni (audio→texte) et QwenTTS (texte→audio). Voici une solution pratique, axée streaming et faible latence, avec un exemple Python adapté à LiveKit. Résumé rapide • Utilisez vLLM (Qwen3 Omni) exposé via une API OpenAI-compatible pour l’inférence LLM en streaming. • Pour la latence la plus faible, faites la reconnaissance vocale en streaming avec un STT ultra‑faible latence (Deepgram/Flux ou un endpoint Whisper‑style si vous l’avez), envoyez les textes en streaming au vLLM, puis synthétisez la sortie immédiatement via QwenTTS si celui-ci propose un endpoint streaming compatible. • Si QwenTTS n’expose pas d’API de streaming compatible, enveloppez-le dans un microservice qui accepte du text-stream et renvoie de l’audio chunké (PCM/opus) pour publish immédiat dans la room LiveKit. Avant de coder — deux vérifications rapides 1. Qwen3 Omni (vLLM) est bien accessible via un endpoint OpenAI‑compatible (base_url) en streaming ? 2. QwenTTS propose un endpoint de synthèse en streaming (websocket / SSE / chunked HTTP) ou seulement génération batch (fichiers) ? Répondez oui/non à ces deux points et j’adapte l’exemple. Exemple de flux minimal (architecture) • Participant → LiveKit audio track (webrtc) • LiveKit Agent (subscriber) → stream audio frames vers STT streaming • STT streaming → génère tokens/text partials → forward vers vLLM (streaming) • vLLM génère réponse token par token (stream) → immédiatement envoyé au TTS streaming • TTS streaming → audio chunks → publish comme track dans la room (playback immédiat) Exemple Python (schéma concret, streaming, faible latence) • Hypothèses : vous avez ◦ vLLM OpenAI-compatible à http://localhost:8000/v1 ◦ Un STT streaming compatible (ici on montre Deepgram en exemple) ◦ QwenTTS exposé via un endpoint streaming ou via un wrapper que vous fournirez • L’exemple montre la logique : recevoir partials STT → envoyer au LLM stream → pipe tokens vers TTS stream → publish audio chunks.
Copy code
import asyncio
from livekit.agents import AgentSession, JobContext, WorkerOptions, cli
from livekit.plugins import openai, deepgram  # exemples de plugins existants
import aiohttp

# Configuration endpoints
VLLM_BASE = "<http://localhost:8000/v1>"         # vLLM OpenAI-compatible
QWENTTS_BASE = "<http://localhost:9000/tts_stream>"  # endpoint streaming TTS (wrapper si besoin)

# LLM config pointant vers vLLM (OpenAI-compatible)
qwen_llm = openai.LLM(
    model="qwen3-omni",
    base_url=VLLM_BASE,
    api_key=None,   # si vous avez token, mettez-le
    stream=True     # indique qu'on utilisera streaming
)

# STT low-latency (ex: Deepgram flux). Utilisez votre plugin/config STT réel.
stt = deepgram.STT(model="flux")

async def tts_stream_to_livekit(session, text_stream_async_iterable):
    """
    Exemple de wrapper simple pour envoyer texte en streaming à QwenTTS
    et recevoir des chunks audio (PCM/opus) renvoyés vers LiveKit.
    Implémentez votre conversion vers AudioFrames selon vos besoins.
    """
    async with aiohttp.ClientSession() as http:
        # Exemple POST streaming (adapté à votre API)
        async with <http://http.post|http.post>(QWENTTS_BASE, data=text_stream_generator(text_stream_async_iterable)) as resp:
            async for chunk in resp.content.iter_chunked(4096):
                # Convertir chunk -> AudioFrame et publier dans la room
                # session.publish_audio_chunk(chunk)  # pseudo-fonction à implémenter
                pass

def text_stream_generator(text_iterable):
    """Convertit un AsyncIterable[str] en bytes pour l'endpoint TTS streaming."""
    async def _gen():
        async for t in text_iterable:
            yield t.encode("utf-8")
    return _gen()

async def entrypoint(ctx: JobContext):
    await ctx.connect(auto_subscribe=ctx.AutoSubscribe.AUDIO_ONLY)

    # Crée la session agent avec STT + LLM. On laisse TTS en externe pour contrôle.
    agent_session = AgentSession(stt=stt, llm=qwen_llm, preemptive_generation=True)

    agent_session.start(ctx.room)

    # Exemple: si vLLM renvoie stream text partials, vous devez les récupérer
    # et forwarder vers tts_stream_to_livekit pour synthèse immédiate.
    # L'API AgentSession/LLM expose callbacks/events pour partials -> abonnez-vous.
    # Pseudo-code d'abonnement :
    async def on_llm_partial(token: str):
        # buffer tokens / or forward token-to-tts immediately
        await send_token_to_tts(token)  # implémentez streaming vers QwenTTS

    # Assurez-vous d'attacher le callback sur l'objet LLM/session (pseudo)
    qwen_llm.on_partial = on_llm_partial

    await ctx.wait_for_room_end()

if __name__ == "__main__":
    cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
Points de mise en œuvre importants pour la latence minimale • Preemptive generation : commencer à générer réponse pendant que l’utilisateur parle. • Token streaming : utiliser le stream token‑by‑token du vLLM et envoyer ces tokens immédiatement au TTS chunker. • TTS streaming : TTS doit renvoyer audio chunké (opus/pcm) afin de publier sans attendre fichier complet. • VAD et small buffers : réduire la taille de buffer audio envoyé au STT (ex : 100–200 ms) et utiliser VAD pour couper les silences. • Co‑localisation : déployer vLLM, TTS et l’agent dans la même région/host pour réduire RTT. • Format audio cohérent : utilisez le même sample rate et encodage attendu par les composants (ex : 16k/16bit PCM ou opus). Si QwenTTS n’a pas d’API streaming • Créez un petit wrapper qui expose une route websocket/SSE acceptant des fragments textuels et qui renvoie des chunks audio générés progressivement. • Ce wrapper appelle QwenTTS synchronously/async en petits lots et stream les résultats au client LiveKit. Questions rapides pour finaliser un exemple complet 1. QwenTTS propose-t‑il déjà un endpoint streaming (websocket / SSE) ? 2. Souhaitez-vous un exemple complet montrant la conversion chunk→AudioFrame et la publication d’un track LiveKit (je peux fournir le code de conversion PCM→AudioFrame) ? 3. Voulez‑vous que j’écrive un exemple de wrapper pour QwenTTS (websocket) qui fait du streaming si vous ne l’avez pas ? Dites‑moi les réponses; je vous fournis le code détaillé et adapté (wrapper TTS si nécessaire, conversion audio → AudioFrame, et la logique exacte pour forwarder les tokens du vLLM vers le TTS en temps réel). Sources: Models overview | LiveKit Documentation | Agent Builder | LiveKit Documentation