Assist Speaker ID

Rozpoznawanie domowników po głosie dla Assista w Home Assistant. Asystent wie, kto pyta, i odpowiada właśnie tej osobie. Wszystko działa lokalnie.

Polski · English · GitHub

1. Co to jest i po co

Assist zamienia mowę na tekst, ale nie wie, kto mówi. Satelity głosowe (Home Assistant Voice PE, ESPHome) wysyłają polecenie bez użytkownika, więc dla Home Assistant każde zdanie jest anonimowe. Kłopot pojawia się przy pytaniach w pierwszej osobie:

Whisper i inne modele zamiany mowy na tekst nie rozpoznają mówcy. Diaryzacja (np. WhisperX) odpowiada tylko na pytanie „kto kiedy mówił” z anonimowymi etykietami, a nie „który to domownik”. Assist Speaker ID dokłada brakujący element: zamienia głos na „odcisk” (wektor liczb), porównuje go z zapisanymi wzorcami domowników i przekazuje wynik dalej – agentowi konwersacji, modelowi LLM i automatyzacjom.

Projekt składa się z dwóch części w jednym repozytorium:

CzęśćCo robiInstalacja
Usługa wyoming-speaker-id Pośrednik Wyoming przed Twoim serwerem zamiany mowy na tekst (np. Whisper). Przekazuje dźwięk dalej bez zmian, a równolegle liczy odcisk głosu i dopisuje mówcę do wyniku. dodatek HA albo kontener Docker na innym komputerze
Integracja Assist Speaker ID Encja zamiany mowy na tekst „Mowa na tekst z mówcą”, agent-opakowanie „Agent z mówcą”, sensor „Ostatni mówca”, akcje do nagrywania wzorców, kalibracji i ogłoszeń. HACS (repozytorium niestandardowe, typ „Integracja”)

Najwięcej daje w parze z Assist Routerem: on używa mówcy do pytań w pierwszej osobie, pokoju mówcy, określeń rodzinnych („mój brat”), odpowiedzi na „Kto to mówi?” i ogłoszeń. Assist Speaker ID działa jednak z każdym agentem.

2. Jak działa

Satelita słowo wybudzające, dźwięk HA: „Mowa na tekst z mówcą” encja STT integracji wyoming-speaker-id dodatek albo kontener, port 10350 Whisper dźwięk bez zmian → tekst Model głosu CAM++ równolegle, ~90 ms transcript: text + speaker, speaker_score, … tekst identyczny jak z samego Whispera Wynik w bieżącym przebiegu pipeline'u ten sam przebieg: STT → agent „Agent z mówcą” dopisuje „Pyta: Anna.” → dowolny agent Assist Router get_speaker(): „mam”, „mój”, pokój, rodzina, ogłoszenia Sensor „Ostatni mówca” zdarzenie speaker_id_identified → automatyzacje Ostatnie nagranie tylko w RAM, 10 min → próbka albo ogłoszenie
  1. Satelita wykrywa słowo wybudzające i wysyła nagranie polecenia do pipeline'u Assista.
  2. Pipeline używa encji „Mowa na tekst z mówcą” zamiast zwykłego Whispera. Encja rozmawia z usługą przez protokół Wyoming, tak jak wbudowana integracja Wyoming.
  3. Usługa wyoming-speaker-id przekazuje dźwięk do Twojego serwera zamiany mowy na tekst bez żadnych zmian i jednocześnie zbiera go dla siebie. Gdy nagranie się kończy, liczy odcisk głosu w czasie, w którym Whisper i tak jeszcze transkrybuje.
  4. Usługa odsyła ten sam tekst co Whisper, z dopisanymi polami: speaker (id osoby albo unknown), speaker_name, speaker_score, speaker_scores (wyniki wszystkich osób), speech_seconds.
  5. Integracja zapamiętuje mówcę dla bieżącego przebiegu pipeline'u. HA wywołuje zamianę mowy na tekst i agenta w tym samym zadaniu, więc agent dostaje mówcę właśnie tego zdania, a nie zdania z innego pokoju wypowiedzianego w tej samej chwili.
  6. Dalej mówcę mogą wykorzystać: agent-opakowanie, Assist Router albo inny agent przez get_speaker(), a także automatyzacje przez sensor i zdarzenie.

