Est ce que il existe un event qui permet de savoir...
# ask-ai
g
Est ce que il existe un event qui permet de savoir que le tts a fini de parler à chaque tour ?
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.
Merci — vous demandez s’il existe un événement qui permet de savoir quand le TTS a fini de parler à chaque tour. Oui, il y a deux façons pratiques de le détecter. 1) Utiliser
SpeechHandle.wait_for_playout()
(recommandé) • Les appels
session.say()
ou
session.generate_reply()
renvoient un objet
SpeechHandle
. • En faisant
await handle.wait_for_playout()
, votre code attendra que la lecture audio soit complètement terminée. • Exemple :
Copy code
handle = session.say("Bonjour, comment puis-je vous aider ?")
await handle.wait_for_playout()
<http://logger.info|logger.info>("L'agent a fini de parler")
• Vous pouvez vérifier si la lecture a été interrompue via
handle.interrupted
. 2) Utiliser un callback pour ne pas bloquer l’exécution • Si vous préférez ne pas await la fin, attachez un callback qui sera appelé quand la lecture est terminée :
Copy code
def on_playout_complete(handle):
    <http://logger.info|logger.info>(f"Lecture terminée, interrompue: {handle.interrupted}")

handle = session.say("Traitement en cours...")
handle.add_done_callback(on_playout_complete)
Remarque importante : l’indicateur
final
des événements de transcription signifie seulement que la transcription est complète — il n’indique pas la fin de la lecture audio. Pour informer des clients web ou autres participants, vous pouvez aussi émettre un attribut de participant ou un message de données une fois que
wait_for_playout()
se termine ou depuis le callback. Souhaitez-vous un exemple adapté à votre stack (Python vs JavaScript) ou un modèle de message pour prévenir les clients web ? Sources: How to detect when an agent has finished speaking | LiveKit
g
J’utilise agent session
t
Parfait — puisque vous utilisez une agent session, les mécanismes que j’ai décrits s’appliquent directement. Pour être sûr de vous donner l’exemple le plus utile : quel langage utilisez-vous avec l’agent session — Python ou JavaScript ? En résumé rapide (applicable à agent session) : • Utilisez
SpeechHandle.wait_for_playout()
pour attendre que la lecture TTS soit complètement terminée après chaque appel
session.say()
ou
session.generate_reply()
. • Ou utilisez
handle.add_done_callback(...)
si vous préférez un comportement non-bloquant. • Pour informer les clients web, envoyez un message de données ou mettez à jour un attribut de participant dès que
wait_for_playout()
se termine ou depuis le callback. Dites-moi le langage et si vous voulez : • Un extrait de code complet (Python ou JS), ou • Un exemple montrant comment émettre un message de données / mettre à jour un attribut participant pour prévenir les clients web.
g
Donne moi un exmple en pyton
t
Merci — voici un exemple Python concret montrant comment, avec une
agent session
, détecter précisément quand le TTS a fini de jouer. Le premier exemple utilise
await handle.wait_for_playout()
(recommandé, synchrone/attente). Le second montre l'approche non-bloquante avec un callback. Les deux exemples montrent aussi comment envoyer un message de données pour prévenir des clients web une fois la lecture terminée. 1) Exemple avec
wait_for_playout()
(await)
Copy code
import asyncio
import logging

logger = logging.getLogger(__name__)

async def run_session_example(session):
    # Exemple : demande au TTS de parler
    handle = session.say("Bonjour, je vous écoute. Que puis-je faire pour vous ?")

    # Attend que la lecture audio soit complètement terminée
    await handle.wait_for_playout()

    # Vérifie si la lecture a été interrompue
    if getattr(handle, "interrupted", False):
        <http://logger.info|logger.info>("La lecture TTS a été interrompue par l'utilisateur.")
    else:
        <http://logger.info|logger.info>("La lecture TTS est terminée.")

    # Optionnel : informer les clients web via un message de données
    # (remplacez 'data' et 'target' par ce qui convient à votre application)
    try:
        session.send_data({"type": "tts_playout_complete", "interrupted": handle.interrupted})
    except Exception:
        # Si send_data n'existe pas dans votre wrapper, envoyez via l'API client que vous utilisez
        logger.debug("Impossible d'envoyer le message de données — adaptez selon votre client.")
2) Exemple non-bloquant avec callback (
add_done_callback
)
Copy code
import logging

logger = logging.getLogger(__name__)

