Paxa Labs

ถอดเสียงแบบเรียลไทม์

WSwss://api.paxalabs.com/v1/stt/live

WS /v1/stt/live ถอดเสียงขณะพูดและตรวจจับจุดจบของแต่ละรอบพูดเอง ออกแบบมาสำหรับ voice agent ส่งเสียงจากไมโครโฟน รับข้อความถอดเสียงฉบับสุดท้ายหนึ่งชุดต่อรอบพูด คิดเครดิตตามความยาวเสียงที่รับเข้ามา

ดูเป็น Markdown
import { open } from "node:fs/promises";

// Runs on Bun as-is; on Node, `import WebSocket from "ws"` accepts
// the same constructor options. Browsers cannot send this header, and
// API keys never ship to browsers anyway: relay the audio through your
// server.
const socket = new WebSocket("wss://api.paxalabs.com/v1/stt/live", {
  headers: { Authorization: `Bearer ${process.env.PAXA_API_KEY}` },
});

socket.onopen = async () => {
  socket.send(JSON.stringify({
    type: "start",
    model: "paxa-stt-lite-realtime-v1-preview",
    audio: { encoding: "pcm_s16le", sample_rate: 16000 },
    language: "th",
  }));
  // 16 kHz signed 16-bit mono is 32,000 bytes a second. A microphone
  // delivers frames at this pace on its own; a file has to be paced.
  const file = await open("caller.pcm");
  const frame = new Uint8Array(640); // 20 ms
  for (;;) {
    const { bytesRead } = await file.read(frame, 0, frame.length);
    if (bytesRead === 0) break;
    socket.send(frame.subarray(0, bytesRead));
    await new Promise((resolve) => setTimeout(resolve, 20));
  }
  socket.send(JSON.stringify({ type: "end" }));
};

socket.onmessage = (event) => {
  const message = JSON.parse(String(event.data));
  switch (message.type) {
    case "speech_started":
      // The user is talking: stop the agent's audio, cancel its reply.
      break;
    case "transcript":
      if (message.is_final) console.log(`turn ${message.turn}: ${message.text}`);
      break;
    case "done":
      socket.close();
  }
};
{"type":"started","connection":"7d9c2b7e-4a41-4c8e-9a35-1f26d8c04b7a","model":"paxa-stt-lite-realtime-v1-preview"}
{"type":"speech_started","turn":1,"time":0.3}
{"type":"speech_ended","turn":1,"time":12.252}
{"type":"charged","seq":1,"seconds":12.252,"credits":2.56,"total_credits":2.56}
{"type":"transcript","turn":1,"is_final":true,"text":"สวัสดีค่ะคุณสมชายยอดชำระของท่านจำนวน พันสองร้อยห้าสิบ บาทครบกำหนดวันที่ สิบห้า สิงหาคมนี้ชำระผ่านแอปได้ตลอด ยี่สิบสี่ ชั่วโมงค่ะ","start":0.3,"end":12.252}
{"type":"done","total_seconds":12.252,"turns":1,"total_credits":2.56}

เชื่อมต่อครั้งเดียว ส่ง start แล้วสตรีมเสียงดิบเป็นเฟรมไบนารี การเชื่อมต่อจะรายงาน speech_started เมื่อผู้ใช้เริ่มพูด แล้วส่ง speech_ended กับ transcript เมื่อรอบพูดจบ agent จึงหยุดคำตอบของตัวเองได้ตั้งแต่เหตุการณ์แรกและตอบกลับเมื่อได้ transcript การเชื่อมต่อที่เปิดอยู่ถือหนึ่งช่องคำขอพร้อมกันฝั่งถอดเสียงของแพ็กเกจจนกว่าจะปิด หัวข้อการตรวจจับรอบพูดในคู่มือการถอดเสียงอธิบายเหตุการณ์และค่าบริการ

เฮดเดอร์#

authorizationBearer pxa_...จำเป็น

Authorization: Bearer pxa_... (recommended).

x-api-keypxa_...

Alternative to the Authorization header. Ignored when Authorization is present.

การยืนยันตัวตน

การเชื่อมต่อ#

wss://api.paxalabs.com/v1/stt/live Binary frames carry audio in. JSON text frames carry control in, and turn, transcript, and billing events out.

ข้อความฝั่งไคลเอนต์#

startConfigures the session. Must be the first frame; exactly one per connection.

type"start"จำเป็น
modelstringจำเป็น

Realtime transcription model id, for example paxa-stt-lite-realtime-v1-preview. GET /v1/models lists the served catalog; a recording model answers unknown_model here.

ตัวอย่าง "paxa-stt-lite-realtime-v1-preview"
audioobjectจำเป็น

