Migrating from Truebar 2.x to 3.x
Truebar 3.x introduced pipelines: every request supplies the full sequence of stages (ASR, NLP, TTS, β¦) together with their parameters. This section highlights what changed from 2.x and provides concrete steps for bringing older integrations forward.
#
What changed- No stored configuration β The
/api/client/configuration
endpoint is gone. Each streaming session or offline job submits its own pipeline definition. - Unified schema β Streaming (WebSocket) and offline (HTTP) APIs now share the same pipeline JSON structure.
- Richer roles β Access control maps directly to stages (
STAGE_ASR
,STAGE_TTS
,STAGE_NLP_TN
, β¦) instead of broad βrecognition/synthesisβ scopes. - Session lifecycle β Clients send an explicit
EOS
message to finish streaming sessions. Sessions can be resumed later by id.
#
Migrating offline jobsOld flow (2.x):
PATCH /api/client/configuration
β store ASR/NLP/TTS preferences on the server.POST /api/client/upload?async=true|false
β upload media and rely on the stored configuration.
New flow (3.x):
- Build a pipeline definition locally (list of stages with tags & parameters).
POST /api/pipelines/process?async=<true|false>
β send the pipeline as JSON plus the binary/text payload.
#
Example conversion2.x
curl --location --request PATCH "$TRUEBAR_API_BASE_URL/api/client/configuration" \ --header "Authorization: Bearer $TOKEN" \ --header "Content-Type: application/json" \ --data-raw '{ "stt": { "framework": "NEMO", "language": "sl-SI", "domain": "COL", "model": "20221208-0800", "enableInterims": true }, "nlp": { "punctuation": { "enabled": { "value": true, "enableRealFinals": true } } } }'
curl --location --request POST "$TRUEBAR_API_BASE_URL/api/client/upload?async=true" \ --header "Authorization: Bearer $TOKEN" \ --form 'file=@/path/to/audio.wav'
- cURL
- Python
- JavaScript (Node.js)
- Java
curl --location --request POST "$TRUEBAR_API_BASE_URL/api/pipelines/process?async=true" --header "Authorization: Bearer $TOKEN" --form 'pipeline=[ { "task": "ASR", "exceptionHandlingPolicy": "THROW", "config": { "tag": "NEMO_ASR:sl-SI:COL:20221208-0800", "parameters": { "enableInterims": true } } }, { "task": "NLP_pc", "exceptionHandlingPolicy": "SKIP", "config": { "tag": "NEMO_PUNCTUATOR:sl-SI:*:*", "parameters": { "enableSplitToSentences": true } } } ];type=application/json' --form 'data=@/path/to/audio.wav'
import jsonimport osfrom pathlib import Path
import requests
pipeline = [ { "task": "ASR", "exceptionHandlingPolicy": "THROW", "config": { "tag": "NEMO_ASR:sl-SI:COL:20221208-0800", "parameters": {"enableInterims": True}, }, }, { "task": "NLP_pc", "exceptionHandlingPolicy": "SKIP", "config": { "tag": "NEMO_PUNCTUATOR:sl-SI:*:*", "parameters": {"enableSplitToSentences": True}, }, },]
response = requests.post( f"{os.environ['TRUEBAR_API_BASE_URL']}/api/pipelines/process", params={"async": "true"}, headers={"Authorization": f"Bearer {os.environ['TRUEBAR_ACCESS_TOKEN']}"}, files={ "pipeline": ("pipeline.json", json.dumps(pipeline), "application/json"), "data": ("audio.wav", Path("/path/to/audio.wav").read_bytes(), "audio/wav"), }, timeout=30,)response.raise_for_status()print(response.json())
import { readFileSync } from 'node:fs';import FormData from 'form-data';import axios from 'axios';
const pipeline = [ { task: 'ASR', exceptionHandlingPolicy: 'THROW', config: { tag: 'NEMO_ASR:sl-SI:COL:20221208-0800', parameters: { enableInterims: true }, }, }, { task: 'NLP_pc', exceptionHandlingPolicy: 'SKIP', config: { tag: 'NEMO_PUNCTUATOR:sl-SI:*:*', parameters: { enableSplitToSentences: true }, }, },];
const form = new FormData();form.append('pipeline', JSON.stringify(pipeline), { filename: 'pipeline.json', contentType: 'application/json',});form.append('data', readFileSync('/path/to/audio.wav'), { filename: 'audio.wav', contentType: 'audio/wav',});
const { data } = await axios.post( `${process.env.TRUEBAR_API_BASE_URL}/api/pipelines/process`, form, { params: { async: 'true' }, headers: { Authorization: `Bearer ${process.env.TRUEBAR_ACCESS_TOKEN}`, ...form.getHeaders(), }, },);console.log(data);
import java.io.ByteArrayOutputStream;import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.util.UUID;
public class OfflineV3xExample { public static void main(String[] args) throws Exception { String boundary = "----TruebarV3x" + UUID.randomUUID(); String pipelineJson = """ [ { "task": "ASR", "exceptionHandlingPolicy": "THROW", "config": { "tag": "NEMO_ASR:sl-SI:COL:20221208-0800", "parameters": { "enableInterims": true } } }, { "task": "NLP_pc", "exceptionHandlingPolicy": "SKIP", "config": { "tag": "NEMO_PUNCTUATOR:sl-SI:*:*", "parameters": { "enableSplitToSentences": true } } } ] """;
byte[] audio = Files.readAllBytes(Path.of("/path/to/audio.wav"));
String pipelinePart = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"pipeline\"; filename=\"pipeline.json\"\r\n" + "Content-Type: application/json\r\n\r\n" + pipelineJson + "\r\n"; String audioPartHeaders = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"data\"; filename=\"audio.wav\"\r\n" + "Content-Type: audio/wav\r\n\r\n"; String closingBoundary = "\r\n--" + boundary + "--\r\n";
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); buffer.write(pipelinePart.getBytes(StandardCharsets.UTF_8)); buffer.write(audioPartHeaders.getBytes(StandardCharsets.UTF_8)); buffer.write(audio); buffer.write(closingBoundary.getBytes(StandardCharsets.UTF_8));
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(System.getenv("TRUEBAR_API_BASE_URL") + "/api/pipelines/process?async=true")) .header("Authorization", "Bearer " + System.getenv("TRUEBAR_ACCESS_TOKEN")) .header("Content-Type", "multipart/form-data; boundary=" + boundary) .POST(HttpRequest.BodyPublishers.ofByteArray(buffer.toByteArray())) .build();
HttpClient client = HttpClient.newHttpClient(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 400) { throw new IllegalStateException("POST failed: " + response.statusCode() + " - " + response.body()); } System.out.println(response.body()); }}
#
Migrating streaming clientsOld flow (2.x):
- Open WebSocket.
- Stream binary audio frames.
- Send an empty binary message to signal end-of-stream.
- Server closed the socket automatically.
New flow (3.x):
- Open WebSocket with
Authorization: Bearer <token>
header (preferable) or?access_token=
. - Wait for the first
STATUS
message (INITIALIZED
), then send a textCONFIG
message containing the pipeline. - Stream audio (
ASR
) orTEXT_SEGMENT
payloads (TTS
) as before. - Send
{"type":"EOS","lockSession":false}
to finish the session. SetlockSession:true
if you intend to resume later. - Read
STATUS: FINISHED
and close the socket from the client side.
#
CONFIG message structure{ "type": "CONFIG", "sessionId": 12345, // optional: resume existing session "pipeline": [ { "task": "ASR", "exceptionHandlingPolicy": "THROW", "config": { "tag": "KALDI:sl-SI:COL:20221208-0800", "parameters": { "enableInterims": true } } } ]}
#
Message types to handleSTATUS
βINITIALIZED
,CONFIGURED
,FINISHED
, plus warnings and errors.TEXT_SEGMENT
β transcripts (STT) or acknowledgement of processed text (TTS).ERROR
β terminal condition; log the payload and reconnect with a new session.WARNING
β non-critical issues (e.g., nearing quotas).
#
Role mapping2.x concept | 3.x equivalent |
---|---|
RECOGNITION | STAGE_ASR + PIPELINE_ONLINE_API / PIPELINE_OFFLINE_API |
SYNTHESIS | STAGE_TTS (+ relevant STAGE_NLP_* for multi-stage voices) |
HISTORY | same endpoint, but permissions tied to the session owner and group |
Grant the narrowest set of roles needed for each service account to reduce blast radius.
#
Tips for a smooth upgrade- Centralise pipeline builders β wrap pipeline JSON generation in helper functions so multiple microservices reuse the same definitions.
- Log
sessionId
β retain the ID returned by streaming sessions; it lets you look up diagnostics later via the History API. - Validate stage availability β call
/api/pipelines/stages
at startup to ensure required tags exist in the current tenant. - Monitor errors β capture the
id
andmessage
from error responses to accelerate support requests.
#
See also- API Overview β environment setup, roles, discovery.
- Offline Pipeline API β reference for
/api/pipelines/process
. - Streaming STT Guide & Streaming TTS Guide β end-to-end message flows.