> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Diarização de locutores

> **Note**
>
> **Guia prático** · Pressupõe que você concluiu o guia de
> [streaming no cliente](/docs/pt/eleven-api/guides/how-to/speech-to-text/realtime/client-side-streaming) ou de
> [streaming no servidor](/docs/pt/eleven-api/guides/how-to/speech-to-text/realtime/server-side-streaming).

## Visão geral

A diarização de locutores atribui IDs de locutor às palavras para que você possa distinguir quem disse o quê. Com a diarização ativada, as transcrições parciais incluem rótulos provisórios de locutor, e cada transcrição confirmada é seguida por um evento `diarized_transcript` separado. Os rótulos de locutor podem mudar à medida que mais áudio é recebido.

## Ativando a diarização

Defina o parâmetro booleano de consulta `diarize=true` ao abrir uma conexão WebSocket com `model_id=scribe_v3_live`. Por padrão, a diarização é `false`.

Os exemplos a seguir no servidor abrem uma conexão e recebem eventos. Instale `websockets` para Python ou `ws` e a dependência de desenvolvimento `@types/ws` para TypeScript. Defina `ELEVENLABS_API_KEY` no ambiente do seu servidor; os exemplos a enviam no cabeçalho `xi-api-key`. Mantenha essa chave no servidor, e não no código do navegador.

Estes exemplos não enviam áudio. Integre-os ao seu produtor de áudio usando o [guia de streaming no servidor](/docs/pt/eleven-api/guides/how-to/speech-to-text/realtime/server-side-streaming): envie mensagens `input_audio_chunk` na mesma conexão enquanto recebe eventos. Os exemplos selecionam `pcm_16000`, então use áudio compatível. Em Python, execute a tarefa de envio de áudio simultaneamente ao loop de recebimento; em TypeScript, envie o áudio depois que a conexão for aberta.

```python
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())
```

```typescript
import WebSocket from "ws";

const apiKey = process.env.ELEVENLABS_API_KEY;
if (!apiKey) {
  throw new Error("Set ELEVENLABS_API_KEY in your server environment.");
}

const websocket = new WebSocket(
  "wss://api.elevenlabs.io/v1/speech-to-text/realtime" +
    "?model_id=scribe_v3_live&audio_format=pcm_16000&diarize=true",
  { headers: { "xi-api-key": apiKey } }
);

websocket.on("message", (message) => {
  const event = JSON.parse(message.toString());
  console.log(event);
});

websocket.on("error", (error) => {
  console.error(error);
});
```

## Como processar eventos

### Transcrições parciais

Com a diarização ativada, cada `partial_transcript` inclui `words` provisórias no mesmo formato de palavras da transcrição em lote. O `speaker_id` de cada palavra é `speaker_0`, `speaker_1` e assim por diante quando um locutor é identificado, ou `null` enquanto não for resolvido.

Trate essas palavras como provisórias: os IDs de locutor e os carimbos de data e hora podem mudar com mais áudio. Palavras que ainda não foram alinhadas não têm carimbos de data e hora (`start` e `end` são `null` ou estão ausentes).

### Transcrições confirmadas e diarizadas

A diarização não atrasa o `committed_transcript`. Com a diarização ativada, esse evento adiciona um `segment_index` inteiro baseado em zero:

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

Cada confirmação é seguida por um evento `diarized_transcript` separado com os `segment_index`, `text` e `words` correspondentes:

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

A palavra acima mostra apenas o texto e o rótulo de locutor. O formato completo da palavra usa os mesmos campos `start`, `end`, `type`, `logprob` e `characters` da transcrição em lote, além de `speaker_id`. Um locutor não resolvido tem um ID de locutor `null`.

As transcrições diarizadas são enviadas na ordem de confirmação. Relacione-as às transcrições confirmadas usando `segment_index`, em vez do texto ou do próximo evento recebido. Um `diarized_transcript` é sempre enviado para cada confirmação, mesmo que a identificação do locutor falhe; nesse caso, os IDs de locutor não resolvidos são `null`.

### Mesclagens de locutores

Um evento `speakers_merged` significa que dois IDs de locutor se referem à mesma pessoa:

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

Substitua cada uso anterior de `from_speaker_id` por `to_speaker_id` nas transcrições parciais e diarizadas. Os IDs de locutor nunca são reutilizados. As mesclagens podem formar uma cadeia, então aplique-as na ordem em que forem recebidas: se `speaker_2` for mesclado em `speaker_1` e depois `speaker_1` for mesclado em `speaker_0`, todas as palavras anteriores de ambos os IDs deverão acabar com o rótulo `speaker_0`.

Por exemplo, chame este manipulador para cada evento recebido. Aqui, `transcript_history` armazena todas as transcrições parciais e diarizadas mantidas pelo aplicativo, incluindo snapshots parciais anteriores. Cada mesclagem atualiza todas as palavras armazenadas no local, portanto, mesclagens em cadeia também atualizam palavras mescladas anteriormente. Renderize os rótulos de locutor usando esse armazenamento atualizado; os rótulos `null` permanecem `null`.

```python
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"]
```

## Limitações

* A diarização é compatível apenas com `scribe_v3_live`. Outros modelos retornam um erro `invalid_request` com a mensagem `"The 'diarize' parameter is only supported by scribe_v3_live."` e, em seguida, fecham a conexão.
* A diarização não pode ser combinada com `filter_background_audio`. Essa combinação retorna um erro `invalid_request` cuja mensagem contém `"cannot be combined with filter_background_audio"` e, em seguida, fecha a conexão.
* Os rótulos de locutor podem permanecer não resolvidos (`null`), e eventos `speakers_merged` posteriores podem revisar rótulos anteriores. Esses eventos de mesclagem são enviados apenas quando a diarização está ativada.