tts

package
v0.69.7 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package tts exposes the embeddable SpeechKit text-to-speech surface.

Index

Examples

Constants

View Source
const (
	FluxSpeechStarted   = "SpeechStarted"
	FluxSpeechFlushed   = "Flushed"
	FluxSpeechMetadata  = "SpeechMetadata"
	FluxSpeechInterrupt = "Interrupt"
)

Flux TTS server event types. A turn opens with SpeechStarted, Flushed acknowledges the client's Flush, and SpeechMetadata closes the turn with its duration and billing counts. Interrupt arrives instead when the listener barges in.

View Source
const (

	// DeepgramFluxTTSDefaultVoice is Deepgram's default Flux TTS voice.
	DeepgramFluxTTSDefaultVoice = "flux-kit-en"
)

Variables

View Source
var ErrMissingRouter = errors.New("speechkit tts: router is required")

Functions

func IsDeepgramFluxVoice added in v0.54.10

func IsDeepgramFluxVoice(voice string) bool

IsDeepgramFluxVoice reports whether a voice id names a Flux TTS voice rather than an Aura one.

func IsMAIVoice added in v0.68.24

func IsMAIVoice(shortName string) bool

IsMAIVoice reports whether shortName addresses a Microsoft MAI voice ("de-DE-Mia:MAI-Voice-2") rather than a classic neural voice.

func MAIVoiceFamilies added in v0.68.24

func MAIVoiceFamilies() []string

MAIVoiceFamilies lists the MAI model series a voice short name can end in.

func PreferredProviderForProfileID

func PreferredProviderForProfileID(profileID string) string

PreferredProviderForProfileID maps a Voice-Output profile ID to Provider.Name. The mapping is shared with the kernel via the ttsroute leaf package.

func SnapDeepgramFluxSpeed added in v0.54.10

func SnapDeepgramFluxSpeed(speed float64) float64

SnapDeepgramFluxSpeed rounds a speed onto the discrete steps Flux TTS accepts, clamping to the nearest bound. It returns 0 for "unset" so callers can omit the parameter.

func VoiceLocale added in v0.68.24

func VoiceLocale(shortName string) string

VoiceLocale returns the BCP-47 locale a Speech voice short name starts with: "de-DE" for "de-DE-Mia:MAI-Voice-2". Empty when the name carries no language-region prefix.

Types

type AzureSpeech added in v0.68.24

