1npx @inkibra/voice-cli init
INKIBRA_API_KEY stored on your serverhttps:// and wss:// routesPOST https://voice.example.com/telnyx/answer, then assign the number to that Application. Send stream status callbacks to POST https://voice.example.com/telnyx/status.telnyx-signature-ed25519, telnyx-timestamp, and the account public key. Reject stale timestamps and make callbacks idempotent by event ID.nonce bound to the expected call, then return:123456789101112131415<?xml version="1.0" encoding="UTF-8"?> <Response> <Start> <Stream url="wss://voice.example.com/telnyx/media" codec="PCMU" bidirectionalMode="rtp" bidirectionalCodec="PCMU" bidirectionalSamplingRate="8000" enableReconnect="false" statusCallback="https://voice.example.com/telnyx/status"> <Parameter name="nonce" value="NONCE" /> </Stream> </Start> </Response>
nonce from the WebSocket start event, claim it once, and bind the received call_control_id and stream_id. Telnyx media upgrades are not Ed25519 webhook requests, so the nonce is the media socket credential. Leave enableReconnect="false" until your application supports resuming the same Inkibra session safely.start, pass the connected media socket to your Telnyx audio transport and connect Inkibra:123456789import LiveVoice from "@inkibra/voice-sdk/server"; const session = await LiveVoice.connect({ apiKey: process.env.INKIBRA_API_KEY!, audio: new TelnyxAudioTransport(telnyxSocket, streamId), prompt: "Answer questions about the customer's order.", conversation: { starts: "assistant" }, tools: {}, });
LiveVoice.connect creates, prepares, and starts the Inkibra session. The transport class implements the provider-specific audio mapping in the next step.media.payload is a base64 RTP payload without an RTP header. Reorder media using its sequence/chunk metadata, decode PCMU at 8 kHz to signed PCM16, resample to 24 kHz with persistent state, and send raw little-endian PCM16 to Inkibra in 480-sample, 20 ms binary frames.enqueue command, command.pcm is PCM16LE mono at 24 kHz. Keep mode: "buffer" chunks private until the matching release. Downsample released audio to 8 kHz, encode PCMU, then send media followed by a mark:123456789telnyx.send(JSON.stringify({ event: "media", media: { payload: pcmuAudio.toString("base64") }, })); telnyx.send(JSON.stringify({ event: "mark", mark: { name: generationId }, }));
done, send one mark after the generation's final media chunk. Call handlers.receipt with started when playout begins and completed when Telnyx echoes that mark. On cancel, discard unsent chunks and send:1telnyx.send(JSON.stringify({ event: "clear" }));
clear; classify those generations as cancelled, not completed. Report the number of 24 kHz samples actually played. Honor block-foreground, release, and reaction-versus-foreground lanes exactly as described in Server media.stop, streaming.stopped, call hangup, or either WebSocket closing:12session.stop(); await session.closed;
call_control_id. If Inkibra sends session.limit, a provider error, or closes the WebSocket, send clear, then hang up the Telnyx call.POST /v1/sessions request.release.clear, a cancelled receipt, and no stale audio after the returned marks.session.stop, both sockets closed, and the nonce/call record removed.