What the binary frames carry, fixed for the connection. The bytes are read exactly as declared. A wrong declaration transcribes noise.

ดูฟิลด์ย่อย
audio.encoding"pcm_s16le" or "mulaw"จำเป็น

"pcm_s16le" is signed 16-bit little-endian PCM, "mulaw" is G.711 mu-law as telephony delivers it. Mono.

audio.sample_rate16000 or 48000 or 8000จำเป็น

Samples per second of the binary frames: 16000 or 48000 for pcm_s16le, 8000 for mulaw. Any other pairing answers validation.

languagestring

The language the speech is expected to be in, as a BCP 47 tag such as "th" or "en". The hint filters nothing. Speech in any other language is still transcribed as spoken, and Thai that switches into English mid-sentence needs no setting. Omitted, the model detects the language itself. Set the tag when detection has picked the wrong language.

up to 16 characterspattern ^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$ตัวอย่าง "th"
timestamps"word"

Adds a words array to every final transcript, one span per word with its start and end in seconds on the connection's clock. Thai words are segmented for you. Costs nothing extra.

style"verbatim" or "clean"

How faithfully the transcript follows the speech. "verbatim", the default, writes exactly what was said: fillers, false starts, and self-corrections included. "clean" drops fillers and merges broken phrases into one, for a transcript that is easier to read. It is a readability choice. A clean transcript departs further from what was said, and our own measurement found it less exact. Any other value answers 400 validation.

ค่าเริ่มต้น "verbatim"
convention"spoken" or "written"

How the transcript writes what was said. "spoken", the default, writes numbers as they were said (สามสิบเปอร์เซ็นต์) and a word said twice as two words, which is what a verbatim transcript, a subtitle, or a language model reading the text needs. "written" keeps display conventions: digits and units (30%), the repetition mark ๆ, for dictated text that will be read on a page. The word timestamps are the same under both.

ค่าเริ่มต้น "spoken"
vocabularyarray of strings

Terms the speech is likely to contain that the model should recognize as written: product names, people, places, jargon, in Thai or any other language. Up to 50 terms of 50 characters each, and a longer list or term answers 400 validation. The terms bias recognition and are never inserted; a term that was not said does not appear. Costs nothing extra and combines with every other option.

ตัวอย่าง ["Paxa Labs","กรุงเทพฯ","quarterly review"]

playbackTells the turn detector when your agent is speaking. Its own voice reaching the microphone then cannot open a turn. While speaking is true, opening a turn takes more sustained speech from the user; a real interruption still opens one and arrives as speech_started. Send it on every change. A session that never sends it treats the room as quiet.

type"playback"จำเป็น
speakingbooleanจำเป็น

true while your agent's audio is playing into the same room as the microphone, false once it stops.

endCloses the turn in progress, if any, and delivers its transcript, then the server sends done and closes with code 1000. Audio after end is ignored.

type"end"จำเป็น

อีเวนต์ฝั่งเซิร์ฟเวอร์#

เฟรมเสียง: Audio bytes in the encoding and sample rate the start frame declared, in any chunking and at any cadence, up to 64 KiB a frame. Sending faster than real time is fine.

startedThe session is configured and listening.

type"started"จำเป็น
connectionstringจำเป็น

Connection id; quote it in support requests (the x-request-id analog).

modelstringจำเป็น

The model serving this session.

speech_startedThe user started speaking. This is the interruption signal. Stop your agent's audio and cancel the reply it was generating. It arrives once enough speech has been heard to be sure. The time it reports is therefore earlier than the moment it arrives.

type"speech_started"จำเป็น
turnintegerจำเป็น

The turn this event belongs to, counting from 1 per connection. A higher number is a later turn: an agent that already replied to turn 3 discards turn 3 and answers turn 4.

min 1
timenumberจำเป็น

Where the user started speaking. In seconds of audio received since the connection's first binary frame, exact to a thousandth.

transcriptA transcript of one turn. The final transcript is the turn: send its text to your language model. An interim gives an earlier look at the same turn and never needs handling on its own.

type"transcript"จำเป็น
turnintegerจำเป็น

The turn this event belongs to, counting from 1 per connection. A higher number is a later turn: an agent that already replied to turn 3 discards turn 3 and answers turn 4.

min 1
is_finalbooleanจำเป็น

true for the turn's finished transcript, sent exactly once per turn. false for an interim transcript of the turn so far, sent at a natural pause and replaced by the final.

textstringจำเป็น

The verbatim transcript of the turn, or of the turn so far. Empty on a final when the turn held no speech the model could read.

startnumberจำเป็น

Where the transcribed audio starts. In seconds of audio received since the connection's first binary frame, exact to a thousandth.

