> 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.

# Diarizacja mówców

> **Note**
>
> **Przewodnik krok po kroku** · Zakłada, że ukończyłeś(-aś) przewodnik o
> [strumieniowaniu po stronie klienta](/docs/pl/eleven-api/guides/how-to/speech-to-text/realtime/client-side-streaming) lub
> [strumieniowaniu po stronie serwera](/docs/pl/eleven-api/guides/how-to/speech-to-text/realtime/server-side-streaming).

## Omówienie

Diarizacja mówców przypisuje identyfikatory mówców do słów, dzięki czemu możesz rozróżnić, kto co powiedział. Gdy diarizacja jest włączona, częściowe transkrypcje zawierają robocze etykiety mówców, a po każdej zatwierdzonej transkrypcji wysyłane jest osobne zdarzenie `diarized_transcript`. Etykiety mówców mogą się zmieniać w miarę napływania kolejnych nagrań audio.

## Włączanie diarizacji

Podczas otwierania połączenia WebSocket z `model_id=scribe_v3_live` ustaw parametr zapytania logicznego `diarize=true`. Domyślnie diarizacja ma wartość `false`.

Poniższe przykłady po stronie serwera otwierają połączenie i odbierają zdarzenia. W Pythonie zainstaluj `websockets`, a w TypeScript `ws` oraz zależność deweloperską `@types/ws`. Ustaw `ELEVENLABS_API_KEY` w środowisku serwera; przykłady wysyłają go w nagłówku `xi-api-key`. Przechowuj ten klucz na serwerze, a nie w kodzie przeglądarki.

Te przykłady nie wysyłają audio. Połącz je ze źródłem audio, korzystając z [przewodnika o strumieniowaniu po stronie serwera](/docs/pl/eleven-api/guides/how-to/speech-to-text/realtime/server-side-streaming): wysyłaj wiadomości `input_audio_chunk` przez to samo połączenie podczas odbierania zdarzeń. Przykłady wybierają `pcm_16000`, więc użyj pasującego audio. W Pythonie uruchom zadanie wysyłające audio równolegle z pętlą odbioru; w TypeScript wyślij audio po otwarciu połączenia.

```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);
});
```

## Obsługa zdarzeń

### Częściowe transkrypcje

Gdy diarizacja jest włączona, każda `partial_transcript` zawiera robocze `words` w tym samym formacie słów co transkrypcja wsadowa. Po zidentyfikowaniu mówcy `speaker_id` każdego słowa ma wartość `speaker_0`, `speaker_1` itd., a podczas ustalania mówcy — `null`.

Traktuj te słowa jako wstępne: identyfikatory mówców i znaczniki czasu mogą się zmieniać wraz z kolejnym audio. Słowa, które nie zostały jeszcze wyrównane, nie mają znaczników czasu (`start` i `end` mają wartość `null` lub nie występują).

### Zatwierdzone i udiaryzowane transkrypcje

Diarizacja nie opóźnia `committed_transcript`. Gdy diarizacja jest włączona, to zdarzenie dodaje indeks całkowity od zera `segment_index`:

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

Po każdym zatwierdzeniu wysyłane jest osobne zdarzenie `diarized_transcript` z pasującymi wartościami `segment_index`, `text` i `words`:

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

Powyższe słowo pokazuje tylko tekst i etykietę mówcy. Pełny format słowa używa tych samych pól `start`, `end`, `type`, `logprob` i `characters` co transkrypcja wsadowa, wraz z `speaker_id`. Nierozpoznany mówca ma identyfikator mówcy `null`.

Udiaryzowane transkrypcje są wysyłane w kolejności zatwierdzania. Łącz je z zatwierdzonymi transkrypcjami za pomocą `segment_index`, a nie tekstu ani kolejnego odebranego zdarzenia. Dla każdego zatwierdzenia zawsze wysyłane jest `diarized_transcript`, nawet jeśli identyfikacja mówcy się nie powiedzie; w takim przypadku nierozpoznane identyfikatory mówców mają wartość `null`.

### Łączenie mówców

Zdarzenie `speakers_merged` oznacza, że dwa identyfikatory mówców odnoszą się do tej samej osoby:

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

Zastąp każde wcześniejsze użycie `from_speaker_id` przez `to_speaker_id` zarówno w częściowych, jak i udiaryzowanych transkrypcjach. Identyfikatory mówców nigdy nie są używane ponownie. Łączenia mogą następować łańcuchowo, więc stosuj je w kolejności odbioru: jeśli `speaker_2` zostanie połączony z `speaker_1`, a potem `speaker_1` z `speaker_0`, wszystkie wcześniejsze słowa z obu identyfikatorów muszą ostatecznie mieć etykietę `speaker_0`.

Na przykład wywołuj ten handler dla każdego odebranego zdarzenia. Tutaj `transcript_history` przechowuje każdą częściową i udiaryzowaną transkrypcję zachowaną przez aplikację, w tym wcześniejsze częściowe wersje. Każde połączenie aktualizuje wszystkie zapisane słowa na miejscu, więc łańcuchowe połączenia aktualizują też wcześniej połączone słowa. Wyświetlaj etykiety mówców z tego zaktualizowanego magazynu; etykiety `null` pozostają `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"]
```

## Ograniczenia

* Diarizacja jest obsługiwana tylko przez `scribe_v3_live`. Inne modele zwracają błąd `invalid_request` z komunikatem `"The 'diarize' parameter is only supported by scribe_v3_live."`, a następnie zamykają połączenie.
* Diarizacji nie można łączyć z `filter_background_audio`. Ta kombinacja zwraca błąd `invalid_request`, którego komunikat zawiera `"cannot be combined with filter_background_audio"`, a następnie zamyka połączenie.
* Etykiety mówców mogą pozostać nierozpoznane (`null`), a późniejsze zdarzenia `speakers_merged` mogą zmienić wcześniejsze etykiety. Te zdarzenia łączenia są wysyłane tylko wtedy, gdy diarizacja jest włączona.