type AzureSpeech struct {
	Host       string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

AzureSpeech implements Provider on the Azure Speech SSML endpoint of a Microsoft Foundry resource. Microsoft's MAI-Voice models are served there, not on the OpenAI-compatible audio/speech route Foundry uses for gpt-*-tts, so this adapter talks to the resource's custom domain directly.

It reports the same provider id as Foundry ("foundry"): routing, preference pinning and option manifests key on the provider, not on the wire format. Validation is strict by default (public https only).

func NewAzureSpeech added in v0.68.24

func NewAzureSpeech(opts AzureSpeechOpts) *AzureSpeech

NewAzureSpeech creates an Azure Speech TTS provider for MAI voices.

func (*AzureSpeech) Capabilities added in v0.68.24

func (*AzureSpeech) Capabilities() []speechkit.Capability

func (*AzureSpeech) CloseIdleConnections added in v0.68.24

func (a *AzureSpeech) CloseIdleConnections()

func (*AzureSpeech) Health added in v0.68.24

func (a *AzureSpeech) Health(ctx context.Context) error

Health lists the voices: free, read-only, and it exercises the same host and credential Synthesize uses.

func (*AzureSpeech) Kind added in v0.68.24

func (a *AzureSpeech) Kind() ProviderKind

func (*AzureSpeech) ListVoices added in v0.68.24

func (a *AzureSpeech) ListVoices(ctx context.Context) ([]AzureSpeechVoice, error)

ListVoices fetches the voices the resource can synthesize with, MAI and classic neural alike; callers filter on IsMAIVoice or ModelSeries.

func (*AzureSpeech) Name added in v0.68.24

func (a *AzureSpeech) Name() string

func (*AzureSpeech) Synthesize added in v0.68.24

func (a *AzureSpeech) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

Synthesize renders text through SSML and returns the requested container.

type AzureSpeechOpts added in v0.68.24

type AzureSpeechOpts struct {
	// Host is the resource's custom domain, e.g.
	// "myresource.cognitiveservices.azure.com" (no scheme). Required.
	Host string
	// APIKey is the resource key, sent as Ocp-Apim-Subscription-Key.
	APIKey string
	// BearerToken, when set, wins over APIKey: it is called per request and
	// the token rides "Authorization: Bearer". Hosts set it for Entra sign-in.
	BearerToken speechkit.BearerTokenFunc
	// Voice is a Speech voice short name such as "de-DE-Mia:MAI-Voice-2" or
	// "en-US-Ethan:MAI-Voice-2-Flash"; defaults to "en-US-Harper:MAI-Voice-2".
	Voice string
	// Style is an optional mstts:express-as style ("friendly", "whispering").
	Style string
	// StyleDegree scales Style (0.01–2); only emitted together with Style.
	StyleDegree float64
}

AzureSpeechOpts configures the Azure Speech (MAI-Voice) TTS provider.

type AzureSpeechVoice added in v0.68.24

type AzureSpeechVoice struct {
	ShortName        string
	DisplayName      string
	LocalName        string
	Locale           string
	Gender           string
	VoiceType        string
	Status           string
	Styles           []string
	ModelSeries      string
	SecondaryLocales []string
	SampleRateHertz  int
}

AzureSpeechVoice is one entry of the resource's voices list.

type CapabilityReporter added in v0.46.0

type CapabilityReporter interface {
	Capabilities() []speechkit.Capability
}

CapabilityReporter is an optional interface a provider can implement to self-describe its capabilities, so routing can query them instead of string-matching profile IDs. It is intentionally NOT part of Provider, so existing implementations and test doubles are unaffected.

type Deepgram added in v0.46.0

type Deepgram struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

Deepgram implements Provider using the Deepgram Aura-2 text-to-speech REST API (POST /v1/speak). It reuses the Deepgram API key shared with the STT and Voice Agent adapters. Aura voices are selected via the model id (e.g. "aura-2-thalia-en"); there is no separate voice parameter.

Aura REST caps a single request at 2000 characters, so longer text is split on sentence/word boundaries. Raw concatenation is correct for streaming codecs (mp3, linear16/pcm, ogg-opus). WAV is handled specially: a multi-chunk WAV request is fetched as linear16 PCM and the joined PCM is wrapped in a single RIFF header (see encodeWAV), so the result is always one valid WAV.

func NewDeepgram added in v0.46.0

func NewDeepgram(opts DeepgramOpts) *Deepgram

NewDeepgram creates a Deepgram Aura TTS provider.

func (*Deepgram) CloseIdleConnections added in v0.46.0

func (d *Deepgram) CloseIdleConnections()

func (*Deepgram) Health added in v0.46.0

func (d *Deepgram) Health(ctx context.Context) error

func (*Deepgram) Kind added in v0.46.0

func (d *Deepgram) Kind() ProviderKind

func (*Deepgram) Name added in v0.46.0

func (d *Deepgram) Name() string

func (*Deepgram) Synthesize added in v0.46.0

func (d *Deepgram) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

type DeepgramFluxTTS added in v0.54.10

type DeepgramFluxTTS struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

DeepgramFluxTTS opens Flux TTS streams. It reuses the Deepgram API key shared with the STT and Voice Agent adapters.

func NewDeepgramFluxTTS added in v0.54.10

func NewDeepgramFluxTTS(apiKey string) *DeepgramFluxTTS

NewDeepgramFluxTTS creates a Flux TTS client.

func (*DeepgramFluxTTS) Open added in v0.54.10

Open dials the Flux TTS WebSocket.

type DeepgramOpts added in v0.46.0

type DeepgramOpts struct {
	APIKey string
	Model  string // Aura-2 voice id, e.g. "aura-2-thalia-en"; empty => locale default
}

DeepgramOpts configures the Deepgram Aura TTS provider.

type EnabledProviders added in v0.46.0

type EnabledProviders struct {
	OpenAI      *OpenAIOpts
	Google      *GoogleOpts
	Deepgram    *DeepgramOpts
	HuggingFace *HuggingFaceOpts
	Foundry     *FoundryOpts
	// FoundrySpeech routes Foundry speech output to the resource's Azure
	// Speech surface (MAI-Voice) instead of the OpenAI-compatible route. Both
	// adapters report the shared "foundry" provider id, so a host enables one
	// of Foundry / FoundrySpeech, not both.
	FoundrySpeech *AzureSpeechOpts
	Piper         *PiperOpts
	// PreferredProfileID optionally pins the provider matching this
	// model_selection profile to the front of the strategy order.
	PreferredProfileID string
}

EnabledProviders carries the per-provider options a host has already resolved from its own config (env secrets, model/voice defaults). Nil fields are skipped. It lets the Device- and Server-Targets share one router-assembly path (BuildRouter) while each keeps its own config-resolution specifics.

type FluxSpeechEvent added in v0.54.10

type FluxSpeechEvent struct {
	// Audio holds raw linear16 PCM at the negotiated sample rate.
	Audio []byte
	// Type is the control event name (SpeechStarted, SpeechMetadata, Interrupt).
	Type string
	// SpeechID identifies the turn this event belongs to.
	SpeechID string
	// AudioDurationMs is the synthesized duration reported with SpeechMetadata.
	AudioDurationMs int64
	// InputCharacterCount and BillableCharacterCount close out the turn's
	// billing, reported with SpeechMetadata.
	InputCharacterCount    int
	BillableCharacterCount int
	// TextSpoken and TextRemaining are reported on Interrupt: what the listener
	// actually heard before the barge-in, and what was cut. Recording
	// TextSpoken as the assistant turn keeps the conversation history honest.
	TextSpoken    string
	TextRemaining string
	// Raw is the undecoded control frame. Flux TTS is young and its event
	// payloads are not fully documented, so keeping the original lets callers
	// read fields this client does not model yet.
	Raw json.RawMessage
}

FluxSpeechEvent is one decoded event from a Flux TTS stream. Exactly one of Audio or Type is populated: binary frames carry Audio, control frames carry Type and the fields belonging to it.

func (FluxSpeechEvent) IsAudio added in v0.54.10

func (e FluxSpeechEvent) IsAudio() bool

IsAudio reports whether the event carries synthesized audio.

type FluxSpeechOptions added in v0.54.10

type FluxSpeechOptions struct {
	// Voice is a Flux TTS model id such as "flux-kit-en". Empty uses
	// DeepgramFluxTTSDefaultVoice.
	Voice string
	// SampleRateHz selects the linear16 output rate. Zero uses Deepgram's
	// default of 24 kHz, which matches SpeechKit's playback contract.
	SampleRateHz int
	// Speed snaps to the nearest value Flux accepts (0.85–1.15 in 0.05 steps).
	// Zero keeps the provider default.
	Speed float64
}

FluxSpeechOptions configures a Flux TTS stream.

type FluxSpeechStream added in v0.54.10

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

FluxSpeechStream is a live Flux TTS connection.

func (*FluxSpeechStream) Close added in v0.54.10

func (s *FluxSpeechStream) Close() error

Close shuts the stream down. It is safe to call more than once.

func (*FluxSpeechStream) Configure added in v0.54.10

func (s *FluxSpeechStream) Configure(ctx context.Context, speed float64) error

Configure adjusts the delivery speed mid-stream without reconnecting.

func (*FluxSpeechStream) Flush added in v0.54.10

func (s *FluxSpeechStream) Flush(ctx context.Context) error

Flush ends the turn so the server synthesizes whatever text is buffered.

func (*FluxSpeechStream) Receive added in v0.54.10

Receive returns the next audio frame or control event, and io.EOF when Deepgram closes the stream.

func (*FluxSpeechStream) SampleRateHz added in v0.54.10

func (s *FluxSpeechStream) SampleRateHz() int

SampleRateHz reports the linear16 output rate.

func (*FluxSpeechStream) Speak added in v0.54.10

func (s *FluxSpeechStream) Speak(ctx context.Context, text string) error

Speak streams text into the current turn. Callers pass LLM tokens as they arrive; the server decides where to break for synthesis.

func (*FluxSpeechStream) Voice added in v0.54.10

func (s *FluxSpeechStream) Voice() string

Voice reports the Flux voice this stream negotiated.

type Foundry added in v0.67.5

type Foundry struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

Foundry implements Provider using the Microsoft Foundry OpenAI-compatible audio/speech API. BaseURL is the OpenAI-compatible base derived from the project endpoint (https://<host>/openai); the model is the deployment name.

Foundry's v1 surface accepts Bearer auth, so the API key rides the standard Authorization header. Validation is strict by default (public https only).

func NewFoundry added in v0.67.5

func NewFoundry(opts FoundryOpts) *Foundry

NewFoundry creates a Microsoft Foundry TTS provider.

func (*Foundry) CloseIdleConnections added in v0.67.5

func (f *Foundry) CloseIdleConnections()

func (*Foundry) Health added in v0.67.5

func (f *Foundry) Health(ctx context.Context) error

func (*Foundry) Kind added in v0.67.5

func (f *Foundry) Kind() ProviderKind

func (*Foundry) Name added in v0.67.5

func (f *Foundry) Name() string

func (*Foundry) Synthesize added in v0.67.5

func (f *Foundry) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

type FoundryOpts added in v0.67.5

type FoundryOpts struct {
	APIKey string
	// BearerToken, when set, wins over APIKey: it is called per request and
	// the token rides "Authorization: Bearer". Hosts set it for Entra sign-in.
	BearerToken speechkit.BearerTokenFunc
	BaseURL     string // OpenAI-compatible base, e.g. https://<host>/openai (required)
	Model       string // deployment name; defaults to "gpt-4o-mini-tts"
	Voice       string // alloy, echo, fable, onyx, nova, shimmer; defaults to "alloy"
}

FoundryOpts configures the Microsoft Foundry TTS provider.

type Google added in v0.46.0

type Google struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

Google implements Provider using the Google Cloud Text-to-Speech API.

BaseURL is configurable for testing. It is validated against Validation on every request. Default Validation is strict (public https only).

func NewGoogle added in v0.46.0

func NewGoogle(opts GoogleOpts) *Google

NewGoogle creates a Google Cloud TTS provider.

func (*Google) Capabilities added in v0.46.0

func (*Google) Capabilities() []speechkit.Capability

func (*Google) CloseIdleConnections added in v0.46.0

func (g *Google) CloseIdleConnections()

func (*Google) Health added in v0.46.0

func (g *Google) Health(ctx context.Context) error

func (*Google) Kind added in v0.46.0

func (g *Google) Kind() ProviderKind

func (*Google) Name added in v0.46.0

func (g *Google) Name() string

func (*Google) Synthesize added in v0.46.0

func (g *Google) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

type GoogleOpts added in v0.46.0

type GoogleOpts struct {
	APIKey string
	Voice  string // e.g. "de-DE-Neural2-B", "en-US-Neural2-J"
}

GoogleOpts configures the Google TTS provider.

type HuggingFace added in v0.46.0

type HuggingFace struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

HuggingFace implements Provider using the HuggingFace Inference API with text-to-speech models (e.g. parler-tts).

BaseURL is configurable for testing. It is validated against Validation on every request. Default Validation is strict (public https only).

func NewHuggingFace added in v0.46.0

func NewHuggingFace(opts HuggingFaceOpts) *HuggingFace

NewHuggingFace creates a HuggingFace TTS provider.

func (*HuggingFace) Capabilities added in v0.46.0

func (*HuggingFace) Capabilities() []speechkit.Capability

func (*HuggingFace) CloseIdleConnections added in v0.46.0

func (h *HuggingFace) CloseIdleConnections()

func (*HuggingFace) Health added in v0.46.0

func (h *HuggingFace) Health(ctx context.Context) error

func (*HuggingFace) Kind added in v0.46.0

func (h *HuggingFace) Kind() ProviderKind

func (*HuggingFace) Name added in v0.46.0

func (h *HuggingFace) Name() string

func (*HuggingFace) Synthesize added in v0.46.0

func (h *HuggingFace) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

type HuggingFaceOpts added in v0.46.0

type HuggingFaceOpts struct {
	Token string // HF API token
	Model string // Model ID, e.g. "Qwen/Qwen3-TTS-12Hz-1.7B-Base"
}

HuggingFaceOpts configures the HuggingFace TTS provider.

type OpenAI added in v0.46.0

type OpenAI struct {
	BaseURL    string
	Validation netsec.ValidationOptions
	// contains filtered or unexported fields
}

OpenAI implements Provider using the OpenAI TTS API.

BaseURL is configurable for testing. It is validated against Validation on every request. Default Validation is strict (public https only).

func NewOpenAI added in v0.46.0

func NewOpenAI(opts OpenAIOpts) *OpenAI

NewOpenAI creates an OpenAI TTS provider.

func (*OpenAI) Capabilities added in v0.46.0

func (*OpenAI) Capabilities() []speechkit.Capability

func (*OpenAI) CloseIdleConnections added in v0.46.0

func (o *OpenAI) CloseIdleConnections()

func (*OpenAI) Health added in v0.46.0

func (o *OpenAI) Health(ctx context.Context) error

func (*OpenAI) Kind added in v0.46.0

func (o *OpenAI) Kind() ProviderKind

func (*OpenAI) Name added in v0.46.0

func (o *OpenAI) Name() string

func (*OpenAI) Synthesize added in v0.46.0

func (o *OpenAI) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

type OpenAIOpts added in v0.46.0

type OpenAIOpts struct {
	APIKey string
	Model  string // "tts-1" or "tts-1-hd"
	Voice  string // alloy, echo, fable, onyx, nova, shimmer
}

OpenAIOpts configures the OpenAI TTS provider.

type Piper added in v0.46.0

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

Piper implements Provider via the `piper` command-line binary. The binary writes a WAV PCM stream to stdout when invoked with

piper --model <voice.onnx> --output-raw < input.txt

or `--output_file -` for a WAV-wrapped stream. Phase 3 of the voice-companion roadmap uses Piper as the all-local TTS so the Voice-Companion can talk without any cloud key.

The implementation does NOT bundle voice models. Operators run `scripts/prepare-piper-voices.ps1` once to download the desired voices into PiperOpts.VoiceDir. Default voice maps to <VoiceDir>/ en_US-amy-medium.onnx; locale "de" looks up de_DE-thorsten-medium.

func NewPiper added in v0.46.0

func NewPiper(opts PiperOpts) (*Piper, error)

NewPiper validates the options and returns a ready Provider. The voice directory must already exist; missing voice models surface as a clear "voice file not found" error at Synthesize time, not at construction, so a missing en_DE voice does not prevent the provider from answering en_US requests.

func (*Piper) Capabilities added in v0.46.0

func (*Piper) Capabilities() []speechkit.Capability

func (*Piper) Health added in v0.46.0

func (p *Piper) Health(ctx context.Context) error

Health verifies the piper binary can be located. Voice-model presence is not checked here — operators may have a partial set installed and we still want /readyz to be green for the locales they DO have. Synthesize surfaces missing-voice errors per request.

func (*Piper) Kind added in v0.46.0

func (*Piper) Kind() ProviderKind

func (*Piper) Name added in v0.46.0

func (*Piper) Name() string

Name returns the provider identifier.

func (*Piper) Probe added in v0.46.0

func (p *Piper) Probe(ctx context.Context, voice, locale string) (*Result, error)

Probe runs piper with a short test phrase to verify the binary and the requested voice work end-to-end. Returns the synthesized WAV bytes (small — a few seconds of speech) on success. Used by the Settings UI to preview a voice without persisting any text.

func (*Piper) Synthesize added in v0.46.0

func (p *Piper) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)

Synthesize runs the piper subprocess for one utterance. The returned Result.Audio is a complete RIFF/WAVE PCM blob suitable for direct playback or HTTP delivery.

type PiperOpts added in v0.46.0

type PiperOpts struct {
	// Binary is the absolute or PATH-relative `piper` executable.
	// Empty defaults to "piper" (must be on $PATH).
	Binary string

	// VoiceDir is the filesystem root containing the .onnx voice
	// model files. Required.
	VoiceDir string

	// DefaultVoices maps a locale code (e.g. "en", "de") to a
	// voice-model filename inside VoiceDir. Falls back to the en_US
	// Amy medium voice when an entry is missing.
	DefaultVoices map[string]string

	// Timeout caps the subprocess execution. Zero defaults to 30 s
	// — generous because Piper warm-load on CPU can take several
	// seconds for a first synthesis.
	Timeout time.Duration
}

PiperOpts configures the local Piper subprocess.

type PiperVoiceInfo added in v0.46.0

type PiperVoiceInfo struct {
	Filename string `json:"filename"`
	Locale   string `json:"locale"`  // short code, e.g. "en", "de"
	Region   string `json:"region"`  // e.g. "US", "DE"; empty when missing
	Name     string `json:"name"`    // e.g. "amy", "thorsten"
	Quality  string `json:"quality"` // e.g. "low", "medium", "high"
	SizeKB   int    `json:"size_kb"`
}

PiperVoiceInfo is one entry from a voice-directory scan. Filename is the basename inside VoiceDir (e.g. "en_US-amy-medium.onnx"). The remaining fields are best-effort parses of the rhasspy/piper-voices naming convention <lang>_<REGION>-<name>-<quality>.onnx; when the filename does not follow that pattern only Filename is populated and the other fields remain empty.

func ListPiperVoices added in v0.46.0

func ListPiperVoices(voiceDir string) ([]PiperVoiceInfo, error)

ListPiperVoices scans voiceDir for *.onnx files and parses each filename using the piper-voices naming convention. The list is sorted by Filename so callers can present a stable UI. Returns an empty slice (not an error) when voiceDir is empty or missing — the UI surfaces "no voices installed" rather than a hard error.

type Provider

type Provider interface {
	Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (*Result, error)
	Name() string
	Kind() ProviderKind
	Health(ctx context.Context) error
}

Provider defines the interface for text-to-speech backends.

func OrderByPreferredProvider

func OrderByPreferredProvider(providers []Provider, preferred string) []Provider

OrderByPreferredProvider returns providers with the matching provider first.

type ProviderKind

type ProviderKind string

ProviderKind identifies whether a provider is local, cloud-routed, or a direct external API. Router strategies use this instead of provider names.

const (
	ProviderKindLocalBuiltIn   ProviderKind = "local_built_in"
	ProviderKindLocalProvider  ProviderKind = "local_provider"
	ProviderKindCloudProvider  ProviderKind = "cloud_provider"
	ProviderKindDirectProvider ProviderKind = "direct_provider"
)

type ResolvedSynthesizeOptions added in v0.46.0

type ResolvedSynthesizeOptions struct {
	Locale    string
	Voice     string
	Speed     float64
	Format    string
	Effective provideropts.EffectiveOptions
}

func ResolveSynthesizeOptions added in v0.46.0

func ResolveSynthesizeOptions(provider, profileID string, opts SynthesizeOpts, providerDefaults, providerOverrides provideropts.Values) ResolvedSynthesizeOptions

type Result

type Result struct {
	Audio      []byte
	Format     string
	SampleRate int
	Duration   time.Duration
	Provider   string
	Voice      string
}

Result holds the output of a TTS synthesis.

type Router

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

Router selects and falls back between TTS providers.

func BuildRouter added in v0.46.0

func BuildRouter(strategy Strategy, enabled EnabledProviders) (router *Router, ok bool, notes []string)

BuildRouter is the single source of truth for assembling a TTS router from a set of enabled providers: it constructs each enabled provider in a stable order, applies optional model_selection pinning, and returns the router plus human-readable notes. ok is false (router nil) when nothing is enabled.

func NewRouter

func NewRouter(strategy Strategy, providers ...Provider) *Router

NewRouter creates a TTS router with the given strategy and providers.

Example (LocalOnly)

ExampleNewRouter_localOnly is the fresh-install path: no cloud providers are eligible, so a cloud voice in the list is skipped without being called.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	"github.com/kombifyio/SpeechKit/pkg/speechkit/tts"
)

