Wyoming Protocol Documentation
repository·main·Indexed 17 days ago
https://github.com/ohf-voice/wyomingA peer-to-peer TCP protocol for voice assistant communication, facilitating the exchange of JSON metadata and binary audio payloads between services like Home Assistant and voice processing engines. It supports speech recognition (ASR), text-to-speech (TTS), wake word detection, intent recognition, and voice satellite control using a client-server event model.
What's inside Wyoming
- The Wyoming Protocol is a peer-to-peer TCP protocol designed for voice assistants. It uses a combination of JSON Lines (JSONL) for event headers and metadata, and raw binary payloads (typically PCM audio) for data transmission. It is used by Home Assistant to communicate with various voice services.
How the Wyoming Protocol event flow works
mainThe Wyoming Protocol operates using a client-server event model where events are exchanged over a connection.
Event Directionality:
→indicates an event from the client to the server.←indicates an event from the server to the client.
Standard Connection Lifecycle:
- Service Description: The client must first send a
describeevent, and the server responds with aninfoevent. - Program Selection: If a server exposes multiple programs of the same type (e.g., multiple
asrprograms), the client can optionally send aselect-programevent with thenameof the desired program. If omitted, the first program of each type listed in theinfoevent is used. - Request Execution: Once a program is selected, the client sends request events (e.g.,
transcribe,synthesize,detect,recognize) specific to that program.
Understand the Wyoming Protocol message format
mainA Wyoming message consists of a single-line JSON header followed by optional data and a binary payload. The structure is as follows:
- JSON Header (Required, UTF-8, single line ending in
\n):type: The event type (string).data: Event-specific metadata (object, optional).data_length: The number of bytes of additional UTF-8 data following the header (int, optional).payload_length: The number of bytes of the binary payload following the data (int, optional).
- Additional Data (Optional, UTF-8):
- A JSON object containing event-specific data, merged with the header's
datafield. - Must be exactly
data_lengthbytes long. - Follows the header immediately.
- A JSON object containing event-specific data, merged with the header's
- Payload (Optional, Binary):
- Typically PCM audio or other binary data.
- Must be exactly
payload_lengthbytes long. - Follows the additional data or the header if no additional data is present.
{ "type": "...", "data": { ... }, "data_length": ..., "payload_length": ...}\n <data_length bytes (optional)> <payload_length bytes (optional)>- JSON Header (Required, UTF-8, single line ending in
Implement Intent Handling with Wyoming
mainOnce an intent is recognized, it must be handled by the server.
Structured Intents
→ intent(required)← handled(if successful)← not-handled(if unsuccessful)
Text-Only Intents
→ transcript(required: includetextto handle)← handled(if successful)← not-handled(if unsuccessful)
Streaming Text-Only Intents (Successful)
→ transcript(required: includetextto handle)← handled-start(required)← handled-chunk(required: chunk of response text)← handled(sent for backwards compatibility)← handled-stop(required)
Implement Text-to-Speech (TTS) with Wyoming
mainTo generate speech from text, use the following event sequences.
Standard TTS
→ synthesize(required: includetext)← audio-start← audio-chunk(one or more chunks)← audio-stop
Streaming TTS
→ synthesize-start(required)→ synthesize-chunk(required: send text chunks as they are produced)← audio-start,← audio-chunk(one or more),← audio-stop(server sends audio chunks as they are produced)→ synthesize(sent for backwards compatibility)→ synthesize-stop(end of text stream)← audio-start,← audio-chunk(one or more),← audio-stop(final audio must be sent)← synthesize-stopped(server acknowledges final audio has been sent)
Implement Speech-to-Text (ASR) with Wyoming
mainTo perform speech recognition, use the following event sequences depending on whether you need standard or streaming transcription.
Standard Transcription
→ transcribe(optional: includenameof model orlanguage)→ audio-start(required)→ audio-chunk(required: send chunks until silence is detected)→ audio-stop(required)← transcript(required: contains the text transcription)
Streaming Transcription
→ transcribe(optional)→ audio-start(required)→ audio-chunk(required: send chunks until silence is detected)← transcript-start(required)← transcript-chunk(required: server sends transcript chunks as they are produced)→ audio-stop(required)← transcript(sent for backwards compatibility)← transcript-stop(required)
Implement Voice Activity Detection (VAD)
mainTo detect speech activity:
→ audio-chunk(required: send chunks until silence is detected)← voice-started(when speech starts)← voice-stopped(when speech stops)
Select a specific program for a connection
mainBy default, a server uses the first program of each type listed in its
inforesponse. To use a specific program, send aselect-programevent immediately after connecting and before sending any request events (likedescribeortranscribe).- The
namemust match a programnameprovided in theinfoevent. - The selection applies for the lifetime of the connection.
- The domain (e.g.,
asr,tts) is implied by the subsequent request events.
{ "type": "select-program", "name": "my-custom-asr-model" }- The
Implement Wake Word Detection with Wyoming
mainTo detect specific wake words, follow this flow:
→ detect(optional: includenamesof wake words to detect)→ audio-start(required)→ audio-chunk(required: keep sending chunks until adetectionis received)← detection(sent for each wake word detection)→ audio-stop(optional: manually end the audio stream)← not-detected(sent afteraudio-stopif no detections occurred)
Implement Intent Recognition with Wyoming
mainTo recognize user intents, use the following flows.
Single Intent
→ recognize(required)← intent(if successful)← not-recognized(if unsuccessful)
Multiple Intents
→ recognize(required)← intents-start(if successful)← intent(one or more intents)← intents-stop(if successful)← not-recognized(if unsuccessful)
Implement Audio Output with Wyoming
mainTo play audio back to a user:
→ audio-start(required)→ audio-chunk(required: one or more chunks)→ audio-stop(required)← played(acknowledgment)
Discover service capabilities with Info and Describe events
mainWyoming uses a discovery pattern to allow clients to understand what services a server provides.
- Describe: The client sends a
Describeevent (typedescribe) to request information. - Info: The server responds with an
Infoevent (typeinfo) containing a detailed breakdown of available services, models, and hardware capabilities.
The
Infoevent includes lists of programs for various domains such asasr(speech-to-text),tts(text-to-speech),handle(intent handling),intent(intent recognition),wake(wake word detection),mic(audio input), andsnd(audio output), as well assatellitemetadata.# Client requesting info describe_event = Describe() # The server would then respond with an Info event- Describe: The client sends a