Dlaczego pośrednik, a nie osobny model obok? Klient Wyoming w HA czyta z wyniku tylko tekst, a encja zamiany mowy na tekst nie wie, z której satelity przyszło nagranie. Dlatego usługa dopisuje mówcę do wyniku transkrypcji, a integracja ma własnego klienta, który te pola odczytuje. Zwykły klient Wyoming dodatkowe pola pomija, więc usługę można bez ryzyka wpiąć w miejsce Whispera: w najgorszym razie działa jak sam Whisper.

3. Rozpoznanie od środka

Dźwięk 16 kHz, mono Wykrywanie mowy bez ciszy, do 8 s mowy Model CAM++ sherpa-onnx, CPU Wektor 192 liczby = barwa głosu Porównanie cosinus z każdym wzorcem Anna 0,82 · Kasia 0,41 · Tomek 0,18 · Jan 0,12 1. najlepszy wynik ≥ próg osoby (np. 0,50)? 2. przewaga nad drugą osobą ≥ margines (np. 0,05)? oba „tak” → Anna; inaczej → unknown Wzorzec osoby średnia wektorów z 10–15 nagranych zdań tej osoby zapisana w speakers.json; nagrania nie są przechowywane mniej niż 1 s mowy → zawsze unknown (za mało, by ocenić głos)

Wybór modelu

Przed wyborem porównaliśmy kilka modeli dostępnych w sherpa-onnx. Zestawy testowe: 6 polskich głosów Pipera × 12 zdań oraz nagrania 3 osób z przykładów sherpa-onnx. Dokładność liczona metodą „zostaw jedno nagranie”. EER (equal error rate) to punkt, w którym fałszywe akceptacje równają się fałszywym odrzuceniom – im niżej, tym lepiej.

ModelWymiar3 s mowyPiper: dokładność / EERLudzie: dokładność / EER
3D-Speaker CAM++ zh_en „advanced” (domyślny)19291 ms100% / 0,2%100% / 0%
NeMo TitaNet-small19259 ms100% / 0,9%100% / 0%
3D-Speaker ERes2Net (VoxCeleb)192218 ms100% / 1,9%100% / 0%
WeSpeaker ResNet34-LM256257 ms98,6% / 12,4%92,9% / 15,4%
3D-Speaker CAM++ (VoxCeleb)51290 ms68,1% / 40,8%71,4% / 37,7%

Przez cały łańcuch (Piper → wyoming-speaker-id → Whisper) wszystkie wypowiedzi z co najmniej 1 s mowy zostały przypisane właściwej osobie, z wynikami 0,76–0,92. Inny model można wskazać opcją model (nazwa modelu sherpa-onnx albo ścieżka do pliku .onnx); po zmianie modelu wzorce trzeba nagrać od nowa.

4. Wymagania

Sprawdzone w praktyce: u autora usługa działa na co dzień na NVIDIA Jetson AGX Orin 64 GB, jako kontener obok faster-whisper (Whisper na GPU, model głosu na CPU), dla całej rodziny i 7 satelit. Działa bardzo dobrze: rozpoznanie trwa ok. 90 ms i liczy się w tle transkrypcji, więc polecenia nie są wolniejsze niż z samym Whisperem.

5. Instalacja

Krok 1a: usługa jako dodatek HA

