Перейти к содержимому
ГОЛОС

Голосовой агент на Claude в 2026: рабочий realtime-стек STT→LLM→TTS

Собираем голосового агента на Claude с низкой задержкой: Deepgram/Whisper, Sonnet/Opus и ElevenLabs. Архитектура, latency-бюджет и код.

Голосовые агенты на Claude в 2026: лучший STT + Claude + TTS стек

Если вы пытались собрать голосового агента в этом году, вы упёрлись в ту же стену, что и все: у Claude нет нативного realtime-аудио API. Нет модели claude-realtime, которая принимает байты микрофона и отдаёт байты речи. У OpenAI такая есть — gpt-4o-realtime. У Google есть Gemini Live. У Anthropic на момент написания — нет.

Звучит как проблема. На деле — нет. Подход с пайплайном — STT → LLM → TTS — в 2026 году стал настолько быстрым, что грамотно собранный стек на Claude укладывается в ~700 мс end-to-end, а это ниже порога, на котором человек ощущает паузу. И вы получаете качество ответа Claude, которое для большинства агентских и reasoning-нагруженных голосовых сценариев (поддержка, квалификация лидов, технические ассистенты) заметно лучше, чем у audio-native GPT-4o-realtime.

Это та архитектура, которую мы шипим в продакшене, бюджет латентности, который её делает рабочей, и код для сборки.

Состояние голоса в 2026

Доминируют три архитектуры:

1. Audio-native realtime (один сокет). OpenAI Realtime API и Gemini Live. Открываете WebSocket, стримите PCM внутрь, получаете PCM наружу. Модель сама делает VAD, обрабатывает прерывания и смену реплик. Латентность отличная (~300–500 мс end-to-end). Минус: вы заперты в audio-native модели. У OpenAI это GPT-4o. Никакого Claude Sonnet, никакого o3, никакого tool calling за пределами OpenAI.

2. Каскадный пайплайн (STT → LLM → TTS). Три провайдера, три стрима, склеенные между собой. Больше движущихся частей. Теоретически больше латентность. На практике современный стриминг делает его конкурентным.

3. Гибрид: realtime STT + LLM-как-текст + realtime TTS. Об этом и пост. Уши — Deepgram Nova-3 или Whisper streaming, мозг — Claude Sonnet 4.5 streaming, голос — ElevenLabs Flash. Полный round-trip в проде: 600–800 мс.

Для пользователей Claude пайплайн выигрывает по простой причине: вариант 1 с Claude недоступен. Вопрос только в том, достаточно ли вариант 2/3 закрывает разрыв по латентности, чтобы не платить за использование Claude. Закрывает.

Почему Claude-пайплайн обыгрывает OpenAI Realtime для большинства агентов

Audio-native модели сжимают LLM в тот же forward pass, что и кодер/декодер речи. Так они и достигают скорости — но «рассуждательная» часть оказывается мельче, чем у текстовых аналогов. GPT-4o-realtime заметно слабее GPT-4o-text на многошаговом reasoning, использовании инструментов и следовании инструкциям, и ещё слабее, чем Claude Sonnet 4.5.

Для голосовых сценариев, которые в основном — болтовня (компаньоны, языковые тьюторы), audio-native годится. Для голосовых сценариев, которые требуют:

  • Прочитать и подытожить аккаунт клиента в реальном времени
  • Многошаговый агентский флоу с инструментами (найти заказ, проверить остатки, поставить перезвон)
  • Следовать сложному скрипту или комплаенс-правилам
  • Длинный контекст на документах

— Claude Sonnet 4.5 в пайплайне обыгрывает GPT-4o-realtime по качеству. Штраф 200–400 мс по латентности относительно one-socket realtime того стоит.

Рекомендуемый стек

Микрофон → VAD (Silero) → STT (Deepgram Nova-3 streaming) →
  Claude Sonnet 4.5 (streaming) →
  TTS (ElevenLabs Flash v2.5) → Динамик

Почему именно эти компоненты:

