wyoming

package
v0.51.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package wyoming implements the Wyoming voice protocol so an ESPHome voice satellite (mediated by Home Assistant's Assist pipeline) can use speechkit-server as its STT and TTS backend.

Wyoming is a peer-to-peer, event-driven protocol spoken over a raw TCP socket (also Unix socket / stdio upstream; this adapter uses TCP). Each event is a JSON header line terminated by '\n', optionally followed by a JSON "data" segment and a binary payload:

{"type":"audio-chunk","data_length":42,"payload_length":2048}\n
<42 bytes of JSON data><2048 bytes of PCM>

wire.go is deliberately OS-agnostic and carries no build tag so the framing codec — the highest-risk part for interop — can be unit-tested on any platform. The TCP server, and the STT/TTS bridges that reach the kernel routers, are Linux-tagged (server target).

Wire-format note: upstream producers vary on whether the "data" object is inline in the header line or a separate length-delimited segment. WriteEvent emits the separate-segment form used by the reference `wyoming` Python library (what Home Assistant speaks); ReadEvent accepts BOTH an inline "data" object and a "data_length" segment so this adapter interoperates with either. Validate against a captured wyoming-faster-whisper / wyoming-piper frame before relying on it in production (see wire_test.go).

Index

Constants

View Source
const (
	TypeDescribe   = "describe"
	TypeInfo       = "info"
	TypeTranscribe = "transcribe"
	TypeTranscript = "transcript"
	TypeAudioStart = "audio-start"
	TypeAudioChunk = "audio-chunk"
	TypeAudioStop  = "audio-stop"
	TypeSynthesize = "synthesize"
)

Wyoming event types used by the STT (asr) and TTS backends.

View Source
const (

	// DefaultMaxSegment caps the data + payload segment sizes when a Reader is
	// created without an explicit limit.
	DefaultMaxSegment = 1 << 20 // 1 MiB
)

Defaults for the read-side safety caps. A misbehaving or hostile peer must not be able to make the reader allocate unbounded memory from a single frame.

Variables

This section is empty.

Functions

func WriteEvent

func WriteEvent(w io.Writer, ev *Event) error

WriteEvent writes one framed event to w and returns the write error, if any. It emits the separate-segment form: header line, then the data segment (when Data is non-empty), then the payload (when non-empty). The caller is responsible for flushing a buffered writer.

Types

type AsrModel

type AsrModel struct {
	Name        string      `json:"name"`
	Attribution Attribution `json:"attribution"`
	Installed   bool        `json:"installed"`
	Description string      `json:"description,omitempty"`
	Version     string      `json:"version,omitempty"`
	Languages   []string    `json:"languages"`
}

type AsrProgram

type AsrProgram struct {
	Name        string      `json:"name"`
	Attribution Attribution `json:"attribution"`
	Installed   bool        `json:"installed"`
	Description string      `json:"description,omitempty"`
	Version     string      `json:"version,omitempty"`
	Models      []AsrModel  `json:"models"`
}

type Attribution

type Attribution struct {
	Name string `json:"name"`
	URL  string `json:"url"`
}

Attribution is the model/service credit block present throughout the Wyoming info schema.

type AudioChunk

type AudioChunk struct {
	Rate      int  `json:"rate"`
	Width     int  `json:"width"`
	Channels  int  `json:"channels"`
	Timestamp *int `json:"timestamp,omitempty"`
}

type AudioStart

type AudioStart struct {
	Rate      int  `json:"rate"`
	Width     int  `json:"width"`
	Channels  int  `json:"channels"`
	Timestamp *int `json:"timestamp,omitempty"`
}

AudioStart / AudioChunk / AudioStop carry the PCM stream. Chunk audio bytes travel in the Event.Payload, not in Data.

type AudioStop

type AudioStop struct {
	Timestamp *int `json:"timestamp,omitempty"`
}

type Event

type Event struct {
	Type    string
	Data    json.RawMessage
	Payload []byte
}

Event is one Wyoming message: a type, an optional structured data object (raw JSON), and an optional binary payload (PCM for audio events).

type Info

type Info struct {
	ASR []AsrProgram `json:"asr,omitempty"`
	TTS []TtsProgram `json:"tts,omitempty"`
}

Info is the reply to a `describe` event: it advertises the asr and/or tts programs this server exposes so Home Assistant can register STT/TTS entities.

type Options

type Options struct {
	STT          Transcriber
	TTS          Synthesizer
	Info         Info
	DefaultVoice string
	DecodeLimits audio.DecodeLimits
	MaxSegment   int
	// AllowedCIDRs, when non-empty, restricts which peers may connect. Wyoming
	// has no in-protocol auth, so this is the adapter's only access control
	// beyond binding to a trusted interface.
	AllowedCIDRs []*net.IPNet
}

Options configures a Wyoming server. STT and/or TTS may be nil; the paired program is simply not advertised in Info and its events are ignored.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads framed Wyoming events from a buffered stream with bounded per-segment allocation.

func NewReader

func NewReader(r io.Reader, maxSegment int) *Reader

NewReader wraps r. maxSegment caps the data and payload segment sizes; values <= 0 use DefaultMaxSegment.

func (*Reader) ReadEvent

func (rd *Reader) ReadEvent() (*Event, error)

ReadEvent reads one framed event. It returns io.EOF at a clean end of stream (no partial frame buffered).

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server accepts Wyoming TCP connections and bridges STT/TTS to the kernel routers. One goroutine per connection; a connection handles a describe handshake and either an STT turn (transcribe → audio-* → transcript) or a TTS turn (synthesize → audio-*).

func NewServer

func NewServer(opts Options) *Server

NewServer returns a ready server. MaxSegment <= 0 uses DefaultMaxSegment.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, ln net.Listener) error

