The previous lesson decoded a neural file all at once. This one feeds it chunk by chunk to simulate a live stream.
bciTranscribeStream opens a duplex session. Writing bytes into session.write(chunk) feeds the sliding window, and iterating the session reads the decoded text as the window advances. The session is fully streaming on both sides: writes don't have to wait for the previous decode to finish, and the reader doesn't have to wait for a full file.
The first step is loading the BCI model. whisperConfig and bciConfig tell the engine which day of neural data we're transcribing:
const modelId = await loadModel({
modelSrc: BCI_WINDOWED,
modelConfig: {
whisperConfig: { language: "en", n_threads: 4, temperature: 0.0 },
bciConfig: { day_idx: 1 },
},
});The session needs one behavior change before it can stream useful updates. Set emit: "delta" so each read contains only the new tokens instead of replaying the full transcript. The session options would look like this:
const session = await bciTranscribeStream({ modelId, emit: "delta" });Sequential read-then-write would deadlock, so the consume task runs as an IIFE in parallel with the write loop, with await consume after session.end(). Writing in 64KB chunks looks like:
const consume = (async () => {
for await (const text of session) {
process.stdout.write(text);
}
})();
const data = readFileSync(neuralFilePath);
for (let offset = 0; offset < data.length; offset += CHUNK_SIZE) {
const chunk = data.subarray(offset, offset + CHUNK_SIZE);
session.write(chunk);
await new Promise((resolve) => setTimeout(resolve, 10));
}
session.end();
await consume;
await unloadModel({ modelId });emit: "delta" is the mode that streams the running transcript (each iteration is the new text since the last read). The alternative mode emits the full transcript on every read.
Note: a 64KB chunk is a reasonable starting size for the example, but a real device driver usually has a buffer of its own. If your source is producing frames continuously, the write loop forwards each frame as it comes in.
Question 1 of 2
What happens if the consume task reads the sliding window only after the write loop finishes?
Question 2 of 2
How does emit: 'delta' change each iteration's output?
Run your code, check your answer, or ask a question. It all shows up here.