endnumberจำเป็น

Where the transcribed audio ends. In seconds of audio received since the connection's first binary frame, exact to a thousandth.

wordsarray of objects

Word spans on the connection's clock, present on a final when the session set timestamps.

ดูฟิลด์ย่อย
words[].textstringจำเป็น

The spoken input text this span covers. An emotion tag takes no span.

words[].startnumberจำเป็น

Where the span begins in the audio, in seconds.

words[].endnumberจำเป็น

Where the span ends in the audio, in seconds.

speech_endedThe user stopped speaking and the turn is closed. Its final transcript follows. Use it to show that the agent is thinking.

type"speech_ended"จำเป็น
turnintegerจำเป็น

The turn this event belongs to, counting from 1 per connection. A higher number is a later turn: an agent that already replied to turn 3 discards turn 3 and answers turn 4.

min 1
timenumberจำเป็น

Where the turn ended. In seconds of audio received since the connection's first binary frame, exact to a thousandth.

chargedBilling receipt. The connection is charged for the audio it receives, silence included. A period closes at the end of each turn, after a minute of audio with no turn, and at the end of the session. Receipts replace the x-credits-charged header.

type"charged"จำเป็น
seqintegerจำเป็น

The billing period this receipt covers, starting at 1.

secondsnumberจำเป็น

Audio received in this period, in seconds, exact to a thousandth.

creditsnumberจำเป็น

Credits charged for this period, exact to a hundredth. The 0.1-credit request floor applies once per connection, on the first receipt.

total_creditsnumberจำเป็น

Credits charged on this connection so far, the audio of failed turns excluded, exact to a hundredth.

errorSomething failed. An error with a turn leaves the connection open; after a fatal one the server closes with the code listed below.

type"error"จำเป็น
codestringจำเป็น

Stable machine-readable code from the error catalog. Branch on this field; the errors reference documents every code.

turninteger

The turn the error belongs to, when it belongs to one. That turn delivers no transcript; the session keeps listening.

not_billednumber

Credits this turn's audio is held back from the bill, exact to a hundredth. It comes off what the periods after this turn owe. A turn that fails with little audio behind it returns less than this. Sent with a turn.

doneEvery turn is delivered; the server closes with code 1000 after this event. A connection that closes without done did not finish delivering.

type"done"จำเป็น
total_secondsnumberจำเป็น

Audio received on this connection, in seconds, exact to a thousandth.

turnsintegerจำเป็น

Turns the connection delivered or failed.

total_creditsnumberจำเป็น

Credits charged on this connection, the audio of failed turns excluded, exact to a hundredth. Zero when no turn was delivered, which returns the connection's charge in full.

โค้ดปิดการเชื่อมต่อ#

โค้ดคำอธิบาย
1000Normal close after done, or client-initiated.
1001The server is restarting. Reconnect and resume.
1009A binary frame exceeded 64 KiB.
4400A frame violated the session protocol, or the start frame named an unknown model or a sample rate its encoding does not take. Another frame that fails validation answers an error event, and the connection stays open.
4401The API key stopped being valid mid-session.
4402The account cannot cover the request floor at start, or the next billing period.
4403The key's spending cap was reached.
4408No frame arrived and no event was sent for 300 seconds.
4413The client read too slowly and the outbound buffer overflowed.
4429Too many concurrent live connections for the account. Close an existing connection and reconnect.
4500Internal server error.
4502The transcription backend failed for the whole connection. What the delivered periods charged stays charged; a connection that delivered no turn is refunded in full. Reconnect.
4503The transcription backend could not be reached at start. Nothing was charged; retry.

ข้อผิดพลาด#

400validationThe request body, query, or headers failed validation against the endpoint schema, or broke a rule the endpoint's reference states. A field the schema refused adds two fields to the problem body. path names the first failing field by location and name in dot form, such as body.voice or headers.idempotency-key. A body that could not be read gives the path body alone. reason is one stable code from the validation reasons list.
400live_protocolA frame on a live WebSocket violated the session protocol. The frame arrived before start, repeated start, or followed end.
400unknown_modelThe model field does not name a served model.
401unauthorizedThe request carried no API key, or the key is invalid or disabled.
402insufficient_creditsThe account does not have enough credits for this request. Nothing was charged.
403key_limitThis API key reached its spending cap. Nothing was charged.
429concurrency_limitedThe account holds the plan's full count of concurrent requests for this product. Nothing was charged. Each product is limited separately, and an open live connection holds one slot of its product for its lifetime.
500internalRequest state was inconsistent on the server.
502provider_errorModel inference failed after the request was charged.
503provider_unavailableThe model behind this endpoint is not available right now. Nothing was charged.