Serve accepts connections until ctx is cancelled or ln is closed. It returns nil on a clean shutdown (ctx cancellation / listener close).

type SynthVoice

type SynthVoice struct {
	Name     string `json:"name,omitempty"`
	Language string `json:"language,omitempty"`
}

type Synthesize

type Synthesize struct {
	Text  string      `json:"text"`
	Voice *SynthVoice `json:"voice,omitempty"`
}

Synthesize requests TTS for Text in the optional Voice.

type Synthesizer

type Synthesizer interface {
	Synthesize(ctx context.Context, text string, opts tts.SynthesizeOpts) (*tts.Result, error)
}

Synthesizer is the minimal TTS surface; satisfied by *internal/tts.Router.

type Transcribe

type Transcribe struct {
	Name     string `json:"name,omitempty"`
	Language string `json:"language,omitempty"`
}

Transcribe starts an STT turn; both fields are optional hints.

type Transcriber

type Transcriber interface {
	Route(ctx context.Context, audio []byte, audioDurationSecs float64, opts stt.TranscribeOpts) (*stt.Result, error)
}

Transcriber is the minimal STT surface the Wyoming adapter needs; satisfied by *internal/router.Router. Mirrors internal/server/dictation.Transcriber so the same batch router backs both HTTP dictation and Wyoming STT.

type Transcript

type Transcript struct {
	Text string `json:"text"`
}

Transcript is the STT result sent back after audio-stop.

type TtsProgram

type TtsProgram struct {
	Name        string      `json:"name"`
	Attribution Attribution `json:"attribution"`
	Installed   bool        `json:"installed"`
	Description string      `json:"description,omitempty"`
	Version     string      `json:"version,omitempty"`
	Voices      []TtsVoice  `json:"voices"`
}

type TtsVoice

type TtsVoice struct {
	Name        string      `json:"name"`
	Attribution Attribution `json:"attribution"`
	Installed   bool        `json:"installed"`
	Description string      `json:"description,omitempty"`
	Version     string      `json:"version,omitempty"`
	Languages   []string    `json:"languages"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL