Speech API

Сервис tagme-speech предоставляет HTTP/WebSocket proxy-API для распознавания и синтеза речи через SmartSpeech. В объединённом Swagger платформы HTTP-эндпойнты сервиса публикуются в разделе SpeechApi.

Параметры распознавания и синтеза в tagme-speech соответствуют тем же опциям SmartSpeech, что используются в upstream gRPC API. Разница состоит в транспортном уровне:

  • для batch ASR и TTS платформа предоставляет HTTP API;

  • для realtime ASR платформа предоставляет WebSocket API;

WebSocket endpoint распознавания речи в реальном времени /api/v0/speech/asr/ws не отображается в OpenAPI автоматически, поэтому его протокол описан на этой странице отдельно.

TTS

HTTP endpoint:

POST /api/v0/speech/tts
Content-Type: application/json

Параметры запроса соответствуют настройкам синтеза SmartSpeech, описанным в gRPC documentation, но передаются в JSON body HTTP-запроса.

Минимальный запрос:

curl -X POST "https://<host>/api/v0/speech/tts" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Пример текста для синтеза",
    "voice": "May_24000",
    "audio_encoding": "wav"
  }' \
  --output speech.wav

Ответ возвращается как streaming audio body. Тип содержимого зависит от audio_encoding, например audio/wav, audio/ogg или audio/pcm.

ASR

HTTP endpoint:

POST /api/v0/speech/asr
Content-Type: multipart/form-data

Параметры распознавания соответствуют настройкам SmartSpeech Recognition API, но передаются как JSON-строка в поле options multipart/form-data запроса.

Минимальный запрос:

curl -X POST "https://<host>/api/v0/speech/asr" \
  -F "file=@audio.wav"

Пример запроса с параметрами распознавания:

curl -X POST "https://<host>/api/v0/speech/asr" \
  -F "file=@audio.wav" \
  -F 'options={"sample_rate":16000,"encoding":"wav","language":"ru-RU","model":"general"}'

Пример ответа:

{
  "text": "Привет, мир. Как дела?",
  "utterances": [
    {
      "text": "привет мир",
      "normalized_text": "Привет, мир.",
      "start_ms": 0,
      "end_ms": 1500,
      "words": [
        {
          "word": "привет",
          "start_ms": 0,
          "end_ms": 600
        },
        {
          "word": "мир",
          "start_ms": 700,
          "end_ms": 1500
        }
      ],
      "channel": 0,
      "eou_reason": "organic",
      "emotions": {
        "positive": 0.7,
        "neutral": 0.2,
        "negative": 0.1,
        "positive_a": 0.6,
        "neutral_a": 0.3,
        "negative_a": 0.1,
        "positive_t": 0.8,
        "neutral_t": 0.1,
        "negative_t": 0.1
      },
      "speaker_info": null
    },
    {
      "text": "как дела",
      "normalized_text": "Как дела?",
      "start_ms": 1600,
      "end_ms": 2500,
      "words": [],
      "channel": 0,
      "eou_reason": "organic",
      "emotions": null,
      "speaker_info": null
    }
  ],
  "backend_info": {
    "model_name": "general",
    "model_version": "M-02.002.00-general-01",
    "server_version": "1.0.0"
  },
  "vad_events": [],
  "insights": []
}

Realtime ASR over WebSocket

WebSocket endpoint:

WS /api/v0/speech/asr/ws

Параметры options соответствуют тем же настройкам SmartSpeech Recognition API, что и в batch ASR. В отличие от upstream gRPC API, в platform API они передаются в первом JSON-сообщении WebSocket-сессии.

Базовый сценарий работы:

  1. Клиент открывает WebSocket-соединение.

  2. Клиент отправляет конфигурацию распознавания.

  3. Сервер отвечает сообщением готовности.

  4. Клиент отправляет бинарные аудиофреймы.

  5. Сервер возвращает события partial, final, vad, backend_info, insight.

  6. Клиент отправляет stop или закрывает соединение.

  7. Сервер отправляет done и закрывает сессию.

Пример первого сообщения клиента:

{
  "type": "config",
  "options": {
    "sample_rate": 16000,
    "encoding": "pcm_s16le",
    "language": "ru-RU",
    "model": "general",
    "enable_partial_results": true,
    "enable_multi_utterance": true,
    "enable_vad": true
  }
}

Пример ответа о готовности:

{
  "type": "ready",
  "session_id": "8f5c6c5f-7c2a-4e6a-9db0-4d5f77a2c123"
}

Пример промежуточного результата:

{
  "type": "partial",
  "text": "пример",
  "start_ms": 0,
  "end_ms": 420
}

Пример финального результата:

{
  "type": "final",
  "utterance": {
    "text": "пример финального текста",
    "normalized_text": "Пример финального текста.",
    "start_ms": 0,
    "end_ms": 1260,
    "words": [],
    "channel": 0,
    "eou_reason": "organic",
    "emotions": null,
    "speaker_info": null
  }
}

Пример остановки со стороны клиента:

{
  "type": "stop"
}

Использование в шаблонах разметки

Ниже приведены минимальные примеры интеграции без привязки к конкретной структуре формы.

TTS в шаблоне

const response = await fetch("/api/v0/speech/tts", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    text: "Пример текста",
    voice: "May_24000",
    audio_encoding: "wav",
  }),
});

const audioBlob = await response.blob();

ASR в шаблоне

const formData = new FormData();
formData.append("file", audioBlob, "audio.wav");
formData.append(
  "options",
  JSON.stringify({
    sample_rate: 16000,
    encoding: "wav",
    language: "ru-RU",
    model: "general",
  })
);

const response = await fetch("/api/v0/speech/asr", {
  method: "POST",
  body: formData,
});

const result = await response.json();

Realtime ASR в шаблоне

const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const ws = new WebSocket(`${wsProtocol}//${window.location.host}/api/v0/speech/asr/ws`);

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: "config",
    options: {
      sample_rate: 16000,
      encoding: "pcm_s16le",
      language: "ru-RU",
      model: "general",
      enable_partial_results: true,
    },
  }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log(message);
};

function sendAudioChunk(int16PcmChunk) {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(int16PcmChunk.buffer);
  }
}

function stopRecognition() {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ type: "stop" }));
  }
}