// fakeVoice is a minimal tts.Provider. Real hosts use tts.Piper for the
// local-only path or one of the cloud providers (tts.OpenAI, tts.Deepgram, ...).
type fakeVoice struct {
	name string
	kind tts.ProviderKind
	fail bool
}

func (v fakeVoice) Name() string                 { return v.name }
func (v fakeVoice) Kind() tts.ProviderKind       { return v.kind }
func (v fakeVoice) Health(context.Context) error { return nil }
func (v fakeVoice) Synthesize(_ context.Context, text string, opts tts.SynthesizeOpts) (*tts.Result, error) {
	if v.fail {
		return nil, errors.New(v.name + " unavailable")
	}
	return &tts.Result{Audio: []byte(text), Format: "pcm", Provider: v.name, Voice: opts.Voice}, nil
}

func main() {
	router := tts.NewRouter(tts.StrategyLocalOnly,
		fakeVoice{name: "cloud", kind: tts.ProviderKindCloudProvider},
		fakeVoice{name: "piper", kind: tts.ProviderKindLocalBuiltIn},
	)

	res, err := router.Synthesize(context.Background(), "hello", tts.SynthesizeOpts{})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Provider)
}
Output:
piper

func (*Router) CloseIdleConnections

func (r *Router) CloseIdleConnections()

