speech

package
v0.61.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: Apache-2.0 Imports: 14 Imported by: 10

Documentation

Overview

Package speech defines the stable text-to-speech protocol and independent synchronous Model and optional Streamer provider capabilities.

NewRequest captures text and Options carries explicit voice, format, speed, and JSON-safe provider overrides written through Options.Extensions.Set. Request has no arbitrary parameter bag. Streamer is separate from Model so consumers only require streaming from implementations that actually support it. ReadChunks preserves byte ownership and read-error ordering for adapters that stream raw audio; transport lifetime stays with the adapter. Collect bounds aggregate audio before appending each chunk and discards partial output on any stream failure. A provider's Stream remains incremental; the aggregate byte budget applies to its synchronous Call.

Example
package main

import (
	"fmt"

	"github.com/Tangerg/scope/core/speech"
)

func main() {
	request, err := speech.NewRequest("Hello from Scope.")
	if err != nil {
		panic(err)
	}
	options := speech.Options{Model: "speech-model"}
	err = options.Validate()
	if err != nil {
		panic(err)
	}
	options.Voice = "alloy"
	options.OutputFormat = "mp3"
	options.Speed = 1
	request.Options = options

	fmt.Println(request.Options.Model, request.Options.Voice, request.Options.Speed)
}
Output:
speech-model alloy 1

Index

Examples

Constants

View Source
const DefaultMaxAudioBytes int64 = 32 << 20

Variables

View Source
var (
	ErrInvalidOptions  = errors.New("speech: invalid options")
	ErrInvalidRequest  = errors.New("speech: invalid request")
	ErrInvalidResponse = errors.New("speech: invalid response")
)

Functions

func ReadChunks added in v0.61.0

func ReadChunks(reader io.Reader) iter.Seq2[[]byte, error]

ReadChunks transfers independently owned bytes in read order, before any non-EOF error from the same read. EOF ends iteration without an error. Reading starts on iteration and stops when the consumer stops; the caller retains responsibility for closing the reader and governing blocked reads. A nil reader, including a typed nil, yields one error without reading.

Types

type Model

type Model interface {
	// Call produces one complete audio response from a validated request. It
	// must not retain or mutate request, transfers response ownership to the
	// caller, and preserves context cancellation for errors.Is.
	Call(ctx context.Context, request *Request) (*Response, error)
}

Model is the synchronous provider-neutral speech generation SPI. Implementations validate requests before I/O, reject explicit options they cannot represent, and return responses that pass Validate. Failures use github.com/Tangerg/scope/core/invocation.ClassifyFailure for evidence about the complete call. A nested failure cannot prove that earlier provider work did not run, and no failure kind authorizes retry.

type ModelFunc

type ModelFunc func(context.Context, *Request) (*Response, error)

func (ModelFunc) Call

func (m ModelFunc) Call(ctx context.Context, request *Request) (*Response, error)

type Options

type Options struct {
	Model string `json:"model"`

	// Voice is a provider-specific speaker profile.
	Voice string `json:"voice"`

	// OutputFormat selects the audio container ("mp3", "wav", ...).
	OutputFormat string `json:"output_format"`

	// Speed scales the playback rate: 1.0 is normal and zero leaves the
	// provider default.
	Speed float64 `json:"speed"`

	Extensions metadata.Extensions `json:"extensions,omitzero"`
}

Options holds provider-neutral text-to-speech configuration. Resolve overlays only explicitly supplied values, merges namespaced extensions, and never aliases mutable data from either input.

func (Options) Clone

func (o Options) Clone() Options

func (Options) JSONSchemaModel added in v0.57.0

func (Options) JSONSchemaModel() any

func (Options) MarshalJSON

func (o Options) MarshalJSON() ([]byte, error)

func (Options) Resolve

func (o Options) Resolve(override Options) (Options, error)

func (*Options) UnmarshalJSON