def on_playout_complete(handle):
    # Cette fonction est appelée quand la lecture se termine
    interrupted = getattr(handle, "interrupted", False)
    <http://logger.info|logger.info>(f"Lecture terminée. Interrompue: {interrupted}")

    # Optionnel : informer les clients web
    try:
        # Ici on suppose l'existence d'un lien vers la session depuis le handle ou scope externe
        # Par exemple, si vous capturez `session` dans une closure, appelez session.send_data(...)
        session.send_data({"type": "tts_playout_complete", "interrupted": interrupted})
    except Exception:
        logger.debug("Envoyer message de données échoué — adaptez selon votre implémentation.")

def start_speaking(session):
    handle = session.say("Je traite votre demande, un instant s'il vous plaît.")
    handle.add_done_callback(on_playout_complete)
    # Le flow principal continue sans attendre la fin de la lecture
Remarques importantes et conseils pratiques •
handle.interrupted
indique si la lecture a été interrompue. Utilisez-le si vous voulez traiter différemment une lecture interrompue. •
wait_for_playout()
bloque la coroutine courante jusqu'à la fin de la lecture ; utilisez-le quand vous voulez séquencer logiquement les tours (par ex. attendre la fin du TTS avant d'écouter l'utilisateur). • Le callback est utile si vous voulez que votre boucle principale continue à tourner (par ex. pour gérer plusieurs sessions simultanées). • Pour informer les clients web, utilisez votre mécanisme de messagerie en temps réel (ex : messages de données LiveKit, attributs participant, WebSocket, etc.). Dans les exemples ci‑dessus, j'ai utilisé
session.send_data(...)
comme placeholder ; adaptez selon votre code existant. Souhaitez-vous que j’adapte cet exemple à votre code concret (partagez un extrait de votre gestion de session) ou que je fournisse un exemple complet avec création/connexion de session ?
g
J utilise agent session et je fais session.start je n ai pas accès à say ou generate a chaque fois comment je fais si je veux que a chaque fois que le tts fini mettre un log
t
Merci — vous utilisez
agent session
avec
session.start
et vous voulez logger à chaque fois que le TTS a fini de parler, même si vous n’appelez pas
say()
directement. Voici ce que vous pouvez faire et un exemple Python concret. Résumé rapide : écoutez l’événement de fin de lecture (playback finished) sur la sortie audio de la session une fois la session démarrée. C’est l’indicateur précis que la lecture TTS est terminée (contrairement au flag
final
de la transcription). 1) Comportement recommandé • Après
await session.start(...)
,
session.output.audio
devient disponible. • Abonnez‑vous à l’événement
playback_finished
pour logger à la fin de chaque playout. 2) Exemple Python (avec logging)
Copy code
import asyncio
import logging

logger = logging.getLogger(__name__)
logging.basicConfig(level=<http://logging.INFO|logging.INFO>)

async def run_agent_session(session, agent, room):
    # Démarre la session (ex: session.start(...))
    await session.start(agent=agent, room=room)

    # session.output.audio est disponible après le start
    audio_output = session.output.audio

    # Définir l'écouteur pour la fin de lecture
    @audio_output.on("playback_finished")
    def on_playback_finished(ev):
        # ev.interrupted indique si la lecture a été interrompue
        interrupted = getattr(ev, "interrupted", False)
        <http://logger.info|logger.info>(f"TTS terminé. Interrompu: {interrupted}")

    # Votre boucle principale ou logique continue ici
    # Par exemple, attendre indéfiniment (ou gérer votre lifecycle)
    try:
        while True:
            await asyncio.sleep(1)
    except asyncio.CancelledError:
        await session.stop()
3) Points importants et variantes • Assurez-vous d’attacher l’écouteur après
session.start()
— avant cela
session.output.audio
peut être None. •
ev.interrupted
vous permet de savoir si la lecture a été interrompue. • Si vous voulez notifier des clients web, envoyez un message de données ou mettez à jour un attribut participant depuis le handler
on_playback_finished
. Par exemple :
Copy code
try:
    session.send_data({"type": "tts_playout_complete", "interrupted": interrupted})
except Exception:
    logger.debug("Adapter l'envoi du message selon votre implémentation.")
• Si votre architecture démarre et arrête plusieurs RoomIO, attachez/détachez l’écouteur au moment opportun pour éviter les handlers dupliqués. Souhaitez‑vous que j’adapte cet exemple à votre code existant ? Par exemple, partagez un extrait montrant comment vous appelez
session.start()
et je vous montrerai exactement où attacher l’écouteur et comment notifier vos clients web. Sources: How to detect when an agent has finished speaking | TTS Metrics | LiveKit Documentation