CloseIdleConnections asks HTTP-backed providers to drop idle connection pools.

func (*Router) HealthCheck

func (r *Router) HealthCheck(ctx context.Context) map[string]error

HealthCheck returns health status for all providers.

func (*Router) ReadyHealthCheck added in v0.50.0

func (r *Router) ReadyHealthCheck(ctx context.Context) map[string]error

ReadyHealthCheck reports only providers eligible under the active routing strategy. A local-only router with cloud providers configured must not be advertised as ready when Synthesize would skip every one of them.

func (*Router) SetProviders

func (r *Router) SetProviders(providers ...Provider)

SetProviders replaces the provider list.

func (*Router) Synthesize

func (r *Router) Synthesize(ctx context.Context, text string, opts SynthesizeOpts) (res *Result, err error)

Synthesize tries each eligible provider until one succeeds. Per-provider option overrides (SynthesizeOpts.ProviderOptionsByProvider) are applied to the selected provider, and an OpenTelemetry span records strategy/provider.

type Service

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

Service is a small stable facade over Router. It gives embedders one construction point while still letting them provide their own providers.

func NewService

func NewService(router *Router, opts ...ServiceOption) (*Service, error)
Example

ExampleNewService shows the stable embedding path: build a Router with the providers the host has credentials for, wrap it in a Service that carries the host's default voice, and synthesize. The Router falls back in order when a provider fails, so a flaky cloud voice never blocks speech output.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	"github.com/kombifyio/SpeechKit/pkg/speechkit/tts"
)