Najprostsza droga, gdy Home Assistant działa jako HA OS albo Supervised.

  1. Ustawienia → Dodatki → Sklep z dodatkami → ⋮ → Repozytoria i dodaj https://github.com/witold-gren/home-assistant-assist-speaker-id.
  2. Zainstaluj Assist Speaker ID (rozpoznawanie mówcy).
  3. W zakładce Konfiguracja ustaw upstream (serwer zamiany mowy na tekst): tcp://core-whisper:10300 dla dodatku Whisper albo adres własnego serwera, np. tcp://192.168.1.10:10300.
  4. Uruchom dodatek. Za pierwszym razem pobierze model (ok. 30 MB). Potem sam zgłosi się Home Assistantowi z losowym tokenem API, a HA zaproponuje integrację (krok 2).
Opcja dodatkuDomyślnieZnaczenie
upstreamtcp://core-whisper:10300serwer Wyoming zamiany mowy na tekst
threshold / margin0,5 / 0,05wspólny próg i przewaga nad drugą osobą (wartości startowe)
min_speech / max_speech1,0 / 8,0 skrótsza mowa daje „nieznany”; ile mowy liczyć
threads2wątki CPU modelu
modelCAM++ zh_eninny model sherpa-onnx (nazwa albo ścieżka)
api_tokenlosowywłasny token API (zwykle niepotrzebny)
debugwyłączoneszczegółowy dziennik

Krok 1b: usługa jako kontener (np. obok Whispera na innym komputerze)

Gdy Whisper działa na osobnej maszynie, najlepiej postawić usługę obok niego. Dźwięk nie przechodzi wtedy dwa razy przez sieć.

git clone https://github.com/witold-gren/home-assistant-assist-speaker-id
docker build -t wyoming-speaker-id home-assistant-assist-speaker-id/speaker_id/
docker run -d --name speaker-id --restart unless-stopped \
  -p 10350:10350 -p 10351:10351 -v speaker-id-data:/data \
  -e SPEAKER_ID_UPSTREAM=tcp://192.168.1.10:10300 \
  -e SPEAKER_ID_API_TOKEN=dlugi-losowy-token \
  wyoming-speaker-id

Ten sam kontener w docker-compose.yaml, obok Whispera:

services:
  whisper:
    image: rhasspy/wyoming-whisper
    # … Twoja dotychczasowa konfiguracja
  speaker-id:
    build: ./home-assistant-assist-speaker-id/speaker_id
    restart: unless-stopped
    ports: ["10350:10350", "10351:10351"]
    volumes: ["./speaker-id/data:/data"]
    environment:
      SPEAKER_ID_UPSTREAM: tcp://whisper:10300
      SPEAKER_ID_API_TOKEN: dlugi-losowy-token
ZmiennaDomyślnieZnaczenie
SPEAKER_ID_UPSTREAM(wymagana)serwer Wyoming zamiany mowy na tekst
SPEAKER_ID_THRESHOLD / SPEAKER_ID_MARGIN0.5 / 0.05wspólny próg i margines
SPEAKER_ID_MIN_SPEECH / SPEAKER_ID_MAX_SPEECH1.0 / 8.0minimum mowy i ile mowy liczyć (sekundy)
SPEAKER_ID_MODELCAM++ zh_ennazwa modelu sherpa-onnx albo ścieżka
SPEAKER_ID_API_TOKENbraktoken API HTTP; bez niego trzymaj port 10351 wyłącznie w sieci domowej
SPEAKER_ID_THREADS, SPEAKER_ID_DEBUG2, 0wątki modelu, szczegółowy dziennik

Port 10350 to Wyoming (zamiana mowy na tekst z mówcą), port 10351 to API HTTP (wzorce, kalibracja, ostatnie nagranie).

Krok 2: integracja

  1. HACS → ⋮ → Repozytoria niestandardowe → dodaj adres repozytorium, typ Integracja. Zainstaluj Assist Speaker ID i zrestartuj HA.
  2. Z dodatkiem: HA sam pokaże wykrytą integrację w Ustawienia → Urządzenia i usługi. Kliknij Konfiguruj.
  3. Z kontenerem: Ustawienia → Urządzenia i usługi → Dodaj integrację → Assist Speaker ID i podaj host, port Wyoming (10350), port API (10351) i token.