func (o *Options) UnmarshalJSON(data []byte) error

func (Options) Validate

func (o Options) Validate() error

type Output

type Output struct {
	// Audio holds the encoded bytes in the format selected by
	// Request.Options.OutputFormat.
	Audio []byte `json:"audio,omitzero"`

	Metadata metadata.Map `json:"metadata,omitzero"`
}

Output is one chunk of generated audio. For synchronous calls the chunk is the entire audio; for streaming calls Audio is whatever segment the provider just produced.

func NewOutput

func NewOutput(audio []byte, outputMetadata metadata.Map) (*Output, error)

NewOutput validates and snapshots one provider result before it enters a Response.

func (Output) JSONSchemaModel added in v0.57.0

func (Output) JSONSchemaModel() any

func (Output) MarshalJSON

func (o Output) MarshalJSON() ([]byte, error)

func (*Output) UnmarshalJSON

func (o *Output) UnmarshalJSON(data []byte) error

func (*Output) Validate

func (o *Output) Validate() error

type Request

type Request struct {
	Text string `json:"text"`

	Options Options `json:"options,omitzero"`
}

func NewRequest

func NewRequest(text string) (*Request, error)

func (Request) JSONSchemaModel added in v0.57.0

func (Request) JSONSchemaModel() any

func (Request) MarshalJSON

func (r Request) MarshalJSON() ([]byte, error)

func (*Request) UnmarshalJSON

func (r *Request) UnmarshalJSON(data []byte) error

func (*Request) Validate

func (r *Request) Validate() error

type Response

type Response struct {
	Output *Output `json:"output,omitzero"`

	Metadata *ResponseMetadata `json:"metadata,omitzero"`
}

Response is one TTS call's audio output plus shared metadata. For synchronous calls Output holds the entire audio; for streaming calls each chunk yields a Response with the just-produced segment in Output.

func Collect added in v0.61.0

func Collect(stream iter.Seq2[*Response, error], maxAudioBytes int64) (*Response, error)

Collect publishes a complete result only after the stream succeeds. It retains the terminal chunk's metadata without mutating borrowed responses.

func NewResponse

func NewResponse(output *Output, responseMetadata *ResponseMetadata) (*Response, error)

func (Response) JSONSchemaModel added in v0.57.0

func (Response) JSONSchemaModel() any

func (Response) MarshalJSON

func (r Response) MarshalJSON() ([]byte, error)

func (*Response) UnmarshalJSON

func (r *Response) UnmarshalJSON(data []byte) error

func (*Response) Validate

func (r *Response) Validate() error

type ResponseMetadata

type ResponseMetadata struct {
	Model string `json:"model"`

	CreatedAt time.Time `json:"created_at,omitzero"`

	Extra metadata.Map `json:"extra,omitzero"`
}

func (ResponseMetadata) JSONSchemaModel added in v0.57.0

func (ResponseMetadata) JSONSchemaModel() any

func (ResponseMetadata) MarshalJSON

func (r ResponseMetadata) MarshalJSON() ([]byte, error)

func (*ResponseMetadata) UnmarshalJSON

func (r *ResponseMetadata) UnmarshalJSON(data []byte) error

type Streamer

type Streamer interface {
	// Stream begins synthesis lazily when iterated and yields independently owned
	// audio chunks in provider order. Stopping iteration releases provider
	// resources synchronously; a terminal error is yielded at most once.
	Stream(ctx context.Context, request *Request) iter.Seq2[*Response, error]
}

Streamer is the optional streaming capability. Every yielded response obeys the Model response contract. It is independent from Model, so callers only require streaming when they consume it.

type StreamerFunc

type StreamerFunc func(context.Context, *Request) iter.Seq2[*Response, error]

func (StreamerFunc) Stream

func (s StreamerFunc) Stream(ctx context.Context, request *Request) iter.Seq2[*Response, error]

Jump to

Keyboard shortcuts

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