// fakeVoice is a minimal tts.Provider. Real hosts use tts.Piper for the
// local-only path or one of the cloud providers (tts.OpenAI, tts.Deepgram, ...).
type fakeVoice struct {
	name string
	kind tts.ProviderKind
	fail bool
}

func (v fakeVoice) Name() string                 { return v.name }
func (v fakeVoice) Kind() tts.ProviderKind       { return v.kind }
func (v fakeVoice) Health(context.Context) error { return nil }
func (v fakeVoice) Synthesize(_ context.Context, text string, opts tts.SynthesizeOpts) (*tts.Result, error) {
	if v.fail {
		return nil, errors.New(v.name + " unavailable")
	}
	return &tts.Result{Audio: []byte(text), Format: "pcm", Provider: v.name, Voice: opts.Voice}, nil
}

func main() {
	router := tts.NewRouter(tts.StrategyCloudFirst,
		fakeVoice{name: "cloud", kind: tts.ProviderKindCloudProvider, fail: true},
		fakeVoice{name: "piper", kind: tts.ProviderKindLocalBuiltIn},
	)
	svc, err := tts.NewService(router, tts.WithDefaultOpts(tts.SynthesizeOpts{Voice: "de-thorsten"}))
	if err != nil {
		log.Fatal(err)
	}

	res, err := svc.Synthesize(context.Background(), "Guten Morgen")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Provider, res.Voice, len(res.Audio) > 0)
}
Output:
piper de-thorsten true