Integracja tworzy urządzenie „Assist Speaker ID” z encją zamiany mowy na tekst „Mowa na tekst z mówcą”, agentem „Agent z mówcą” i sensorem „Ostatni mówca”.

Opcje integracji (Konfiguruj) to menu z dwiema pozycjami:

6. Ustawienie pipeline'u

Ustawienia → Asystenci głosowi → wybierz pipeline (asystenta) każdej satelity:

  1. Zamiana mowy na tekst: „Mowa na tekst z mówcą”. Język ustaw taki jak dotąd w Whisperze.
  2. Agent konwersacji:
    • Assist Router albo inny agent, który sam czyta mówcę, albo
    • „Agent z mówcą”, który dopisze mówcę dowolnemu agentowi (wybranemu w opcjach integracji).
  3. Wyłącz „Preferuj obsługę poleceń lokalnie” (Prefer handling commands locally).

Dlaczego wyłączyć obsługę lokalną? Gdy jest włączona, HA najpierw próbuje własnych intencji, zanim zapyta agenta. Wtedy wbudowana intencja rozgłaszania złapie „Ogłoszenie, …” i przeczyta tekst syntezą zamiast Twojego nagrania, a podczas nagrywania wzorców agent nie zdąży odpowiedzieć krótkim „Nagrano 3 z 10”. Assist Router i „Agent z mówcą” i tak przekazują HA wszystko, co HA rozumie, więc zwykłe polecenia działają dalej.

Przełączaj satelity po jednej. Gdyby coś nie działało, wystarczy w pipeline'ie wrócić do zwykłego Whispera.

Sprawdzenie: Ustawienia → Asystenci głosowi → pipeline → ⋮ → Debugowanie. Po poleceniu ze satelity sensor „Ostatni mówca” pokazuje unknown (nie ma jeszcze wzorców), a atrybut speech_seconds długość mowy. To znak, że dźwięk przechodzi przez usługę.

7. Nagrywanie wzorców głosu

Każdy domownik nagrywa 10–15 zwykłych zdań. Najwygodniej robi to nagrywanie prowadzone: satelita sama prosi o kolejne zdania, bez słowa wybudzającego.

  1. Narzędzia deweloperskie → Akcje → speaker_id.start_enrollment:
    action: speaker_id.start_enrollment
    data:
      speaker: anna            # id osoby: małe litery, bez spacji
      name: Anna               # nazwa wypowiadana i wyświetlana
      count: 10
      satellite: assist_satellite.salon   # satelita, przy której stoi Anna
  2. Satelita mówi: „Nagrywam wzorzec głosu: Anna. Powiedz zwykłe polecenie, na przykład: jaka będzie jutro pogoda.” i słucha.
  3. Anna mówi dowolne zdanie, np. „Jaka będzie jutro pogoda w Krakowie?”. Polecenie nie jest wykonywane; satelita od razu odpowiada „Nagrano 1 z 10. Kolejne zdanie.” i słucha dalej.
  4. Za krótkie zdanie (poniżej 1,5 s mowy) nie liczy się – satelita poprosi o dłuższe. Po ciszy albo urwanej rozmowie sama zapyta ponownie, a po 3 próbach bez nowej próbki zakończy.
  5. Po ostatniej próbce: „Gotowe, nagrano 10 próbek głosu: Anna.”. Wzorzec działa od razu.

Bez pola satellite nagrywanie też działa, ale każde zdanie zaczyna się od słowa wybudzającego. Postęp widać w atrybucie enrollment sensora „Ostatni mówca”. Przerwanie: speaker_id.stop_enrollment.

Nieudane nagrywanie? Dograj próbki tą samą akcją (nowe dochodzą do starych) albo zacznij od zera: speaker_id.delete_speaker i nagrywanie jeszcze raz. Pojedyncze zdanie dodasz po fakcie akcją speaker_id.add_last_sample: ostatnia wypowiedź (najwyżej sprzed 10 min) staje się próbką wskazanej osoby.

