ASR gRPC Integration

Integrating speech recognition directly over gRPC gives you control that a telephony bridge hides: you decide when the platform starts counting audio, when to stop playing a prompt because the caller started speaking, how long to wait for an answer, and what to do when nothing matches. That control comes with a sequence you have to get right. This article explains the session and interaction model, the two ways to supply audio, how grammars are loaded, what the platform sends back, and the mistakes that cost integrators the most time. It covers grammar-based ASR, where the caller’s speech is matched against grammars and returned as a structured result.

Scope. Free-form transcription, NLU, language identification, and diarization use the same session lifecycle but different interactions, and are covered in their own articles. For the message and field definitions, see the gRPC API reference. If you connect through a telephony platform over MRCP instead, see the Media Server integration articles. Settings are described in the ASR & Transcription Settings Reference.

Sessions and interactions

Two objects organize everything you send to the platform.

  • A session represents one conversation, typically one phone call. It holds the audio you stream in and the settings that apply to the work done on that audio. You create it once and close it when the call ends.
  • An interaction is one unit of work against the session’s audio, such as one ASR recognition. A session can run many interactions, one after another or in parallel. Each interaction is a child of its session, so it inherits the session’s settings at the moment it is created.

You send requests and receive results over a bidirectional stream. Requests are wrapped in a session_request, audio_request, interaction_request, or dtmf_request message, and everything the platform returns arrives as a response on the same stream. Each request can carry an optional correlation_id so you can match responses to requests; the platform generates one if you do not.

The call sequence

Every ASR integration follows the same sequence. The differences between batch and streaming mode are in the audio and processing steps and are explained in the sections that follow.

StepYour client sendsWhat happens
1session_createThe platform creates the session and returns the session_id. The request carries your deployment_id and operator_id; you can supply your own session_id (a UUID) or let the platform generate one.
2session_audio_formatDefines the format of the audio you will send. It must be set before any audio is sent and cannot be changed afterward.
3audio_pushAdds binary audio to the session, as one block or in chunks.
4interaction_create_asrCreates the ASR interaction and returns an interaction_id, which you use in every later call for that interaction. Grammars and interaction settings go in this request.
5interaction_begin_processing (streaming only, optional)Starts processing. Depending on the stream start location, processing can also start when the interaction is created.
6interaction_finalize_processing (streaming only, optional)Forces processing to finish and returns the result.
7interaction_request_results (optional)Retrieves the results if your client missed them on the stream.
8interaction_closeEnds the interaction when its processing is complete.
9session_closeEnds the session when all its interactions are complete.

Supplying audio

Audio is pushed into the session with audio_push as raw bytes in the format you declared with session_audio_format.

Audio format fieldMeaning
standard_audio_formatThe format of the audio, such as LINEAR16, ULAW, ALAW, WAV, FLAC, MP3, OPUS, M4A, MP4, or GSM.
sample_rate_hertzThe sample rate. It is mandatory for raw PCM audio and optional for the other formats. The default is 8000 (8 kHz). For formats that carry a header, the value in the header is used instead.
channel_countThe number of audio channels. Specify it only for raw (headerless) multi-channel audio. The default is 1 (mono).

Push WAV audio before you create the interaction. When you use a WAV format, the audio must already be in the session when you create the interaction.

For multi-channel audio, choose the channel to recognize with audio_consume_settings.audio_channel. Channel 0 is used by default.

Choosing a mode: batch or streaming

You select the mode with audio_consume_settings.audio_consume_mode on the interaction. Streaming is the default.


Batch (offline)Streaming (live)
Use it forAudio that already exists, such as a recorded fileA live call, where the caller is speaking while you send audio
SettingAUDIO_CONSUME_MODE_BATCHAUDIO_CONSUME_MODE_STREAMING
When processing startsWhen the interaction is createdOn interaction_begin_processing, or automatically when the interaction is created, depending on the stream start location
When it stopsWhen the platform has processed the audioWhen voice activity detection finds the end of speech, or when you call interaction_finalize_processing
Partial resultsNot applicableAvailable if you enable them

Batch mode

  1. Create the session, set the audio format, and push the whole audio file.
  2. Create the ASR interaction with audio_consume_mode set to AUDIO_CONSUME_MODE_BATCH and your grammars.
  3. The platform processes the audio as soon as the interaction is created, and returns the final result on the stream.
  4. Close the interaction, and close the session when you are done.

In batch mode, the only valid stream start location is STREAM_START_LOCATION_STREAM_BEGIN.