func (*Service) Router

func (s *Service) Router() *Router

func (*Service) Synthesize

func (s *Service) Synthesize(ctx context.Context, text string, opts ...SynthesizeOpts) (*Result, error)

type ServiceOption

type ServiceOption func(*Service)

func WithDefaultOpts

func WithDefaultOpts(opts SynthesizeOpts) ServiceOption

type Strategy

type Strategy string

Strategy determines how Router selects providers.

const (
	StrategyCloudFirst Strategy = "cloud-first"
	StrategyLocalFirst Strategy = "local-first"
	StrategyCloudOnly  Strategy = "cloud-only"
	StrategyLocalOnly  Strategy = "local-only"
)

type SynthesizeOpts

type SynthesizeOpts struct {
	Locale          string
	Voice           string
	Speed           float64
	Format          string
	Options         provideropts.Values
	ProviderOptions provideropts.Values
	// ProviderOptionsByProvider holds provider-keyed overrides that the Router
	// applies to the selected provider via ForProvider, so one request can
	// carry per-provider tuning without the caller knowing which provider wins.
	ProviderOptionsByProvider map[string]provideropts.Values
}

SynthesizeOpts configures a single TTS request.

func (SynthesizeOpts) ForProvider added in v0.46.0

func (o SynthesizeOpts) ForProvider(provider string) SynthesizeOpts

ForProvider returns a copy of opts with ProviderOptions merged from the provider-keyed overrides for the named provider. The Router calls this for the selected provider so per-provider tuning takes effect transparently.

Directories

Path Synopsis
Package ttscontract provides a reusable conformance suite that every tts.Provider implementation is expected to satisfy.
Package ttscontract provides a reusable conformance suite that every tts.Provider implementation is expected to satisfy.

Jump to

Keyboard shortcuts

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