The rendering pipeline separates semantic detection data from renderer-owned runtime artifacts.
The two gates are not annotations against masks. A mask is one geometry a detection can carry, beside boxes, polygons, polylines, and keypoints, so both gates are about detections. They differ in which stage above they wait on.
detections.playbackGate, waits for arrival:
whether this frame's detections have reached the source at all, or are still
being fetched, or are still being written by a producer that is running. It
cannot tell one geometry from another, because a frame with no data carries
none of them.renderer.renderPreparation.playbackGate, waits
for preparation: whether the geometries that need rasterizing have become
the ID-mask artifact that draws them. Masks and polygons take that step. The
other geometries have nothing to rasterize, so this gate never waits on them.Both hold every frame on a media source the renderer pulls samples from, and only the start of playback on a source that presents its own frames. See Media Sessions for the defaults and the single switch that answers for both.
Detection frames are app/model data:
mediaTime is seconds on the renderer media timeline;endTime is exclusive when present;frameIndex is optional and only used by frame-grid synchronization;x and y identify its center, not its top-left corner;NotLabeled, Occluded, and
Visible values;0 to 1;The library validates incoming frames before storing or buffering them. Invalid geometry, mask dimensions, confidence values, or frame timing fail early instead of becoming renderer behavior later.
When detections are composed from multiple sources, copied detections can carry two renderer-neutral provenance fields:
sourceId identifies the source entry that produced the copied detection;sourceDetectionIndex identifies the detection's index inside that source
frame before composition.These fields are intentionally generic. A product may decide that one source is model output and another is ephemeral user drawing state, but the library only uses provenance to support deterministic ordering, source-aware styling, and host callbacks.
Advanced integrations can compose sources directly:
const source = createCompositeDetectionFrameSource({
sources: [
{ frames: modelFrames, id: "model" },
{ frames: overlayFrames, id: "overlay", order: 10 },
],
});
A box, a label anchor, a polygon, a polyline, and a keypoint are absolute media pixels. The numbers reach the scene whose unit is one media pixel. Present the same detections against a raster of a different size and every one of them is drawn at the wrong fraction of the picture, far enough off that objects near an edge take their labels off the canvas entirely.
Masks are the exception. A DetectionMask carries the pixel size its counts
are encoded against, and the mask layer stretches the sprite onto whatever the
media is, so a mask lands correctly at any raster. That difference is why a
rescaled source shows correct masks beside misplaced boxes.
Vector geometry is reconciled by declaring where it came from.
DetectionFrame.coordinateSpace names the pixel space a frame's geometry was
produced in. The media renderer wraps every detection source in
createProjectedDetectionFrameSource, which scales that geometry onto the
presented frame and leaves masks alone so the ratio is never applied twice.
It is opt-in, and that is the trap: a frame that declares nothing is taken at its word as already being in the presented frame's pixels. Any source whose geometry was computed against a different raster than the one being played has to declare its space, or the annotations are silently wrong rather than visibly broken.
Compressed RLE is good cold semantic storage. It is not the best thing to loop over in the active video render path.
For dense masks, the library prepares a frame-level ID mask artifact. Each pixel stores background or detection identity. Pixi renders that artifact with shader palette styling, so changing class colors and opacity can stay cheap.
In Python supervision, visual behavior is usually expressed through
annotators. In supervision-js, the equivalent shape is:
This keeps detection data clean and keeps rendering performance decisions inside the engine.
Styles are small objects with a resolve(detection, context) method. They return
renderer-neutral draw instructions or undefined to skip a detection. The
default styles are intentionally practical, but custom styles can change class
colors, opacity, labels, confidence filtering, and shape choices without
changing the stored detections.
The built-in base styles accept static values for simple global styling and resolver functions for per-detection behavior:
const boxStyle = new BaseBoxStyle({
cornerRadius: (detection) => (detection.className === "basketball" ? 999 : 8),
shape: BoxShape.RoundedRect,
shouldRender: (detection) => (detection.confidence ?? 0) >= 0.5,
stroke: (detection) => ({
color: detection.className === "person" ? 0x22c55e : 0xa855f7,
width: 3,
}),
});
session.setPresentation({
renderers: [annotationRenderers.box({ style: boxStyle })],
});
Use a custom style object when the base classes are not expressive enough. The contract stays the same: detections remain semantic data, and styles resolve how that data should be presented.
Continue to Annotation Renderers for focused box, mask, label, polygon, polyline, and keypoint examples backed by the frozen basketball fixture.
One detection may carry any supported semantic geometry:
import { KeypointVisibility, type Detection } from "supervision";
const detection: Detection = {
id: "pose-1",
className: "person",
rect: { x: 320, y: 240, width: 180, height: 360 },
polygon: {
points: [
{ x: 230, y: 60 },
{ x: 410, y: 60 },
{ x: 420, y: 420 },
{ x: 220, y: 420 },
],
},
keypoints: {
points: [
{ x: 320, y: 100 },
{ x: 280, y: 180 },
{ x: 360, y: 180 },
],
edges: [
[0, 1],
[0, 2],
],
visibility: [
KeypointVisibility.Visible,
KeypointVisibility.Visible,
KeypointVisibility.Occluded,
],
},
};
The corresponding boxStyle, polygonStyle, and keypointStyle independently
decide which layers render. Geometry remains reusable app/model data.