Dobre próbki: nagrywaj przez tę satelitę i z tej odległości, z której domownik zwykle mówi – mikrofon i pomieszczenie zmieniają głos bardziej niż słowa. Używaj zwykłych poleceń po kilka słów, zwykłym tonem (krzyk, szept i śmiech zaniżają wyniki). Nagraj wszystkich domowników, zanim zaczniesz kalibrować. Głosy dzieci zmieniają się z wiekiem, więc co kilka miesięcy dograj im nowe próbki.

8. Wyniki, progi i kalibracja

Podobieństwo

Każda wypowiedź jest porównywana z wzorcem każdej osoby. Wynik to podobieństwo, zwykle od 0 do 1 (w odpowiedzi na „Kto to mówi?” podawane w procentach):

PodobieństwoCo zwykle oznacza (CAM++, mikrofon satelity)
0,75–0,95ta sama osoba, dobre warunki
0,55–0,75ta sama osoba, ale krótko, z daleka, w hałasie albo innym tonem
0,35–0,55podobny głos, często rodzeństwo albo rodzic i dziecko tej samej płci
0–0,35inna osoba

To nie jest „unikatowość” głosu. Wysoki wynik oznacza tylko, że ta wypowiedź jest bardzo podobna do tego wzorca.

Próg i margines

Najlepiej pasująca osoba zostaje rozpoznana tylko wtedy, gdy spełnia oba warunki:

  1. podobieństwo ≥ próg tej osoby (jej własny albo wspólny, gdy własnego nie ma);
  2. podobieństwo − wynik drugiej osoby ≥ margines. Przy dwóch prawie równych wynikach lepiej powiedzieć „nie wiem”, niż zgadywać.

Inaczej mówca jest „nieznany” (unknown), a Assist działa tak, jakby rozpoznawania nie było. Pomyłka jest gorsza niż brak rozpoznania, więc domyślnie system jest ostrożny.

0 0,25 0,50 0,75 1 cudze próbki others_max 0,31 próbki Tomka own_min 0,71 próg 0,54 przerwa = zapas Tomek 0,82, Anna 0,30 → Tomek 0,82 ≥ 0,54 i przewaga 0,52 ≥ margines 0,05 Kasia 0,62, Jan 0,59 → unknown próg spełniony, ale przewaga 0,03 < margines 0,05
ParametrDomyślnieGdzie zmienić
Próg wspólny0,50opcje integracji → Progi rozpoznawania
Próg osobybrak = wspólnyopcje integracji, akcja speaker_id.set_speaker, kalibracja z apply: true
Margines0,05opcje integracji
Minimum mowy1,0 sopcje integracji; krótsza wypowiedź = zawsze „nieznany”

Wartości z opcji integracji są zapisane w usłudze (speakers.json) i mają pierwszeństwo przed opcjami dodatku i zmiennymi środowiska. Te są tylko wartościami startowymi.

Kalibracja

Akcja speaker_id.calibrate porównuje próbki każdej osoby z jej wzorcem i z próbkami pozostałych osób, a potem proponuje próg. Z apply: true od razu zapisuje progi osób.

Pole raportuZnaczenie
samplesliczba próbek
own_minnajgorsza własna próbka: podobieństwo do wzorca z pozostałych próbek tej osoby
own_p1010. percentyl: 9 na 10 własnych próbek jest co najmniej tak podobnych
own_meanśrednie podobieństwo własnych próbek
others_maxnajbardziej podobna cudza próbka
separabletrue, gdy own_min > others_max: żadna cudza próbka nie zbliżyła się do najgorszej własnej
suggested_thresholdśrodek między own_p10 a others_max (w zakresie 0,2–0,9)

Przykład (Tomek, dorosły):

samples: 10
own_min: 0.709      # najgorsza własna próbka: 71% podobieństwa do wzorca
own_p10: 0.778      # 9 z 10 własnych próbek ma co najmniej 78%
own_mean: 0.803     # średnio 80%
others_max: 0.305   # najbardziej podobna cudza próbka: tylko 31%
separable: true     # 0.709 > 0.305 - głosy wyraźnie rozdzielone
suggested_threshold: 0.541   # (0.778 + 0.305) / 2

