> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# synthesize()

> Convert text to speech with neural voices

<Note>**Early Beta** -- The Web SDK is in early beta. APIs may change between releases.</Note>

## Overview

The Text-to-Speech (TTS) API converts text to spoken audio using on-device neural voice synthesis with Piper TTS compiled to WebAssembly. All synthesis happens locally in the browser.

## Basic Usage

```typescript theme={null}
import { TTS } from '@runanywhere/web'

const result = await TTS.synthesize('Hello, welcome to the RunAnywhere SDK!')
console.log('Duration:', result.durationMs, 'ms')
console.log('Sample rate:', result.sampleRate)
// result.audioData is a Float32Array of PCM samples
```

## Setup

Before synthesizing, load a TTS voice model:

```typescript theme={null}
import { TTS } from '@runanywhere/web'

await TTS.loadVoice({
  voiceId: 'piper-en-lessac',
  modelPath: '/models/piper-en-lessac.onnx',
  tokensPath: '/models/tokens.txt',
  dataDir: '/models/espeak-ng-data',
})
```

## API Reference

### `TTS.loadVoice`

Load a TTS voice model.

```typescript theme={null}
await TTS.loadVoice(config: TTSVoiceConfig): Promise<void>
```

### TTSVoiceConfig

```typescript theme={null}
interface TTSVoiceConfig {
  /** Unique voice identifier */
  voiceId: string

  /** Path to VITS/Piper ONNX model */
  modelPath: string

  /** Path to tokens file */
  tokensPath: string

  /** Path to espeak-ng-data directory (for Piper voices) */
  dataDir?: string

  /** Path to lexicon file */
  lexicon?: string

  /** Number of threads (default: 1) */
  numThreads?: number
}
```

### `TTS.synthesize`

Convert text to audio data.

```typescript theme={null}
await TTS.synthesize(
  text: string,
  options?: TTSSynthesizeOptions
): Promise<TTSSynthesisResult>
```

**Parameters:**

| Parameter | Type                   | Description             |
| --------- | ---------------------- | ----------------------- |
| `text`    | `string`               | Text to synthesize      |
| `options` | `TTSSynthesizeOptions` | Optional voice settings |

### TTSSynthesizeOptions

```typescript theme={null}
interface TTSSynthesizeOptions {
  /** Speaker ID for multi-speaker models (default: 0) */
  speakerId?: number

  /** Speech speed multiplier (default: 1.0) */
  speed?: number
}
```

### TTSSynthesisResult

```typescript theme={null}
interface TTSSynthesisResult {
  /** Raw PCM audio data */
  audioData: Float32Array

  /** Audio sample rate in Hz */
  sampleRate: number

  /** Audio duration in milliseconds */
  durationMs: number

  /** Processing time in milliseconds */
  processingTimeMs: number
}
```

## Examples

### Basic Synthesis with Playback

```typescript theme={null}
import { TTS, AudioPlayback } from '@runanywhere/web'

const result = await TTS.synthesize('Hello from RunAnywhere!')
const player = new AudioPlayback()
await player.play(result.audioData, result.sampleRate)
```

### With Speed Options

```typescript theme={null}
// Slower speech
const slow = await TTS.synthesize('This is spoken slowly.', { speed: 0.75 })

// Faster speech
const fast = await TTS.synthesize('This is spoken quickly!', { speed: 1.5 })

// Normal speed (default)
const normal = await TTS.synthesize('This is normal speed.', { speed: 1.0 })
```

### Multi-Speaker Model

```typescript theme={null}
// Use different speakers from the same model
const speaker0 = await TTS.synthesize('Hello from speaker zero.', { speakerId: 0 })
const speaker1 = await TTS.synthesize('Hello from speaker one.', { speakerId: 1 })
```

### React TTS Component

```tsx TextToSpeech.tsx theme={null}
import { useState, useCallback } from 'react'
import { TTS, AudioPlayback } from '@runanywhere/web'

export function TextToSpeech() {
  const [text, setText] = useState('')
  const [isPlaying, setIsPlaying] = useState(false)

  const handleSpeak = useCallback(async () => {
    if (!text.trim()) return

    setIsPlaying(true)
    try {
      const result = await TTS.synthesize(text, { speed: 1.0 })
      const player = new AudioPlayback()

      player.onComplete(() => setIsPlaying(false))
      await player.play(result.audioData, result.sampleRate)
    } catch (error) {
      console.error('Synthesis failed:', error)
      setIsPlaying(false)
    }
  }, [text])

  return (
    <div>
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Enter text to speak..."
      />
      <button onClick={handleSpeak} disabled={isPlaying || !text.trim()}>
        {isPlaying ? 'Speaking...' : 'Speak'}
      </button>
    </div>
  )
}
```

## Voice Properties

After loading a voice, check its properties:

```typescript theme={null}
console.log('Voice loaded:', TTS.isVoiceLoaded)
console.log('Voice ID:', TTS.voiceId)
console.log('Sample rate:', TTS.sampleRate)
console.log('Speakers:', TTS.numSpeakers)
```

## Speed Options

| Speed | Effect                 |
| ----- | ---------------------- |
| 0.5   | Half speed (very slow) |
| 0.75  | Slower than normal     |
| 1.0   | Normal speed (default) |
| 1.25  | Slightly faster        |
| 1.5   | Fast                   |
| 2.0   | Double speed           |

## Error Handling

```typescript theme={null}
import { TTS, SDKError, SDKErrorCode } from '@runanywhere/web'

try {
  const result = await TTS.synthesize(text)
} catch (err) {
  if (err instanceof SDKError) {
    switch (err.code) {
      case SDKErrorCode.NotInitialized:
        console.error('Initialize the SDK first')
        break
      case SDKErrorCode.ModelNotLoaded:
        console.error('Load a TTS voice first')
        break
      default:
        console.error('TTS error:', err.message)
    }
  }
}
```

## Related

<CardGroup cols={2}>
  <Card title="TTS Voices" icon="waveform" href="/web/tts/voices">
    Available voices and voice management
  </Card>

  <Card title="Voice Agent" icon="robot" href="/web/voice-agent">
    Full voice pipeline
  </Card>

  <Card title="Audio Playback" icon="play" href="/web/configuration#audio-utilities">
    Playing synthesized audio
  </Card>
</CardGroup>