Deepgram Nova-3 для STT. Стриминг частичных транскриптов с шагом ~150 мс, финальный транскрипт ~200 мс после конца реплики. WER на разговорном английском ~5%. Whisper Large v3 streaming через groq — нормальная альтернатива (дешевле, чуть выше латентность, чуть выше WER). Для не-английского беру Whisper.

Claude Sonnet 4.5 в качестве мозга. Стриминг через Anthropic Messages API, время до первого токена обычно 250–400 мс на коротких промптах. Мы ходим через https://api.claudexia.tech/v1 — это добавляет ~30 мс прокси-оверхеда и даёт кэширование + observability.

ElevenLabs Flash v2.5 для TTS. ~200 мс до первого аудио, если кормить токенами по мере генерации. Новый Turbo v3 быстрее, но голоса звучат менее естественно; Flash — золотая середина в 2026.

Silero VAD локально. Крошечная ONNX-модель, кадры по 10 мс, крутится на CPU. Говорит, когда пользователь начал и закончил говорить — чтобы не отправлять тишину в STT и не держать LLM в ожидании на не-реплике.

Бюджет латентности

Куда уходят ~700 мс от конца речи пользователя до первого аудио на выходе:

ЭтапБюджет
VAD: детект конца речи80 мс
Deepgram финальный транскрипт150 мс
Сеть: приложение → Claude40 мс
Claude время до первого токена300 мс
Сеть: Claude → TTS30 мс
ElevenLabs время до первого аудио200 мс
Прогрев аудио-буфера50 мс
Итого воспринимаемая латентность~700 мс

Можно ужать дальше:

  • Спекулятивный TTS: начинать слать токены в TTS, как только Claude выдаст первый конец предложения, не дожидаясь окончания LLM. Экономит ~300 мс на длинных ответах.
  • Предсказательное завершение STT: запускать вызов LLM на высокоуверенном partial-транскрипте, не дожидаясь final. Рискованно, но срезает ~120 мс.
  • Тюнинг endpointing: снизить порог тишины VAD с 500 мс до 300 мс. Срезает 200 мс мёртвого эфира, но повышает частоту ложных срабатываний.

Агрессивный тюнинг доводит до ~450 мс. Ниже — вы уже играете с OpenAI Realtime на его поле.

Прерывание и barge-in

Самое сложное в голосовом агенте — не латентность, а прерывание. Пользователь начинает говорить, пока бот ещё говорит. Бот должен:

  1. Засечь начало речи в пределах ~100 мс (VAD на входном микрофоне, не привязанный к выходу).
  2. Немедленно остановить воспроизведение TTS (убить аудио-буфер, а не просто прекратить генерацию).
  3. Отменить in-flight запрос к Claude (AbortController на вызове SDK).
  4. Выбросить частичный ответ или зашить его в контекст как «[прервано]».

Стейт-машина выглядит так:

IDLE → LISTENING → THINKING → SPEAKING → (обратно в LISTENING)
                       ↑                      ↓
                       └── BARGE-IN ──────────┘

Типичный баг: собственное аудио бота протекает в микрофон и триггерит самопрерывание. Лечится эхо-подавлением (WebRTC AEC в браузере или RNNoise на сервере) и порогом уверенности на VAD.

Код: WebSocket-мост на TypeScript

Минимальный end-to-end луп. Браузер шлёт PCM микрофона на сервер, сервер оркестрирует STT/LLM/TTS, стримит аудио обратно.

import Anthropic from "@anthropic-ai/sdk";
import { createClient as deepgram } from "@deepgram/sdk";
import { ElevenLabsClient } from "elevenlabs";
import WebSocket from "ws";

const claude = new Anthropic({
  baseURL: "https://api.claudexia.tech/v1",
  apiKey: process.env.CLAUDEXIA_API_KEY,
});
const dg = deepgram(process.env.DEEPGRAM_KEY);
const tts = new ElevenLabsClient({ apiKey: process.env.ELEVEN_KEY });