Między najgorszą własną próbką (71%) a najbliższą cudzą (31%) jest 40 punktów przerwy. Każdy próg w przedziale ok. 0,35–0,70 zadziała, a proponowane 0,54 leży pośrodku z zapasem w obie strony. U dziecka może wyjść np. own_p10: 0.74 i others_max: 0.68 (rodzeństwo): próg 0,71 i tylko 6 punktów przerwy. Wtedy warto też podnieść margines.

Podobne głosy (np. rodzeństwo)

  1. Nagraj więcej próbek: 15–20 na osobę, z typowej satelity i odległości.
  2. Kalibruj dopiero po nagraniu wszystkich: others_max liczy się tylko z osób, które mają wzorce.
  3. Przy separable: false często winna jest jedna nieudana próbka (ktoś się wtrącił, hałas). Dograj próbki albo nagraj tę osobę od nowa.
  4. Próg ustaw między others_max a own_p10: bliżej own_p10 to mniej pomyłek, bliżej others_max – mniej „nieznanych”.
  5. Margines 0,08–0,15: asystent powie „nie jestem pewien”, zamiast zgadywać.
  6. Sprawdź „Kto to mówi?” na kilku dłuższych zdaniach każdej osoby i patrz na wynik „następnej osoby” – przerwa między nimi to Twój faktyczny zapas.

Kalibracja z apply: true nadpisuje progi osób. Ręczne poprawki rób po niej.

9. Korzystanie na co dzień

„Kto to mówi?”

Z Assist Routerem zapytaj „Kto to mówi?”, „Kim jestem?”, „Czy mnie rozpoznajesz?” albo „Czyj to głos?”. Odpowiedź podaje osobę i podobieństwo, np. „Mówi Anna, podobieństwo 82%. Następna osoba: Kasia, 41%.”. To najszybszy test progów i jakości wzorców.

„Agent z mówcą”: mówca dla dowolnego agenta

Ustaw go w pipeline'ie, a w opcjach integracji wybierz agenta docelowego (np. Ollama, OpenAI, wbudowany agent HA). Przed przekazaniem polecenia „Agent z mówcą”:

Własny agent albo integracja: get_speaker()

try:
    from custom_components.speaker_id.api import get_speaker
except ImportError:
    get_speaker = None

speaker = get_speaker(hass) if get_speaker else None
if speaker and speaker.speaker:
    ...  # speaker.speaker (id), .name, .person, .user_id, .score

Agent, który sam obsługuje nagrywanie, wywołuje na początku enrollment_reply(hass): zwraca krótką odpowiedź („Nagrano 3 z 10. Kolejne zdanie.”) i informację, czy słuchać dalej, albo None dla zwykłej wypowiedzi. Tak robi Assist Router: pytanie w pierwszej osobie bez imienia („jakie mam zajęcia”) dotyczy danych mówcy, „tu” to pokój mówcy, a „mój brat” to konkretna osoba z rodziny.

Automatyzacje

Sensor „Ostatni mówca” (stan: imię albo unknown; atrybuty: speaker, name, person, score, scores, speech_seconds, enrollment) i zdarzenie speaker_id_identified. Treść wypowiedzi celowo nie trafia do historii.

Automatyzacje z wyzwalaczem zdaniowym HA uruchamia przed agentem, więc nie dostają mówcy wprost. Sensor zmienia się jednak w tym samym poleceniu, tuż przed nimi – wynik sprzed kilku sekund to mówca tego zdania. Wygodne makro w /config/custom_templates/mowca.jinja:

{% macro mowca(max_s=20) -%}
  {%- set s = states.sensor.assist_speaker_id_ostatni_mowca -%}
  {%- if s and (now() - s.last_updated).total_seconds() <= max_s -%}
    {{- s.attributes.speaker or '' -}}
  {%- endif -%}
{%- endmacro %}

