Custom metadata
The problem. A transcript is useless if you cannot tie it back to the call, the customer or the agent it came
from. custom_metadata attaches your identifiers to the session: they come back with every result and callback,
and you can search your history with them.
Where it works. Every session.
Step by step
Section titled “Step by step”1. Attach your identifiers
Section titled “1. Attach your identifiers”{ "custom_metadata": { "call_id": "c-8812", "agent": "lea" } }2. Start a session with it
Section titled “2. Start a session with it”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_metadata.py meeting.wav.
# pip install gladiaio-sdkimport osimport sysimport threadingimport 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" ] }, "custom_metadata": { "call_id": "c-8812", "agent": "lea" }}
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 chunkfor start in range(0, len(audio), step): session.send_audio(audio[start : start + step]) # live audio: send each chunk as it is capturedsession.stop_recording()
ended.wait(timeout=60)job = client.live_v2().get(session.session_id) # the session, from your historyprint("metadata:", job.custom_metadata)sys.exit(1 if errors or not ended.is_set() else 0)// npm install @gladiaio/sdkimport { readFileSync } from "node:fs";import { GladiaClient } from "@gladiaio/sdk";
const { sampleRate, channels, pcm } = readWav(process.argv[2]); // a 16-bit PCM WAV file
const config = { encoding: "wav/pcm", sample_rate: sampleRate, bit_depth: 16, channels, model: "solaria-3", language_config: { languages: [ "en" ] }, custom_metadata: { call_id: "c-8812", agent: "lea" }};
const client = new GladiaClient({ apiKey: process.env.GLADIA_API_KEY, apiUrl: process.env.GLADIA_API_URL ?? "https://eu1.api.gladia.io",});const session = client.liveV2().startSession(config);
session.on("message", (message) => { if (message.type === "transcript" && message.data.is_final) console.log(message.data.utterance.text);});session.on("error", (error) => { console.error(error); process.exitCode = 1;});session.once("ended", async () => { const job = await client.liveV2().get(session.sessionId); // the session, from your history console.log("metadata:", job.custom_metadata); process.exit();});
const step = (sampleRate * channels * 2) / 10; // 100 ms of audio per chunkfor (let start = 0; start < pcm.length; start += step) { session.sendAudio(pcm.subarray(start, start + step)); // live audio: send each chunk as it is captured}session.stopRecording();
function readWav(path) { const file = readFileSync(path); let fmt, pcm; for (let pos = 12; pos < file.length; ) { const id = file.toString("ascii", pos, pos + 4); const size = file.readUInt32LE(pos + 4); if (id === "fmt ") fmt = { channels: file.readUInt16LE(pos + 10), sampleRate: file.readUInt32LE(pos + 12) }; if (id === "data") pcm = file.subarray(pos + 8, pos + 8 + size); pos += 8 + size + (size % 2); } return { ...fmt, pcm };}Create the session, then stream its audio to the returned url (Live WebSocket):
curl -X POST https://eu1.api.gladia.io/v2/live \ -H "x-gladia-key: $GLADIA_API_KEY" \ -H "content-type: application/json" \ -d '{ "encoding": "wav/pcm", "sample_rate": 16000, "bit_depth": 16, "channels": 1, "model": "solaria-3", "language_config": { "languages": [ "en" ] }, "custom_metadata": { "call_id": "c-8812", "agent": "lea" } }'3. Get them back
Section titled “3. Get them back”They are in GET /v2/live/{id}, in Gladia Workspace next to the transcript, and in
the history:
curl -G https://eu1.api.gladia.io/v2/live -H "x-gladia-key: $GLADIA_API_KEY" \ --data-urlencode 'custom_metadata={"agent": "lea"}'The filter returns the sessions whose metadata contains the values given: {"agent": "lea"} matches
{"call_id": "c-8812", "agent": "lea"}.
Limits and gotchas
Section titled “Limits and gotchas”- A JSON object. A string or an array is refused (
400). - Small. The metadata travels with the session’s configuration in its WebSocket URL, together with the
vocabulary and the spelling dictionary: keep it to identifiers. Too big,
POST /v2/liveanswers400“the session configuration is too large…”. - Not redacted. PII redaction applies to transcripts, never to metadata: no names, phone numbers or emails in it.
- Exact values. The history filter compares values exactly:
"Lea"does not match"lea". - Set once. It cannot be changed after
POST /v2/live.