const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (client) => {
  const history: Array<{ role: "user" | "assistant"; content: string }> = [];
  let abortLLM: AbortController | null = null;

  const stt = dg.listen.live({
    model: "nova-3",
    language: "ru",
    smart_format: true,
    interim_results: true,
    endpointing: 300,
  });

  stt.on("Results", async (data: any) => {
    const transcript = data.channel.alternatives[0].transcript;
    if (!transcript) return;

    // Barge-in: пользователь заговорил, пока мы говорили
    if (abortLLM) {
      abortLLM.abort();
      client.send(JSON.stringify({ type: "stop_audio" }));
    }

    if (!data.is_final) return;

    history.push({ role: "user", content: transcript });
    abortLLM = new AbortController();

    const stream = await claude.messages.stream(
      {
        model: "claude-sonnet-4.5",
        max_tokens: 1024,
        system: "Ты — голосовой ассистент. Отвечай не длиннее 2 предложений.",
        messages: history,
      },
      { signal: abortLLM.signal },
    );

    let buffer = "";
    let assistantText = "";
    for await (const chunk of stream) {
      if (chunk.type !== "content_block_delta") continue;
      const delta = (chunk.delta as any).text ?? "";
      buffer += delta;
      assistantText += delta;

      // Сбрасываем в TTS на границе предложения
      const sentenceEnd = buffer.match(/[.!?]\s/);
      if (sentenceEnd) {
        const sentence = buffer.slice(0, sentenceEnd.index! + 1);
        buffer = buffer.slice(sentenceEnd.index! + 2);
        streamTTS(sentence, client);
      }
    }
    if (buffer.trim()) streamTTS(buffer, client);
    history.push({ role: "assistant", content: assistantText });
    abortLLM = null;
  });

  client.on("message", (raw) => {
    // Браузер шлёт сырой 16-bit PCM @ 16kHz
    stt.send(raw);
  });
});

async function streamTTS(text: string, client: WebSocket) {
  const audio = await tts.textToSpeech.convertAsStream(
    "21m00Tcm4TlvDq8ikWAM", // voice id
    {
      text,
      model_id: "eleven_flash_v2_5",
      output_format: "pcm_16000",
    },
  );
  for await (const chunk of audio) {
    client.send(chunk);
  }
}

Это ~80 строк, и они дают рабочий голосовой луп с barge-in. В проде сюда добавляется реконнект, ресемплинг аудио, prompt caching на Claude и метрики.

Когда брать OpenAI Realtime вместо этого

Не используйте Claude-пайплайн, если:

  • Качества GPT-4o хватает для вашего сценария (большая часть потребительского чата — да).
  • Хочется один сокет и одного вендора ради операционной простоты.
  • Нужно < 400 мс end-to-end, а спекулятивный стриминг невозможен.
  • Не нужны Anthropic-специфичные фичи (tool use Claude, длинный контекст, MCP).

Берите Claude-пайплайн, если:

  • Агент делает реальный reasoning, многошаговые tool calls или комплаенс-флоу.
  • Нужен контекст 300K+ для грунтования на документах.
  • У вас уже есть текстовый агент на Claude и вы хотите добавить голос, не переписывая мозг.
  • Хочется независимо менять STT/TTS-провайдеров (например, Whisper для не-английского, региональный TTS под комплаенс).

Итог

В 2026 выбор не «Claude или realtime» — а «Claude-пайплайн или GPT-4o realtime». Для агентских голосовых задач, где ответ должен быть фактически правильным, Claude-пайплайн выигрывает по качеству, а 200 мс латентного штрафа пользователь не замечает. Для чисто разговорной задачи «латентность любой ценой» OpenAI Realtime пока остаётся опцией.

Когда Anthropic выпустит нативный realtime-аудио режим — а они выпустят, — этот пост устареет целиком. До тех пор стек Deepgram + Claude Sonnet 4.5 + ElevenLabs Flash — это бенчмарк, который надо обыгрывать.

Цены на Claude разобрали в обзоре цен Claude API на 2026.