Duyu
Live streaming
Send raw PCM from a microphone or phone line; each utterance arrives as a final shortly after silence.
const ws = new WebSocket("wss://voice.patientdesk.ai/v1/audio/stream?key=pd_live_...");
ws.onopen = () => ws.send(JSON.stringify({ type: "start", sampleRate: 48000 }));
// then: ws.send(int16PcmChunk.buffer) for every ~40 ms of microphone audio
ws.onmessage = (e) => {
const m = JSON.parse(e.data);
if (m.type === "final") console.log(m.start, m.end, m.text);
};
// when done: ws.send(JSON.stringify({ type: "stop" }))Protocol
- Open the connection and send
{"type":"start","sampleRate":16000}. Optional:partials: true,partial_ms,eager_final: true. - Send a raw Int16 PCM chunk every 40–100 ms (binary message). The server resamples; 8 kHz telephone band is supported.
- Read events as JSON. When done, send
{"type":"stop"}; the open utterance closes as afinalandstoppedfollows.
Events
readyeventmodel, quota.remaining_s. The connection is ready.vadeventprob, active. About every 100 ms; immediately when active flips. Use it for a level meter.segment_starteventSpeech started (
start).partialeventDraft of the utterance in progress; only with
partials: true, every partial_ms.segment_endeventSpeech ended (
end). A final follows.finaleventtext, start, end, audio_s, infer_ms, rtf. The definitive text of the utterance.stoppedeventAll utterances decoded;
audio_s is the billed duration.erroreventmessage, code.{"type":"ready","model":"duyu-1","quota":{"remaining_s":7130}}
{"type":"vad","prob":0.91,"active":true}
{"type":"segment_start","start":0.42}
{"type":"partial","text":"Yarın saat"}
{"type":"partial","text":"Yarın saat on dörtteki"}
{"type":"segment_end","end":3.10}
{"type":"final","text":"Yarın saat on dörtteki randevumu on altıya alabilir miyiz?","start":0.42,"end":3.10,"audio_s":2.68,"infer_ms":118,"rtf":0.04}
{"type":"stopped","audio_s":2.68}Turn taking
A final arrives after 500 ms of silence. With eager_final: true the model may commit the utterance before the silence threshold, moving a voice agent's reply about 120 ms earlier. No external VAD is needed: vad and segment_* events come from the model itself.