Results & Structured Output
Every time the AI finishes analyzing a clip or frame, it calls your result callback with a StreamInferenceResult.
onResult: (result) => {
if (!result.ok) {
console.warn('Inference failed:', result.error)
return
}
console.log(result.result)
}Result Fields
| Field | Type | Description |
|---|---|---|
result | string | The model's response. Plain text by default, or a JSON string if you set outputSchema. |
ok | boolean | Whether the inference succeeded. Always check this before using result. |
error | string | null | Error message if ok is false. |
finish_reason | "stop" | "length" | "content_filter" | null | Why the model stopped generating. |
inference_latency_ms | number | Time the model spent on inference. |
total_latency_ms | number | End-to-end latency (capture to delivery). |
id | string | Unique result ID. |
stream_id | string | The stream this result belongs to. |
mode | "clip" | "frame" | Which processing mode produced this result. |
model_name | string | The model that ran this inference. |
model_backend | string | The backend used (typically "overshoot"). May be absent. |
prompt | string | The prompt that was active when this result was generated. |
Finish Reason
The finish_reason field tells you why the model stopped:
"stop"— The model finished naturally. Output is complete."length"— The model hit themaxOutputTokenslimit. Output is truncated. Consider increasingmaxOutputTokensor using a longer interval. See Output Token Limits for details on how token budgets are calculated."content_filter"— Output was blocked by safety filtering.null— No finish reason available (usually whenokisfalse).
onResult: (result) => {
if (result.finish_reason === 'length') {
console.warn('Output was truncated — consider increasing maxOutputTokens')
}
}Structured Output
By default, result.result is plain text. Pass an output schema to get JSON:
const vision = new RealtimeVision({
apiKey: 'your-api-key', // Get yours at platform.overshoot.ai/api-keys
model: 'Qwen/Qwen3.5-9B',
prompt: 'Count the people in the frame',
source: { type: 'camera', cameraFacing: 'environment' },
outputSchema: {
type: 'object',
properties: {
count: { type: 'number' },
description: { type: 'string' }
},
required: ['count']
},
onResult: (result) => {
if (!result.ok) return
const data = JSON.parse(result.result)
console.log('People count:', data.count)
}
})result.result is always a string — you need to JSON.parse() it yourself.
If the model can't produce valid JSON matching your schema, result.ok will be false.
Memory Between Results
Currently, each inference is independent — the model doesn't remember previous results. We're actively building native persistent memory so the model can maintain context across results. If this is important to your use case, we'd love to hear from you at founders@overshoot.ai.
In the meantime, you can track state across results in your callback:
let lastCount = 0
const vision = new RealtimeVision({
apiKey: 'your-api-key', // Get yours at platform.overshoot.ai/api-keys
model: 'Qwen/Qwen3.5-9B',
prompt: 'Count the people',
source: { type: 'camera', cameraFacing: 'environment' },
outputSchema: {
type: 'object',
properties: { count: { type: 'number' } },
required: ['count']
},
onResult: (result) => {
if (!result.ok) return
const data = JSON.parse(result.result)
if (data.count !== lastCount) {
console.log(`Count changed: ${lastCount} → ${data.count}`)
lastCount = data.count
}
}
})