Streaming mode

  1. Create the session and set the audio format.
  2. Create the ASR interaction with your grammars and, if you want it, voice activity detection settings.
  3. Push audio continuously as the call produces it.
  4. Start processing with interaction_begin_processing, or let it start automatically, as described below.
  5. Watch the stream for voice activity events and results. With VAD enabled, the platform detects the end of speech, stops processing, and returns the final result.
  6. Close the interaction and, when the call ends, the session.

Where processing starts

In streaming mode, stream_start_location decides which audio the interaction processes.

ValueProcessing starts from
STREAM_START_LOCATION_STREAM_BEGINThe beginning of the stream. This is the default, and the only option for batch mode.
STREAM_START_LOCATION_BEGIN_PROCESSING_CALLThe audio streamed after you call interaction_begin_processing. Not valid for batch mode.
STREAM_START_LOCATION_INTERACTION_CREATEDThe audio streamed after the interaction was created. Not valid for batch mode.

Choose BEGIN_PROCESSING_CALL when you want to control the start yourself, for example to ignore audio from a prompt that is still playing.

Ending processing: VAD or finalize

Voice activity detection (VAD) is controlled by vad_settings.use_vad.

  • When use_vad is true, VAD detects when the caller starts and stops speaking, and processing stops at the end of speech. In batch mode, the engine looks for the start of speech within the audio and stops at end of speech, so not all loaded audio may be processed.
  • When use_vad is false, all audio selected by the audio consume settings is processed. In streaming mode you must then call interaction_finalize_processing to finish.
  • With VAD on, you can still call interaction_finalize_processing at any time to force processing to stop and return the result.

Voice activity events

While VAD runs, the platform sends vad_event messages that tell your application what is happening in the audio. Each carries the interaction ID and the offset in milliseconds from the start of the audio.

EventMeaning
VAD_EVENT_TYPE_BEGIN_PROCESSINGVAD began processing audio.
VAD_EVENT_TYPE_BARGE_INThe caller started speaking. The audio that the ASR processes starts here. Use this event to stop prompt playback.
VAD_EVENT_TYPE_END_OF_SPEECHEnd of speech occurred. No further audio is processed by VAD for the interaction.
VAD_EVENT_TYPE_BARGE_IN_TIMEOUTVAD timed out waiting for the caller to start speaking. The interaction no longer processes audio.
VAD_EVENT_TYPE_END_OF_SPEECH_TIMEOUTVAD timed out waiting for the caller to stop speaking. The interaction no longer processes audio.
VAD_EVENT_TYPE_END_OF_AUDIO_BEFORE_BARGEINThe audio limit (audio_consume_max_ms) was reached before the caller started speaking.
VAD_EVENT_TYPE_END_OF_AUDIO_AFTER_BARGEINThe audio limit was reached before the caller stopped speaking.

The timing settings that drive these events, barge_in_timeout_ms, end_of_speech_timeout_ms, and eos_delay_ms, are in the ASR & Transcription Settings Reference.

DTMF input

To include keypad input in the recognition, send each key press to the interaction with a dtmf_request (a DtmfPushRequest) that names the interaction_id and the dtmf_key. Valid keys are 0 to 9, A to F, *, and #.

Grammars

An ASR interaction needs at least one grammar. Grammars tell the recognizer what to listen for and how to turn what it hears into a structured result. To learn how to write them, see A SRGS Introduction and Intro to Semantic Interpretation.

Where grammars are loaded

LevelHowWhen to use it
InteractionList the grammars in the grammars field of interaction_create_asr.Most applications.
SessionLoad each grammar once with session_load_grammar and a label, then reference it from any interaction in the session with session_grammar_label.Advanced use: a grammar that many interactions in the same call reuse, so it is not reloaded each time.

Loading grammars at the deployment (global) level is not available, and the global_grammar_label field is deprecated. Once processing has begun, the grammar list cannot be changed for that interaction.

Ways to supply a grammar

Each entry in grammars is one of the following.

FieldWhat it is
grammar_urlA URL from which the platform fetches the grammar. For how fetched grammars are cached, see HTTP Caching.
inline_grammar_textThe raw grammar text, sent in the request.
session_grammar_labelA reference to a grammar previously loaded at the session level.
builtin_voice_grammarA built-in voice grammar: BOOLEAN, CURRENCY, DATE, DIGITS, NUMBER, PHONE, or TIME. Built-in grammars are language-specific. See Builtin Grammars.
builtin_dtmf_grammarA built-in DTMF grammar.
labelAn optional label that is used in error reporting. Labels can contain only letters, digits, hyphens, and underscores.
grammar_weightAn optional scaling weight for the grammar. A value of 0 or unset uses the service default of 1.0. See Applying Grammar Weights.

Example: load once, reuse in an interaction

First, load the grammar at the session level:

{
  "session_request": {
    "session_load_grammar": {
      "language": "en-US",
      "grammar_label": "account-number",
      "grammar_url": "https://grammars.example.com/account-number.grxml"
    }
  }
}

Then create a streaming ASR interaction that uses it, with VAD enabled:

{
  "interaction_request": {
    "interaction_create_asr": {
      "language": "en-US",
      "grammars": [
        { "session_grammar_label": "account-number" }
      ],
      "vad_settings": {
        "use_vad": true
      },
      "audio_consume_settings": {
        "audio_consume_mode": "AUDIO_CONSUME_MODE_STREAMING"
      }
    }
  }
}

Field names are shown as they appear in the API reference. The grammar label must be one you loaded with session_load_grammar, and a label can contain only letters, digits, hyphens, and underscores. The language selects the language for the grammars, either with a dialect such as en-US or dialect-independent such as en.

Results

Results arrive on the session response stream. The messages you handle in an ASR integration are:

ResponseWhen it arrives
final_resultWhen the interaction has a final result. It carries the interaction ID, the result, and a final status.
partial_resultWhile the caller is still speaking, if partial results are enabled with recognition_settings.enable_partial_results.
vad_eventAs voice activity detection finds events in the audio (see above).
session_eventWhen something goes wrong. It carries a status message and, if applicable, the interaction ID.
interaction_request_resultsIn response to an interaction_request_results request.

Final status

Check the final status before you read the result. These are the statuses an ASR interaction returns.

StatusMeaning
FINAL_RESULT_STATUS_GRAMMAR_MATCHA complete grammar match was returned.
FINAL_RESULT_STATUS_GRAMMAR_PARTIAL_MATCHRaw text was returned, but it could not be parsed with the supplied grammars.
FINAL_RESULT_STATUS_GRAMMAR_NO_MATCHNo result could be obtained for the audio with the supplied grammars.
FINAL_RESULT_STATUS_NO_INPUTNo voice audio was detected. The result is empty.
FINAL_RESULT_STATUS_ERRORAn error occurred that stopped processing.
FINAL_RESULT_STATUS_CANCELLEDThe interaction was cancelled or closed before results could be returned.

What a result contains

An ASR result (asr_interaction_result) holds a list of the best matches, n_bests, plus the input_mode (for example speech or DTMF) and the language. Each match contains:

FieldWhat it holds
asr_result_meta_dataThe raw transcript: transcript as one string, the individual words, start_time_ms and duration_ms, and a confidence from 0 to 1000. Each word has its own start time, duration, and confidence.
semantic_interpretationsThe structured results that the grammar produced. Each has the interpretation (also available as interpretation_json), the grammar_label of the grammar that produced it, a confidence from 0 to 1000, the tag_format, and the input_text.

The number of matches returned is set by recognition_settings.max_alternatives, which is 1 by default. Confidence values are integers from 0 to 1000.

If your client misses a result on the response stream, call interaction_request_results with the interaction ID to retrieve it.

Settings you can supply

The ASR create request accepts these settings groups: grammar_settings, recognition_settings, vad_settings, audio_consume_settings, and general_interaction_settings. You can also set defaults at the session or deployment level, and an interaction takes a snapshot of its settings when it is created. See Speech Settings: Hierarchy, Inheritance and Value Types for how that works, and the ASR & Transcription Settings Reference for every setting.

Troubleshooting

SymptomLikely cause and fix
The first audio is rejected or the audio format is unknownSend session_audio_format before any audio_push. The format must be set before audio is sent and cannot be changed afterward.
A WAV file produces no resultPush the WAV audio before you create the interaction.
A streaming interaction never returnsIf use_vad is false, call interaction_finalize_processing. If VAD is on, check for VAD_EVENT_TYPE_BARGE_IN_TIMEOUT or END_OF_SPEECH_TIMEOUT events, and review the timing settings.
The result status is NO_INPUTNo speech was detected in the audio that was processed. Check the stream start location, the audio channel, and whether prompt audio or silence was processed instead of the caller’s speech.
The status is GRAMMAR_PARTIAL_MATCH or GRAMMAR_NO_MATCHThe speech was recognized but did not match the grammar, or nothing matched. Review the grammar and the language selector. The raw transcript is still returned for a partial match.
A session grammar label is not foundLoad it with session_load_grammar in the same session before you reference it. Labels can contain only letters, digits, hyphens, and underscores.
Loading a grammar from a URL fails or is slowCheck that the platform can reach the URL, and review the grammar load timeout in the grammar settings. See HTTP Caching for how fetched grammars are cached.
Changing the grammar list has no effectThe grammar list cannot be changed after processing has begun. Create a new interaction.
Results were missedCall interaction_request_results with the interaction ID.

Related Articles


Was this article helpful?