Passer à la navigation

Diarisation des locuteurs

Ce guide explique comment identifier les personnes qui parlent dans des transcriptions en temps réel avec l’API Realtime Speech to Text.

Guide pratique · Suppose que vous avez suivi le guide sur le streaming côté client ou le streaming côté serveur.

Vue d’ensemble

La diarisation des locuteurs attribue des identifiants de locuteur aux mots afin de distinguer qui a dit quoi. Lorsque la diarisation est activée, les transcriptions partielles incluent des étiquettes de locuteur provisoires, et chaque transcription validée est suivie d’un événement diarized_transcript distinct. Les étiquettes de locuteur peuvent changer à mesure que davantage d’audio arrive.

Activer la diarisation

Définissez le paramètre de requête booléen diarize=true lors de l’ouverture d’une connexion WebSocket avec model_id=scribe_v3_live. La diarisation est désactivée (false) par défaut.

Les exemples côté serveur suivants ouvrent une connexion et reçoivent des événements. Installez websockets pour Python, ou ws et la dépendance de développement @types/ws pour TypeScript. Définissez ELEVENLABS_API_KEY dans l’environnement de votre serveur ; les exemples l’envoient dans l’en-tête xi-api-key. Conservez cette clé sur le serveur, et non dans le code du navigateur.

Ces exemples n’envoient pas d’audio. Intégrez-les à votre producteur audio à partir du guide de streaming côté serveur : envoyez des messages input_audio_chunk sur la même connexion tout en recevant les événements. Les exemples sélectionnent pcm_16000, utilisez donc un format audio correspondant. En Python, exécutez la tâche d’envoi audio simultanément avec la boucle de réception ; en TypeScript, envoyez l’audio après l’ouverture de la connexion.

import asyncio
import json
import os
from websockets.asyncio.client import connect
async def main():
url = (
"wss://api.elevenlabs.io/v1/speech-to-text/realtime"
"?model_id=scribe_v3_live&audio_format=pcm_16000&diarize=true"
)
headers = {"xi-api-key": os.environ["ELEVENLABS_API_KEY"]}
async with connect(url, additional_headers=headers) as websocket:
async for message in websocket:
event = json.loads(message)
print(event)
if __name__ == "__main__":
asyncio.run(main())

Gérer les événements

Transcriptions partielles

Lorsque la diarisation est activée, chaque partial_transcript inclut des words provisoires avec la même structure de mot que la transcription par lots. Le speaker_id de chaque mot est speaker_0, speaker_1, etc. une fois le locuteur identifié, ou null tant qu’il n’est pas résolu.

Considérez ces mots comme provisoires : les identifiants de locuteur et les horodatages peuvent changer avec l’arrivée de davantage d’audio. Les mots qui n’ont pas encore été alignés ne disposent pas d’horodatages (start et end sont null ou absents).

Transcriptions validées et diarées

La diarisation ne retarde pas committed_transcript. Lorsque la diarisation est activée, cet événement ajoute un entier segment_index à partir de zéro :

{
"message_type": "committed_transcript",
"segment_index": 0,
"text": "Hello."
}

Chaque validation est suivie d’un événement diarized_transcript distinct avec les champs segment_index, text et words correspondants :

{
"message_type": "diarized_transcript",
"segment_index": 0,
"text": "Hello.",
"words": [
{
"text": "Hello.",
"speaker_id": "speaker_0"
}
]
}

Le mot ci-dessus n’affiche que le texte et l’étiquette du locuteur. La structure complète d’un mot utilise les mêmes champs start, end, type, logprob et characters que la transcription par lots, ainsi que speaker_id. Un locuteur non résolu possède un identifiant de locuteur null.

Les transcriptions diarées sont envoyées dans l’ordre de validation. Associez-les aux transcriptions validées à l’aide de segment_index, plutôt qu’en utilisant le texte ou l’événement reçu suivant. Un diarized_transcript est toujours envoyé pour chaque validation, même si l’identification du locuteur échoue ; dans ce cas, les identifiants de locuteur non résolus sont null.

Fusions de locuteurs

Un événement speakers_merged signifie que deux identifiants de locuteur renvoient à la même personne :

{
"message_type": "speakers_merged",
"from_speaker_id": "speaker_1",
"to_speaker_id": "speaker_0"
}

Remplacez chaque utilisation antérieure de from_speaker_id par to_speaker_id dans les transcriptions partielles comme diarées. Les identifiants de locuteur ne sont jamais réutilisés. Les fusions peuvent s’enchaîner, appliquez-les donc dans l’ordre de réception : si speaker_2 fusionne avec speaker_1, puis que speaker_1 fusionne avec speaker_0, tous les mots précédents associés à ces deux identifiants doivent être étiquetés speaker_0.

Par exemple, appelez ce gestionnaire pour chaque événement reçu. Ici, transcript_history stocke chaque transcription partielle et diarée conservée par l’application, y compris les instantanés partiels antérieurs. Chaque fusion met à jour tous les mots stockés sur place, de sorte que les fusions en chaîne mettent également à jour les mots précédemment fusionnés. Affichez les étiquettes de locuteur depuis ce stockage mis à jour ; les étiquettes null restent null.

transcript_history = []
def handle_event(event):
if event["message_type"] in ("partial_transcript", "diarized_transcript"):
transcript_history.append(event)
elif event["message_type"] == "speakers_merged":
for transcript in transcript_history:
for word in transcript.get("words") or []:
if word.get("speaker_id") == event["from_speaker_id"]:
word["speaker_id"] = event["to_speaker_id"]

Limites

  • La diarisation est prise en charge uniquement par scribe_v3_live. Les autres modèles renvoient une erreur invalid_request avec le message "The 'diarize' parameter is only supported by scribe_v3_live.", puis ferment la connexion.
  • La diarisation ne peut pas être combinée avec filter_background_audio. Cette combinaison renvoie une erreur invalid_request dont le message contient "cannot be combined with filter_background_audio", puis ferme la connexion.
  • Les étiquettes de locuteur peuvent rester non résolues (null), et des événements speakers_merged ultérieurs peuvent modifier les étiquettes précédentes. Ces événements de fusion sont envoyés uniquement lorsque la diarisation est activée.