Skip to content

Custom spelling

The problem. The model hears a word correctly but writes it its own way: “e mail” where your style guide says “e-mail”, “sequel” for “SQL”, “gladia” without its capital. Custom spelling rewrites those variants into your spelling, in every transcript, before you receive them.

Where it works. Every model.

{
"realtime_processing": {
"custom_spelling": true,
"custom_spelling_config": {
"spelling_dictionary": { "SQL": ["sequel"], "e-mail": ["email", "e mail"] }
}
}
}

Each key is the spelling you want; its values are the variants to replace.

Each program streams a 16-bit WAV file and prints what comes back. Put your API key in the GLADIA_API_KEY environment variable, then run python custom_spelling.py meeting.wav.

custom_spelling.py
# pip install gladiaio-sdk
import os
import sys
import threading
import wave
from gladiaio_sdk import GladiaClient, LiveV2InitRequest
API_URL = os.environ.get("GLADIA_API_URL", "https://eu1.api.gladia.io")
API_KEY = os.environ["GLADIA_API_KEY"]
with wave.open(sys.argv[1]) as wav: # a 16-bit PCM WAV file
rate, channels = wav.getframerate(), wav.getnchannels()
audio = wav.readframes(wav.getnframes())
config = {
"encoding": "wav/pcm",
"sample_rate": rate,
"bit_depth": 16,
"channels": channels,
"model": "solaria-3",
"language_config": {
"languages": [
"en"
]
},
"realtime_processing": {
"custom_spelling": True,
"custom_spelling_config": {
"spelling_dictionary": {
"Gladia": [
"gladya",
"glad ia"
],
"SQL": [
"sequel"
],
"e-mail": [
"email",
"e mail"
]
}
}
}
}
client = GladiaClient(api_key=API_KEY, api_url=API_URL)
session = client.live_v2().start_session(LiveV2InitRequest.from_dict(config))
ended, errors = threading.Event(), []
@session.on("message")
def on_message(message):
if message.type == "transcript" and message.data.is_final:
print(message.data.utterance.text)
session.on("error", errors.append)
session.once("ended", lambda _: ended.set())
step = rate * channels * 2 // 10 # 100 ms of audio per chunk
for start in range(0, len(audio), step):
session.send_audio(audio[start : start + step]) # live audio: send each chunk as it is captured
session.stop_recording()
ended.wait(timeout=60)
sys.exit(1 if errors or not ended.is_set() else 0)
{ "type": "transcript", "data": { "is_final": true, "utterance": { "text": "Send the SQL query by e-mail to Gladia." } } }

The rewrite applies to partial and final transcripts, and to the text of their words.

  • Whole words, any case. “sequel” is rewritten, “sequels” is not. Add each form you need as a variant.
  • The longest variant wins. With “e mail” and “mail” both listed, “e mail” is rewritten first.
  • It does not change what is recognised. If the model writes something else entirely, there is nothing to rewrite: help it hear the word with custom vocabulary, then fix the spelling here.
  • Values must be lists. {"SQL": "sequel"} is refused (400): write {"SQL": ["sequel"]}.
  • Translations are not rewritten. Translation works from the audio, not from the transcript.
  • Size limit. The spelling dictionary shares the session’s URL budget with the vocabulary and custom_metadata: a few hundred entries in all, else 400 “the session configuration is too large…”.
  • Entities keep their tags. With entities or PII redaction, the rewrite never touches the inline elements, only the words.
symptom cause fix
a variant is not rewritten it is part of a longer word, or a different form add that exact form as a variant
400 on custom_spelling_config a value is a string, not a list wrap it in a list
the spelling flag is on, nothing changes custom_spelling_config missing, or the variant is never written by the model send the dictionary; check the raw transcript first