Po utworzeniu pliku uruchom akcję homeassistant.reload_custom_templates. Przykład: „Gdzie jest mój telefon?” dzwoni na telefon osoby, która pyta:

triggers:
  - trigger: conversation
    command: "gdzie jest mój telefon"
actions:
  - variables:
      kto: "{% from 'mowca.jinja' import mowca %}{{ mowca() }}"
  - if: "{{ kto in ['anna', 'tomek'] }}"
    then:
      - action: script.zadzwon_na_telefon     # Twój skrypt, np. dzwonek przez aplikację HA
        data: { osoba: "{{ kto }}" }
      - set_conversation_response: "Dzwonię na Twój telefon."
    else:
      - set_conversation_response: "Nie wiem, kto pyta. Czyj telefon mam znaleźć?"

Nazwa sensora zależy od języka HA; po angielsku to sensor.assist_speaker_id_last_speaker.

10. Ogłoszenia Twoim głosem

„OK Nabu, ogłoszenie, dzieci, proszę przyjść na obiad.” Pozostałe głośniki odtwarzają Twoje nagranie – dokładnie to, co powiedziałeś po słowie wybudzającym – zamiast czytać tekst syntezą mowy. Słychać, kto woła i jakim tonem.

PoleDomyślnieZnaczenie
satelliteswszystkie satelity z ogłoszeniamigdzie zagrać
excludebrakpominięta satelita, zwykle ta, która nagrała
media_playersbrakdodatkowe odtwarzacze, np. głośniki przez Music Assistant (play_media z announce: true)
preannouncetruekrótki sygnał przed nagraniem
max_age60 sstarsza wypowiedź nie jest ogłaszana

Agent konwersacji może wywołać to samo funkcją async_announce_last(hass, exclude=…, media_players=…) z custom_components.speaker_id.api. Pamiętaj o wyłączeniu obsługi lokalnej w pipeline'ie (rozdział 6).

11. Akcje i API

AkcjaCo robi
speaker_id.start_enrollmentnagrywanie wzorca: speaker, name, count, opcjonalnie satellite (nagrywanie prowadzone)
speaker_id.stop_enrollmentprzerywa nagrywanie
speaker_id.add_last_sampleostatnia wypowiedź (najwyżej sprzed 10 min) jako próbka osoby
speaker_id.calibrateraport kalibracji i propozycje progów; apply: true zapisuje progi
speaker_id.set_speakerzmiana nazwy i własnego progu osoby
speaker_id.delete_speakerusuwa wzorzec osoby
speaker_id.list_speakerslista osób z liczbą próbek i progami
speaker_id.announce_lastodtwarza ostatnią wypowiedź jako ogłoszenie

Usługa ma też API HTTP (port 10351, nagłówek Authorization: Bearer <token>), przydatne do skryptów i testów:

ZapytanieCo robi
GET /api/info, GET/PUT /api/settingswersja i model; progi, margines, minimum mowy
GET /api/speakers, PUT/DELETE /api/speakers/{id}lista osób; zmiana albo usunięcie osoby
POST /api/speakers/{id}/samplespróbka z pliku WAV
POST /api/speakers/{id}/samples/last, DELETE …/samples/{n}ostatnia wypowiedź jako próbka; usunięcie próbki
POST/DELETE /api/enrollmentstart i koniec nagrywania wzorca
GET /api/last, GET /api/last.wavwynik i nagranie ostatniej wypowiedzi (z RAM)
POST /api/identifyrozpoznanie mówcy z przesłanego pliku WAV
POST /api/calibrateraport kalibracji

12. Ograniczenia

To wygoda, nie zabezpieczenie. Głos można nagrać i odtworzyć, a rodzeństwo bywa do siebie bardzo podobne. Nie używaj mówcy do otwierania zamków, wyłączania alarmu ani niczego, co wymaga uwierzytelnienia.

13. Prywatność

Wzorzec głosu to dane biometryczne (RODO, art. 9). Dlatego: