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

# Quickstart

> Install the KugelAudio SDK for Python, TypeScript, Java, Rust, C++ or Dart, generate your first audio, pre-connect for low latency and run a complete example.

KugelAudio ships official SDKs for Python, TypeScript/JavaScript, Java, Rust, C++ and
Dart. Every page of this reference shows each language in its own tab; pick your
language once and every code block follows it.

| SDK | Runtime | Source (MIT, issues and pull requests welcome) |
|---|---|---|
| Python: Pythonic interface with synchronous and asynchronous APIs | Python 3.10 or newer | [Kugelaudio/python-sdk](https://github.com/Kugelaudio/python-sdk) |
| TypeScript/JavaScript: type-safe interface for Node.js and browsers | Node.js 18 or newer, or a modern browser | [Kugelaudio/js-sdk](https://github.com/Kugelaudio/js-sdk) |
| Java: type-safe builder interface | Java 17 or newer | [Kugelaudio/java-sdk](https://github.com/Kugelaudio/java-sdk) |
| Rust: async client on Tokio, streams as `futures::Stream` | Rust 1.89 or newer | [Kugelaudio/rust-sdk](https://github.com/Kugelaudio/rust-sdk) |
| C++: C++17 library with blocking calls and callbacks | A C++17 compiler, CMake 3.20 or newer, libcurl | [Kugelaudio/cpp-sdk](https://github.com/Kugelaudio/cpp-sdk) |
| Dart: one package for Dart and Flutter, including Flutter web | Dart 3.4 or newer | [Kugelaudio/dart-sdk](https://github.com/Kugelaudio/dart-sdk) |

## Installation

<Tabs>
<Tab title="Python">

```bash
pip install kugelaudio
```

Or with uv (recommended):

```bash
uv add kugelaudio
```

</Tab>
<Tab title="TypeScript">

```bash
npm install kugelaudio
```

Or with yarn/pnpm:

```bash
yarn add kugelaudio
# or
pnpm add kugelaudio
```

The `ws` WebSocket package is installed with it, so Node needs nothing extra.
TypeScript types ship inside the package. There is no `@types/kugelaudio` to
install, and no extra configuration is required.

**Module systems.** The SDK ships both an ESM and a CommonJS build, each with its own
type declarations, so it works from either module system without a bundler or
transpiler:

<CodeGroup>

```typescript ESM / TypeScript
import { KugelAudio } from 'kugelaudio';

const client = new KugelAudio({ apiKey: process.env.KUGELAUDIO_API_KEY! });
```

```javascript CommonJS
const { KugelAudio } = require('kugelaudio');

const client = new KugelAudio({ apiKey: process.env.KUGELAUDIO_API_KEY });
```

</CodeGroup>

Use **named imports**. The package intentionally has no default export, so
`import KugelAudio from 'kugelaudio'` is a type error.

Types resolve correctly under every TypeScript `moduleResolution` setting
(`node`, `node16`, `nodenext`, and `bundler`) for the main entry point and for
the [`kugelaudio/livekit`](/integrations/livekit) subpath.

</Tab>
<Tab title="Java">

Add the dependency to your `pom.xml`:

```xml
<dependency>
  <groupId>com.kugelaudio</groupId>
  <artifactId>kugelaudio</artifactId>
  <version>3.1.0</version>
</dependency>
```

Or with Gradle:

```groovy
implementation 'com.kugelaudio:kugelaudio:3.1.0'
```

</Tab>
<Tab title="Rust">

Add the crate and a Tokio runtime:

```bash
cargo add kugelaudio
cargo add tokio --features macros,rt-multi-thread
cargo add futures-util  # StreamExt, for the streaming examples
```

Every call is `async` and needs a Tokio runtime. TLS goes through rustls, so no
OpenSSL is needed.

</Tab>
<Tab title="C++">

Fetch the library with CMake `FetchContent`:

```cmake
include(FetchContent)
FetchContent_Declare(kugelaudio
  GIT_REPOSITORY https://github.com/Kugelaudio/cpp-sdk.git
  GIT_TAG v0.1.0)
FetchContent_MakeAvailable(kugelaudio)

target_link_libraries(my_app PRIVATE kugelaudio::kugelaudio)
```

libcurl must be installed (for example `apt install libcurl4-openssl-dev`; macOS
ships it). IXWebSocket and nlohmann/json are taken from your system when CMake finds
them, and downloaded at pinned versions otherwise.

Or install it with vcpkg, using the overlay port in the repository's `ports/`
directory, and find the installed package:

```bash
vcpkg install kugelaudio --overlay-ports=/path/to/cpp-sdk/ports
```

```cmake
find_package(kugelaudio CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE kugelaudio::kugelaudio)
```

Include the umbrella header `<kugelaudio/kugelaudio.hpp>`.

</Tab>
<Tab title="Dart">

```bash
dart pub add kugelaudio      # Dart
flutter pub add kugelaudio   # Flutter
```

The package is pure Dart, so it runs on Android, iOS, macOS, Windows, Linux, the web
and servers. File helpers that need `dart:io` live in `package:kugelaudio/io.dart`.

</Tab>
</Tabs>

## Generate your first audio

Create an API key in [the dashboard](https://www.kugelaudio.com/dashboard)
and keep it out of your code, for example in the `KUGELAUDIO_API_KEY` environment
variable (see [Authentication](/api-reference/authentication)). Only Java's
`KugelAudio.fromEnv()` reads `KUGELAUDIO_API_KEY` for you; the other SDKs do not read
the environment on their own, so pass the key explicitly.

<CodeGroup>

```python Python
import os

from kugelaudio import KugelAudio

# Initialize the client
client = KugelAudio(api_key=os.environ["KUGELAUDIO_API_KEY"])

# Generate speech
audio = client.tts.generate(
    text="Hello, world!",
    model_id="kugel-3.5",
    voice_id=1071,
)

# Save to file
audio.save("output.wav")
```

```typescript TypeScript
import { writeFileSync } from 'node:fs';
import { KugelAudio, createWavFile } from 'kugelaudio';

// Initialize the client
const client = new KugelAudio({ apiKey: process.env.KUGELAUDIO_API_KEY! });

try {
  // Generate speech
  const audio = await client.tts.generate({
    text: 'Hello, world!',
    modelId: 'kugel-3.5',
    voiceId: 1071,
  });

  // audio.audio is raw PCM16; wrap it in a WAV header and save it
  writeFileSync('output.wav', Buffer.from(createWavFile(audio.audio, audio.sampleRate)));
  console.log(`Saved ${audio.durationMs}ms of audio to output.wav`);
} finally {
  // The client keeps a pooled WebSocket open; close it so Node can exit
  client.close();
}
```

```java Java
import com.kugelaudio.sdk.KugelAudio;
import com.kugelaudio.sdk.GenerateRequest;
import com.kugelaudio.sdk.AudioResponse;

import java.nio.file.Path;

public class HelloKugelAudio {
    public static void main(String[] args) throws Exception {
        // Reads KUGELAUDIO_API_KEY; or new KugelAudio(KugelAudioOptions.builder(key).build())
        KugelAudio client = KugelAudio.fromEnv();

        AudioResponse audio = client.tts().generate(
            GenerateRequest.builder("Hello, world!")
                .modelId("kugel-3.5")
                .voiceId(1071)
                .language("en")
                .build()
        );

        audio.saveWav(Path.of("output.wav")); // throws IOException
        client.close();
    }
}
```

```rust Rust
use kugelaudio::{KugelAudio, TtsRequest};

#[tokio::main]
async fn main() -> kugelaudio::Result<()> {
    // Initialize the client
    let client = KugelAudio::new(std::env::var("KUGELAUDIO_API_KEY").unwrap_or_default())?;

    // Generate speech
    let request = TtsRequest::new("Hello, world!")
        .model_id("kugel-3.5")
        .voice_id(1071)
        .language("en");
    let audio = client.tts().generate(&request).await?;

    // Save to file
    audio.save_wav("output.wav")?;

    // Close the pooled WebSocket and deliver pending diagnostics
    client.close().await;
    Ok(())
}
```

```cpp C++
#include <cstdlib>

#include <kugelaudio/kugelaudio.hpp>

int main() {
  const char* key = std::getenv("KUGELAUDIO_API_KEY");
  if (key == nullptr) return 1;

  // Initialize the client
  kugelaudio::Client client{key};

  // Generate speech
  kugelaudio::GenerateRequest request;
  request.text = "Hello, world!";
  request.model_id = "kugel-3.5";
  request.voice_id = 1071;
  request.language = "en";
  kugelaudio::AudioResponse audio = client.tts().generate(request);

  // Save to file
  audio.save_wav("output.wav");
}  // The destructor closes the client
```

```dart Dart
import 'dart:io';

import 'package:kugelaudio/io.dart';

Future<void> main() async {
  // Initialize the client
  final client = KugelAudio(apiKey: Platform.environment['KUGELAUDIO_API_KEY']!);

  // Generate speech
  final audio = await client.tts.generate(
    text: 'Hello, world!',
    modelId: 'kugel-3.5',
    voiceId: 1071,
    language: 'en',
  );

  // Save to file (io.dart; in Flutter web use audio.toWav() bytes instead)
  await audio.saveWav('output.wav');

  await client.close();
}
```

</CodeGroup>

In a browser, the TypeScript SDK plays the audio instead of saving it: see
[Playing audio in the browser](/sdks/generate#playing-audio-in-the-browser).

## Pre-connecting for low latency

For latency-sensitive applications, pre-establish the WebSocket connection at startup
to keep the handshake out of your first TTS request. Without pre-connecting, the first
TTS request includes the WebSocket connection setup; later requests reuse the
connection. See [Latency](/latency) for typical numbers.

In the examples below, `play_audio` / `playAudio` stands for your own playback
function; the SDKs do not ship one.

<Tabs>
<Tab title="Python">

**Async applications (recommended):**

```python
import asyncio
import os

from kugelaudio import AudioChunk, KugelAudio

async def main():
    # Create a pre-connected client (handshake happens here)
    client = await KugelAudio.create(api_key=os.environ["KUGELAUDIO_API_KEY"])

    # First request is now fast: no handshake on the hot path
    async for item in client.tts.stream_async("Hello, world!", voice_id=1071):
        if isinstance(item, AudioChunk):
            play_audio(item.audio)

    await client.aclose()

asyncio.run(main())
```

**Sync applications.** For synchronous code that needs connection reuse, keep a
streaming session open across sends:

```python
import os

from kugelaudio import KugelAudio

client = KugelAudio(api_key=os.environ["KUGELAUDIO_API_KEY"])
with client.tts.streaming_session_sync(voice_id=1071) as session:
    for chunk in session.send("Hello, world!"):
        play_audio(chunk.audio)
    for chunk in session.flush():
        play_audio(chunk.audio)
```

<Tip>
  The synchronous `generate()` and `stream()` wrappers create and close a
  connection on their own event-loop thread, so `client.connect()` does not
  pre-connect those calls. Use the async API or `streaming_session_sync()` when
  connection reuse matters.
</Tip>

</Tab>
<Tab title="TypeScript">

**Factory method (recommended):**

```typescript
import { KugelAudio } from 'kugelaudio';

// Create a pre-connected client (handshake happens here)
const client = await KugelAudio.create({ apiKey: process.env.KUGELAUDIO_API_KEY! });

// First request is now fast: no handshake on the hot path
await client.tts.stream(
  { text: 'Hello, world!', modelId: 'kugel-3.5', voiceId: 1071 },
  { onChunk: (chunk) => playAudio(chunk.audio) }
);
```

**Manual connection:**

```typescript
import { KugelAudio } from 'kugelaudio';

// Initialize client
const client = new KugelAudio({ apiKey: process.env.KUGELAUDIO_API_KEY! });

// Pre-connect at startup (handshake happens here)
await client.connect();

// Check connection status
console.log(`Connected: ${client.isConnected()}`);

// First request is now fast
await client.tts.stream(
  { text: 'Hello, world!', voiceId: 1071 },
  { onChunk: (chunk) => playAudio(chunk.audio) }
);
```

Pre-connecting moves the connection overhead to application startup. Call
`client.close()` when you are done so the process can exit.

</Tab>
<Tab title="Java">

By default, `new KugelAudio(options)` immediately starts a WebSocket connection in
the background (`autoConnect = true`), so the handshake is absorbed at client
construction rather than on the first request.

```java
// Connection starts in background automatically (autoConnect = true by default)
KugelAudio client = new KugelAudio(
    KugelAudioOptions.builder("your_api_key").build()
);

// If you need to guarantee the connection is ready before the first request:
client.connect();
System.out.println("Connected: " + client.isConnected());

// Or use the blocking factory method:
KugelAudio connectedClient = KugelAudio.createConnected(
    KugelAudioOptions.builder("your_api_key").build()
);
```

</Tab>
<Tab title="Rust">

```rust
use futures_util::StreamExt;
use kugelaudio::{KugelAudio, StreamEvent, TtsRequest};

let client = KugelAudio::new("your_api_key")?;

// Pre-connect at startup (handshake happens here); None opens it for kugel-3.5
client.tts().connect(None).await?;
println!("Connected: {}", client.tts().is_connected());

// First request is now fast: it reuses the pooled socket
let mut stream = client
    .tts()
    .stream(&TtsRequest::new("Hello, world!").voice_id(1071))
    .await?;
while let Some(event) = stream.next().await {
    if let StreamEvent::Audio(chunk) = event? {
        play_audio(&chunk.audio);
    }
}
```

</Tab>
<Tab title="C++">

```cpp
kugelaudio::Client client{"your_api_key"};

// Pre-connect at startup (blocks until the handshake is done)
client.connect();
std::cout << "Connected: " << client.is_connected() << '\n';

// First request is now fast: it reuses the pooled socket
kugelaudio::GenerateRequest request;
request.text = "Hello, world!";
request.voice_id = 1071;
kugelaudio::StreamCallbacks callbacks;
callbacks.on_audio = [](const kugelaudio::AudioChunk& chunk) { play_audio(chunk.audio); };
client.tts().stream(request, callbacks);
```

</Tab>
<Tab title="Dart">

**Factory method (recommended):**

```dart
// Create a pre-connected client (handshake happens here)
final client = await KugelAudio.create(apiKey: 'your_api_key');

// First request is now fast: no handshake on the hot path
await for (final chunk in client.tts.stream(text: 'Hello, world!', voiceId: 1071)) {
  playAudio(chunk.audio);
}
```

**Manual connection:**

```dart
final client = KugelAudio(apiKey: 'your_api_key');
await client.tts.connect();
print('Connected: ${client.tts.isConnected}');
```

</Tab>
</Tabs>

## Complete example

List the models and voices, generate audio and report its timing:

<CodeGroup>

```python Python
import os

from kugelaudio import KugelAudio

# Initialize client
client = KugelAudio(api_key=os.environ["KUGELAUDIO_API_KEY"])

# List available models
print("Available Models:")
for model in client.models.list():
    print(f"  - {model.id}: {model.name}")

# List available voices
print("\nAvailable Voices:")
result = client.voices.list(limit=5)
for voice in result.voices:
    print(f"  - {voice.id}: {voice.name}")

# Generate audio
print("\nGenerating audio...")
audio = client.tts.generate(
    text="Welcome to KugelAudio. This is an example of high-quality text-to-speech synthesis.",
    model_id="kugel-3.5",
    voice_id=1071,
)

print(f"Generated {audio.duration_seconds:.2f}s of audio in {audio.generation_ms:.0f}ms")
print(f"Real-time factor: {audio.rtf:.2f}x")

# Save to file
audio.save("example.wav")
print("Saved to example.wav")

# Close client
client.close()
```

```typescript TypeScript
import { KugelAudio, base64ToArrayBuffer } from 'kugelaudio';

async function main() {
  // Initialize client
  const client = new KugelAudio({ apiKey: process.env.KUGELAUDIO_API_KEY! });

  try {
    // List available models
    console.log('Available Models:');
    const models = await client.models.list();
    for (const model of models) {
      console.log(`  - ${model.id}: ${model.name}`);
    }

    // List available voices
    console.log('\nAvailable Voices:');
    const { voices } = await client.voices.list({ limit: 5 });
    for (const voice of voices) {
      console.log(`  - ${voice.id}: ${voice.name}`);
    }

    // Generate audio with streaming
    console.log('\nGenerating audio (streaming)...');
    const chunks: ArrayBuffer[] = [];
    let ttfa: number | undefined;
    const startTime = Date.now();

    await client.tts.stream(
      {
        text: 'Welcome to KugelAudio. This is an example of high-quality text-to-speech synthesis.',
        modelId: 'kugel-3.5',
        voiceId: 1071,
      },
      {
        onChunk: (chunk) => {
          if (!ttfa) {
            ttfa = Date.now() - startTime;
            console.log(`Time to first audio: ${ttfa}ms`);
          }
          chunks.push(base64ToArrayBuffer(chunk.audio));
        },
        onFinal: (stats) => {
          console.log(`Generated ${stats.durationMs}ms of audio`);
          console.log(`Generation time: ${stats.generationMs}ms`);
          console.log(`RTF: ${stats.rtf}x`);
        },
      }
    );
  } finally {
    // Release the pooled WebSocket and its keepalive timer
    client.close();
  }
}

main();
```

```java Java
import com.kugelaudio.sdk.*;
import java.nio.file.Path;

public class KugelAudioExample {
    public static void main(String[] args) throws Exception {
        try (KugelAudio client = new KugelAudio(
                KugelAudioOptions.builder("your_api_key").build())) {

            // List available models
            System.out.println("Available Models:");
            for (Model model : client.models().list()) {
                System.out.printf("  - %s: %s%n", model.getId(), model.getName());
            }

            // List available voices
            System.out.println("\nAvailable Voices:");
            VoiceListResponse voiceResult = client.voices().list(null, null, 5, 0);
            for (Voice voice : voiceResult.getVoices()) {
                System.out.printf("  - %d: %s%n", voice.getId(), voice.getName());
            }

            // Generate audio
            System.out.println("\nGenerating audio...");
            AudioResponse audio = client.tts().generate(
                GenerateRequest.builder(
                    "Welcome to KugelAudio. This is an example of high-quality text-to-speech synthesis."
                )
                .modelId("kugel-3.5")
                .voiceId(1071)
                .language("en")
                .build()
            );

            System.out.printf("Generated %.2fs of audio in %.0fms (RTF: %.2f)%n",
                audio.getDurationMs() / 1000.0, audio.getGenerationMs(), audio.getRtf());

            // Save to file
            audio.saveWav(Path.of("example.wav"));
            System.out.println("Saved to example.wav");
        }
    }
}
```

```rust Rust
use kugelaudio::{KugelAudio, TtsRequest, VoiceListOptions};

#[tokio::main]
async fn main() -> kugelaudio::Result<()> {
    // Initialize client
    let client = KugelAudio::new(std::env::var("KUGELAUDIO_API_KEY").unwrap_or_default())?;

    // List available models
    println!("Available Models:");
    for model in client.models().list().await? {
        println!("  - {}: {}", model.id, model.name);
    }

    // List available voices
    println!("\nAvailable Voices:");
    let page = client.voices().list(&VoiceListOptions::default().limit(5)).await?;
    for voice in &page.voices {
        println!("  - {}: {}", voice.id, voice.name);
    }

    // Generate audio over the WebSocket, which also reports timing and usage
    println!("\nGenerating audio...");
    let request = TtsRequest::new(
        "Welcome to KugelAudio. This is an example of high-quality text-to-speech synthesis.",
    )
    .model_id("kugel-3.5")
    .voice_id(1071)
    .language("en");
    let audio = client.tts().stream(&request).await?.collect_response().await?;

    println!(
        "Generated {:.2}s of audio in {:.0}ms",
        audio.duration_seconds(),
        audio.generation_ms.unwrap_or_default()
    );
    println!("Real-time factor: {:.2}x", audio.rtf.unwrap_or_default());

    // Save to file
    audio.save_wav("example.wav")?;
    println!("Saved to example.wav");

    // Close client
    client.close().await;
    Ok(())
}
```

```cpp C++
#include <cstdlib>
#include <iostream>

#include <kugelaudio/kugelaudio.hpp>

int main() {
  const char* key = std::getenv("KUGELAUDIO_API_KEY");
  if (key == nullptr) return 1;
  try {
    // Initialize client
    kugelaudio::Client client{key};

    // List available models
    std::cout << "Available Models:\n";
    for (const auto& model : client.models().list()) {
      std::cout << "  - " << model.id << ": " << model.name << '\n';
    }

    // List available voices
    std::cout << "\nAvailable Voices:\n";
    kugelaudio::VoiceListOptions options;
    options.limit = 5;
    for (const auto& voice : client.voices().list(options).voices) {
      std::cout << "  - " << voice.id << ": " << voice.name << '\n';
    }

    // Generate audio over the WebSocket, which also reports timing and usage
    std::cout << "\nGenerating audio...\n";
    kugelaudio::GenerateRequest request;
    request.text =
        "Welcome to KugelAudio. This is an example of high-quality text-to-speech synthesis.";
    request.model_id = "kugel-3.5";
    request.voice_id = 1071;
    request.language = "en";
    kugelaudio::AudioResponse audio = client.tts().stream(request);

    std::cout << "Generated " << audio.duration_seconds() << "s of audio in "
              << audio.generation_ms << "ms\n";
    std::cout << "Real-time factor: " << audio.rtf << "x\n";

    // Save to file
    audio.save_wav("example.wav");
    std::cout << "Saved to example.wav\n";
  } catch (const kugelaudio::KugelAudioError& e) {
    std::cerr << e.type_name() << ": " << e.what() << '\n';
    return 1;
  }
}
```

```dart Dart
import 'dart:io';

import 'package:kugelaudio/io.dart';

Future<void> main() async {
  // Initialize client
  final client = KugelAudio(apiKey: Platform.environment['KUGELAUDIO_API_KEY']!);

  try {
    // List available models
    print('Available Models:');
    for (final model in await client.models.list()) {
      print('  - ${model.id}: ${model.name}');
    }

    // List available voices
    print('\nAvailable Voices:');
    final page = await client.voices.list(limit: 5);
    for (final voice in page.voices) {
      print('  - ${voice.id}: ${voice.name}');
    }

    // Generate audio over the WebSocket, which also reports timing and usage
    print('\nGenerating audio...');
    final audio = await client.tts
        .stream(
          text: 'Welcome to KugelAudio. This is an example of high-quality '
              'text-to-speech synthesis.',
          modelId: 'kugel-3.5',
          voiceId: 1071,
          language: 'en',
        )
        .collect();

    print('Generated ${audio.durationMs.round()}ms of audio '
        'in ${audio.generationMs?.round()}ms');
    print('Real-time factor: ${audio.rtf}x');

    // Save to file
    await audio.saveWav('example.wav');
    print('Saved to example.wav');
  } finally {
    // Close client
    await client.close();
  }
}
```

</CodeGroup>

## Browser support

<Tabs>
<Tab title="Python">

Not applicable: the Python SDK runs on your server.

</Tab>
<Tab title="TypeScript">

The SDK also runs in modern browsers, using the native `WebSocket`. The
credential travels in the WebSocket URL, so never ship a project API key to a
browser: run the SDK on your backend and forward the audio to the browser.

</Tab>
<Tab title="Java">

Not applicable: the Java SDK runs on your server.

</Tab>
<Tab title="Rust">

Not applicable: the Rust SDK runs on your server or device.

</Tab>
<Tab title="C++">

Not applicable: the C++ SDK runs on your server or device.

</Tab>
<Tab title="Dart">

The package also runs in Flutter web, using the browser's `WebSocket`. Code in a
browser exposes its API key to anyone using the page, so never ship a project API key
there: call KugelAudio from your own server and stream the audio to the page.

</Tab>
</Tabs>

## Local turn detection (optional)

<Tabs>
<Tab title="Python">

The Python SDK also ships an optional, local end-of-turn detector for voice agents.
It runs on your machine, needs Python 3.11 or newer, and pulls in PyTorch,
Transformers and ONNX Runtime:

```bash
pip install "kugelaudio[turn-detection]"
hf auth login  # the model bundle is downloaded from Hugging Face
```

Load the detector once per process and create one session per conversation.
Supported languages are `de`, `en`, `es`, `it` and `nl`. `pcm_chunk` stands for
16 kHz mono PCM16 bytes of the user's audio:

```python
from kugelaudio.turn import TurnDetector, TurnMessage

detector = TurnDetector.from_pretrained()
turn = detector.create_session("en")

# Optional: prior dialogue, separate from the current user transcript
turn.update_history([
    TurnMessage("user", "I'd like to book a trip."),
    TurnMessage("assistant", "Where would you like to go?"),
])

# Feed the current user's audio and interim transcript continuously
turn.push_pcm16(pcm_chunk, sample_rate=16_000)
turn.update_transcript("To Berlin, and then")

# Call with the current silence duration whenever your VAD reports silence
decision = turn.observe_silence(duration_ms=200)
if decision.end_turn:
    turn.reset_turn()  # start the assistant response, then reset
```

History requires a bundle trained for multiple context messages; single-message
bundles reject a nonempty history. Supply only messages already known at
scoring time and assistant text that was actually spoken. `update_history()`
replaces the history, `reset_turn()` keeps it, and `reset_conversation()`
clears it.

</Tab>
<Tab title="TypeScript">

Not available in the TypeScript SDK; the local turn detector is Python only.

</Tab>
<Tab title="Java">

Not available in the Java SDK; the local turn detector is Python only.

</Tab>
<Tab title="Rust">

Not available in the Rust SDK; the local turn detector is Python only.

</Tab>
<Tab title="C++">

Not available in the C++ SDK; the local turn detector is Python only.

</Tab>
<Tab title="Dart">

Not available in the Dart SDK; the local turn detector is Python only.

</Tab>
</Tabs>

## Next steps

- [Configuration](/sdks/configuration): client options, authentication modes, regions, lifecycle
- [Generate speech](/sdks/generate): one-shot generation, parameters, word timestamps, models
- [Streaming](/sdks/streaming): streaming sessions for LLM output, barge-in, multi-context sessions
- [Text normalization](/sdks/normalization): languages and spell tags
- [Voices](/sdks/voices): list, create, and manage voices
- [Dictionaries](/sdks/dictionaries): per-project pronunciation and replacement lists
- [Speech enhancement](/sdks/speech-enhancement): remove background noise or keep one voice
- [Types and errors](/sdks/types): exceptions, data models, and enums
- [Agent skill](/guides/agent-skill): teach your coding assistant to write correct KugelAudio code

- [Speech to text](/sdks/speech-to-text): transcribe recordings and stream live audio with Kugel Ear 1
