Ask AI

Documentation Assistant

Ask any question about the Video Annotation Tool. I have full context of the documentation and can help you find answers quickly.

Overview

Teams that train video models need large volumes of cleanly structured, precisely timed annotations. This tool is a browser-based video annotation component for the SuperAnnotate multimodal platform β€” configurable, AI-accelerated, and built for teams who need more than a basic timeline labeller.

Editor layout: top toolbar, video player at the centre, annotation panel on the right, and the frame panel timeline below the video.

Key Capabilities

  • Frame-based video annotation β€” synchronised video player with bounding boxes, cuboids, and keypoints / skeletons drawn over the frame, plus time-interval segments. The Frame Panel drives frame-level annotation with visible ranges, keyframes, and per-instance editing. Live brightness / contrast / saturation / shape-opacity adjustments. Video β†’
  • Five annotation tool types β€” Segment (time interval), Box (axis-aligned rectangle on the video frame, keyframed), Rotated Box (oriented rectangle drawn with a three-click workflow, keyframed), Cuboid (image-space 3D cuboid on the video frame, keyframed), and Keypoint (single point or multi-point skeleton on the video frame, keyframed). Classes & Tools β†’
  • Keyframes & interpolation β€” Box, Rotated Box, Cuboid, and Keypoint geometry is keyframed over time and linearly interpolated between keyframes (rotation interpolates along the shortest angle), so a few poses describe smooth motion across a clip. Interpolation β†’
  • Per-class properties β€” Free Text, AI Text, AI Select, Select (single / multi), Numeric, Rating, and Approval properties on every class. Per-role visibility and option-visibility rules. Properties β†’
  • AI autofill β€” for each AI Text or AI Select property, the model fills the value from the per-property prompt (for AI Select, choosing from the predefined option list). AI Autofill β†’
  • Multi-video items β€” a single item can hold up to 10 video files, each with its own annotations and tags. Navigate via tabs, or open Split View to play and compare every file in parallel as live, interactive cards. Multi-File Items β†’
  • Tags & relationships β€” item-scoped or video-scoped tags for classification; admin-curated relationships for linking annotations into graphs. Tags β†’ Β· Relationships β†’
  • Comments & isolation β€” scoped comments on every annotation; per-user isolation with role-based bypass for QA. Comments β†’ Β· Annotation Isolation β†’
  • JSONL ingest / ZIP export β€” load video (uploaded, public, presigned, or integration-signed URLs) at the platform level; export annotations + name-id maps as a ZIP. Import β†’ Β· Export β†’
  • Continuous auto-save β€” local state debounces every ~1 s; the platform receives a server save every 60 s. Auto-Save β†’

How It Works

The tool has two runtime modes, keeping setup separate from working:

  1. Configuration mode β€” An admin defines classes (with tool type), tags, properties, feature toggles, the AI proxy, and per-role instructions. This schema determines what every annotator sees and can do.
  2. Working mode β€” Users open items, draw segments / boxes / cuboids / keypoints, fill properties, and review. Everything auto-saves.

Typical flow: admin configures the project β†’ items arrive (uploaded video or URL-linked video via JSONL) β†’ annotators work β†’ export annotations for model training.

First Annotation

  1. Open an item in the editor and let the video load.
  2. Pick a class from the dropdown (or press 1–9 for the first nine classes). The matching tool (Segment, Box, Rotated Box, Cuboid, or Keypoint) auto-selects.
  3. For Segment, use + Segment on the frame panel to add a time interval. For Box, drag a rectangle on the video. For Rotated Box, use the three-click workflow on the video. For Cuboid, use the four-click workflow on the video. For Keypoint, click to place the point (or each skeleton joint in turn).
  4. The annotation appears in the annotation panel on the right.
  5. Fill any properties the class defines, or run AI autofill on configured AI Text and AI Select properties.
  6. Move on. Everything auto-saves as you go.

Configuration

Configuration defines the labeling schema and the experience each role gets β€” what users can see, do, and capture. A well-designed configuration is the single most impactful step before annotation begins.

Access Control

Access Control is a set of per-feature allow-lists. Each control gates a separate capability:

  • Upload Files (Roles) β€” which roles can use the in-editor upload button to add new video files.
  • Download Annotations (Roles) β€” which roles see the Download button.
  • Annotation Isolation β€” Off or By User. When set to By User, each user only sees their own annotations. Bypass Isolation (Roles) and Bypass Isolation (Statuses) independently let reviewers see everyone's work. See Annotation Isolation.

Role and status pickers share the same behaviour: Select all stores All Roles or All Statuses, including roles or statuses added later; a partial selection stores only the checked IDs; No Roles or No Statuses grants no bypass. Upload and download default to admin-only. Isolation bypass defaults to no roles and no statuses when isolation is enabled.

Access Control card showing Upload Files (Roles), Download Annotations (Roles), Annotation Isolation mode, and role/status isolation bypasses.

Feature Control

Feature Control toggles editor capabilities. Turning a feature off hides every affordance for it across the editor.

  • Object Comments (Off / On) β€” enables comments on annotations. When on, two sub-controls appear: which roles can resolve and which can delete comments.
  • Instance Relationships (Off / On) β€” enables relationships between annotations. When on, a Relationship Types editor appears so admins can curate the relationship taxonomy. Relationship type names must be unique (case-insensitive); duplicate or empty names are silently reverted on blur.
  • Annotation Panel β€” controls which views of the annotation panel are available: Instance + Table, Instance only, Table only, or None. The adjacent Configure Annotation Panel button becomes active whenever the panel is enabled (any mode other than None); the Table Column Settings button further activates when the table view is specifically reachable (Instance + Table or Table only).
  • Default Split View (Off / Split View 2 / 3) β€” for items with more than one video, opens the editor directly in catalog split view instead of the single viewport. If the item has fewer videos than the configured column count, the largest fitting split is used. Single-video items always open normally. Best suited to comparison workflows where every item has the same small video count.
  • Fullscreen on First Interaction (Off / On) β€” the first pointer interaction inside the editor requests fullscreen (browsers cannot enter fullscreen without a user gesture). Applies once per editor mount; annotators can exit with Esc or the toolbar button and are not forced again until the next item load. A brief informational notice confirms when fullscreen was triggered by this setting.
  • Video Player β€” the player mode dropdown. The tool is video-only and ships with a single Frame Mode option, which shows the video with the frame-based Frame Panel timeline below it. (A timeline / time-based mode is planned as a future addition; the dropdown is kept so it can slot in alongside Frame Mode.)
Feature Control card with toggles for Object Comments, Instance Relationships, Annotation Panel selector, Configure Annotation Panel button, Table Column Settings button, and the Video Player (Frame Mode) dropdown.

Annotation Panel Settings

Click Configure Annotation Panel… to set the project-wide defaults that apply when an editor is first opened. Each control commits live β€” Done simply closes the modal and Restore to Default clears every setting in this modal back to the built-in baseline. Editors can still resize, regroup, or reorder per-session from the panel header; this modal only controls what they start with.

  • Default panel width. Optional percentage (between 20% and 75% of the editor's container width) used as the starting width of the annotation panel. Out-of-range values snap to the closest valid percentage; leave the field blank to fall back to the built-in default of 480 px. Once an annotator drags the resize handle in the editor, their per-session width takes over until they reload.
  • Default Group By. Initial grouping mode for the panel (Video Name, Class Name, Tool Type, or any project property). Property options are gathered from every regular and tag class. If the chosen property has 100 or more distinct values across the open item, the editor falls back to Video Name grouping for that session β€” the configured selection re-engages automatically once the dataset shrinks below 100.
  • Default Order By. Initial ordering of instances (JSON Export, Class Name, Tool Type, Start Time, Created By, Creator Role, Created At, or any project property). Drag-to-reorder in the panel only writes to the JSON-export order, so it is only available when Group By is set to Video Name and Order By is set to JSON Export β€” either as project default or at the per-session level.

Reset chevron in the editor. Each Group By / Order By dropdown in the editor has a small reset arrow next to its title to revert to config-selected defaults.

Table Column Settings

Click Configure columns & groups… to open a two-panel modal that controls the Table View columns for the whole project.

Left panel β€” Columns. Lists every column currently available (excluding role-hidden ones). Drag rows to reorder; uncheck Show to hide a column by default. Click the pin icon to keep a column glued to the leading edge while editors scroll the table horizontally. Changes are saved immediately β€” Done simply closes the modal. Restore to Default clears all column and group overrides.

Pinned columns. A pinned column sticks to the leading edge of the Table View when editors scroll horizontally; pinned columns always render before unpinned ones in both the editor's Columns dropdown and the table itself, preserving their relative order within each cluster. Drag-reordering inside the modal is also restricted to within a cluster β€” drop a row across the pinned/unpinned boundary and it snaps back. Pinning is independent of Show: a pinned-but-hidden column is dormant (its pin icon dims at 55% opacity) and reactivates the next time the column is shown. Pinning two or more columns can leave little room for unpinned columns on narrow annotation panels β€” a heads-up note appears when this happens.

Right panel β€” Column Groups. Groups let you bundle related columns so editors can show or hide them all at once with a single toggle chip in the Table View. Click + Add Group to create a group, give it a short label, and pick columns from the dropdown. Group labels must be unique (case-insensitive); duplicate or empty labels are silently reverted. Each column can belong to at most one group. Columns assigned to a group have their individual Show checkbox controlled by the group's visibility toggle. Empty groups (no columns selected) are automatically removed when the modal closes.

  • Per-session user adjustments. Annotators keep their existing per-session control via the Columns dropdown and the column group chips β€” their adjustments don't persist across reloads; the project default does.
  • New columns appear at the end, visible. Adding a new property or relationship type after configuring defaults appends it visible. Reopen the modal to reposition or hide it.
  • Stale entries keep their position. Removing a column source (e.g. toggling Comments off) doesn't drop its stored position β€” it returns to the same spot if re-enabled later.

Classes & Tags

Classes and tags together form the structured vocabulary of your project. Classes describe what individual annotations are; tags describe what the video file or whole item is about.

Classes

A class is what a user assigns to a new annotation. Each class has:

  • Name β€” the label shown in the class picker and the annotation panel.
  • Color β€” the highlight / fill colour used for that class's segments, boxes, cuboids, and keypoints.
  • Tool Type β€” one of Segment, Box, Rotated Box, Cuboid, or Keypoint. Picking a class auto-selects the matching tool in the editor toolbar. Keypoint classes also expose an Edit Skeleton button for defining a multi-point skeleton.
  • Properties β€” the structured fields captured on each annotation of this class (see Properties below).

The five tool types and what they produce:

TypeWhere it drawsCaptures
SegmentThe frame panel timeline. Use + Segment to add an interval, then trim its start / end.A time interval in seconds.
BoxThe video frame. Drag a rectangle; add keyframes at multiple times to track movement.A rectangle (x, y, w, h) plus a start/end interval, with keyframes and interpolation.
Rotated BoxThe video frame. Three-click placement (set the top edge, then the height) for an oriented rectangle. Edit with eight resize handles plus a rotation handle.An oriented rectangle stored as centre (cx, cy), size (width, height) and a rotation angle (radians) plus a start/end interval, with keyframes and interpolation.
CuboidThe video frame. Four-click placement for an image-space 3D cuboid shape.Eight corner points plus a start/end interval, with keyframes and interpolation.
KeypointThe video frame. Click to place a single point, or place each skeleton joint in turn.One point, or a set of named skeleton points (each optional), plus a start/end interval, with per-point keyframes and interpolation.

Class names must be unique (case-insensitive); duplicate or empty names are silently reverted on blur. The first nine classes (in the order they appear in the configuration list) become number-key shortcuts (1–9) in the editor β€” arrange your most-used classes first.

Classes also accept per-role visibility:

  • Hide From Roles β€” listed roles see no annotations or controls for this class.
  • View Only Roles β€” listed roles see existing annotations of this class but cannot create new ones; the class shows a small lock icon in the dropdown.
Class list with each class showing its colour swatch, name, tool-type badge (Segment / Box / Rotated Box / Cuboid / Keypoint), property count, and per-class hide / view-only role controls.

Keypoint Skeletons

A Keypoint class can be either a single point or a skeleton of several named, connected points. When a class's tool type is set to Keypoint, an Edit Skeleton button appears in its Properties modal; open it to define the skeleton.

  • Points. Add named points (e.g. head, left shoulder, right knee). A class with no points defined behaves as a single-point keypoint; a class with two or more points behaves as a skeleton.
  • Connections. Link points into edges (bones) by selecting a pair of points. Connections are drawn as lines between the points in the editor and carry an optional per-edge colour.
  • Layout preview. The modal shows the points and their connections so you can lay out and sanity-check the skeleton before annotators use it.

The skeleton definition is part of the class. In the editor, drawing a skeleton keypoint walks the annotator through its points in order, each point can be skipped, and the connections render automatically. See Keypoint & Skeleton in the editor section.

Edit Skeleton modal: list of named points on the left, a connection editor for linking point pairs, and a live preview of the skeleton with its edges.

Tags

Tags capture structured attributes that describe something broader than a single annotation. There are two scopes per tag class:

  • Item-level tags β€” apply to the whole item regardless of how many video files it contains. Think topic, dataset partition, or any coarse attribute about the entire item. Shown at the top of the annotation panel independently of the active file.
  • Video-level tags β€” apply to a specific video file within the item. In multi-file items, each file can have its own video-level tags (e.g. per-file quality, domain, scene type). Shown under Video tags sub-headers in the annotation panel.

Tag scope is configured per tag class in the admin settings. Tags are ideal for:

  • Routing items through triage (e.g. "Indoor", "Needs-Review", "Low-light").
  • Capturing ground-truth for whole-clip classification training.
  • Filtering and grouping in dashboards downstream.
  • Per-file quality or metadata signals (video-level scope).

Tag names must be unique (case-insensitive); duplicate or empty names are silently reverted on blur.

Tag list with item-scoped and video-scoped tag classes, each with name, color chip, scope label, and per-tag-class properties.

Properties

Raw segments and boxes only tell a model where something is. Properties attach structured metadata β€” text, options, numbers, AI-generated content β€” to each annotation, turning bare regions into rich training samples. Property names must be unique within their class or tag (case-insensitive); duplicate or empty names are silently reverted on blur. There are seven property types:

TypeWhat it capturesExample
Free TextOpen-ended string input.Object name, notes, IDs, manual corrections.
AI TextText auto-filled by the configured AI proxy (or an optional per-property override), guided by a per-property default prompt. See AI Autofill. Not available on tag classes (item or video scope).Summary, key attributes, normalised label.
SelectPredefined option list. Toggle Allow multi-select to switch between dropdown (single) and checkbox (multi) behaviour.Object category, scene type, quality bucket, multi-label tagging.
AI SelectSelect field whose options are auto-chosen by the configured AI proxy (or an optional per-property override), guided by a per-property default prompt. Combines a predefined option list with AI-driven pre-selection. See AI Autofill. Not available on tag classes (item or video scope).Auto-classification, object category, scene type, multi-label tagging.
NumericNumber input with optional min, max, step, and unit.Confidence score, count, distance, size.
RatingStar picker backed by a numeric string value. Admins choose the maximum star count (3–10, default 5); 1 is the lowest selectable rating and empty / absent means unset. No AI hookup. Can be marked time-based like any other property β€” ratings then live in propertyKeyframes.Frame quality, subjective severity, event usefulness, confidence stars.
ApprovalThree-state verdict captured via a compact thumbs-up / thumbs-down picker. Stores "true" when approved, "false" when disapproved, and is omitted (or blank) when no verdict has been given. Carries no options, no AI configuration, no numeric or text-display options. Can be marked time-based like any other property β€” verdicts then live in propertyKeyframes instead of propertyValues.Reviewer sign-off on an instance / tag, accept-reject for a detected event, QA verdict for a specific frame range.

Common property options:

  • Required β€” flags the annotation as incomplete until filled.
  • Time-based β€” turns the property into a timeline of values that can change across the video instead of a single constant value (e.g. an Action that switches from "Walking" to "Running"). Mutually exclusive with property visibility rules. See Time-Based Properties.
  • Text Display (Free Text and AI Text) β€” a three-way toggle that sets how the field is presented; the three modes are mutually exclusive:
    • Inline (default) β€” a compact resizable textarea shown directly in the popover / table cell. Best for short values.
    • Modal β€” opens a roomy plain-text modal that stores the value exactly as typed (no formatting, no conversion). Best for long or structured plain text β€” e.g. raw HTML, JSON, or multi-line snippets you need preserved verbatim.
    • Rich Text β€” opens a rich-text modal with inline formatting, useful for longer values like detailed descriptions or multi-paragraph captions.
  • Enable Editing (AI Text and AI Select) β€” controls whether the AI output is editable at extraction time. For AI Text, when off, the model auto-extracts using the predefined prompt as-is; when on, annotators can tweak the prompt before triggering extraction. For AI Select, when off, the model's chosen option is applied directly; when on, annotators can review and override the AI's selection.
  • AI Text / AI Select: Default Prompt β€” the system prompt the model receives when extraction runs. Annotators with prompt editing enabled can also override it per-run from the Edit prompt flow.
  • AI Text / AI Select: Proxy / Model override β€” optional per-property routing. By default each AI property inherits the project-wide AI Property Proxy and model. In the property card, use the Proxy/Model override row to send this property only through a different proxy and/or model tier. Overrides are included when you copy a property to other classes. See Per-property proxy & model routing.
  • Default value (Select only) β€” a starting option auto-populated on each new annotation.
  • Hide From Roles / View-Only Roles β€” restrict who sees and edits this property.
  • Info β€” optional helper text shown next to the field for annotator guidance.
Properties modal for a Vehicle class showing an AI Text property "Summary", a Single Select "Type", and a Numeric "Confidence", each with the per-property options panel expanded.

Per-property proxy & model routing

Every AI Text and AI Select property can optionally override the project defaults set under AI Proxy. In the property modal, below the Default System Prompt, the Proxy/Model override row exposes two dropdowns:

  • Proxy β€” starts at Default (project AI proxy / model). Pick any team proxy whose domain routes to OpenAI or Gemini to override the project selection for this property only.
  • Model β€” enabled once a non-default proxy is chosen. Lists the same three tiers as the project-level model picker for that provider (cheapest β†’ most capable). Changing the override proxy resets the model to that provider's default middle tier.

At extraction time the editor routes each property through its resolved proxy + model. Properties sharing the same route are batched into one API call; properties with different overrides (or a mix of overrides and project defaults) run as separate batches in sequence. A property with an override can still extract when the project default is unset β€” but any property without an override still requires the project AI Property Proxy to be configured. The Ask AI documentation assistant always uses the project proxy/model; it does not read per-property overrides.

Property Visibility Rules

A property visibility rule controls whether an entire property is visible and editable on a given annotation or tag, based on the value of one or more sibling Select / AI Select properties. Use this when a whole field only makes sense in a specific context β€” e.g. only show "Occlusion Type" when "Is Occluded" is "Yes", or only show "Vehicle Make" when "Object Category" is "Vehicle". This is the property-scope equivalent of option visibility rules: option rules hide individual options inside a Select; property rules hide the whole property.

Property visibility rules can be set on any property type (not just Select / AI Select). A Free Text, Numeric, Rating, AI Text, AI Select, Select, or Approval property can all be gated by a rule. The controller must still be a sibling Select-like property in the same class or tag class. Time-based properties are the one exception β€” see Time-Based Properties below; time-based ⇄ visibility rule is mutually exclusive.

Setting Up a Rule

  1. Open the property modal for a class or tag class.
  2. In the property card's right-hand header, click the chain icon next to the copy / delete buttons. The icon is only enabled when the class has at least one sibling Select-like property to use as a controller.
  3. An inline rule editor expands below the property card β€” same shape as the option-rule editor: choose All conditions match (AND) or Any condition matches (OR), then add one or more conditions picking a controller property and which value(s) it must hold.
  4. Click the chain icon again (or the editor's Γ— / Remove rule button) to collapse / clear the rule.

The chain icon switches to a bolder blue tint when a rule is active, so you can spot rule-bearing properties at a glance in the property list. Hovering the icon shows a tooltip naming the controlling property and required value(s).

Behavior in the Editor

  • Greyed-out field β€” when the rule is unsatisfied, the property still appears in the popover and table column (so annotators can see the field exists), but it's rendered dimmed with a not-allowed cursor. Hovering anywhere over the disabled field shows a tooltip explaining what controls it (e.g. "Controlled by: Object Category = Vehicle").
  • Stored value cleared β€” the moment a rule becomes unsatisfied (e.g. the user changes a controller value), any value stored on that property is automatically cleared. The clear cascades: if A controls B, and B itself controls C, changing A clears both B and C in one step.
  • Required validation suppressed β€” an inaccessible property is not counted as "missing required" even when marked Required. The red required indicator on the annotation / tag row only reactivates when the rule becomes satisfied and the field becomes editable again.
  • AI extraction skipped β€” for AI Text / AI Select properties, the row-level Extract / Edit prompt controls, the per-property icons in the property popover, and the per-cell extract icons in the table skip any AI property whose rule is unsatisfied. The buttons appear / disappear immediately as the controller value changes, no popover reopen needed.
  • Modal / Rich Text properties β€” a property gated by an unsatisfied rule renders as a plain "β€”" placeholder; its modal (plain-text or rich-text) cannot be opened.
  • Default values disabled β€” when a Select property has a property visibility rule, the per-option "Default" checkboxes in the configuration screen are disabled. Defaults wouldn't make sense for a property that may not even be visible on instance creation; the configuration UI prevents the contradiction up-front.

For details on how property visibility rules interact with option visibility rules on the same property, see Property & Option Visibility Rules in the editor section.

Time-Based Properties

By default a property holds one constant value for the whole instance β€” the box marking a car is always "Red". A time-based property instead records a timeline of values that change across the video, so the same instance can carry state that evolves: an Action property might be "Idle", then "Driving" from one frame on, then "Parked" later. Conceptually this mirrors geometry keyframes, except the value is held constant between keyframes rather than interpolated β€” each property keyframe sets a new value that carries forward until the next one (or the end of the instance).

Enable it with the Time-based checkbox (marked with a small clock icon) in the property card, alongside Required and the Text Display toggle. It is available for every property type β€” Free Text, AI Text, Select, AI Select, Numeric, Rating, and Approval β€” since AI fields can also be filled manually.

Property modal with the "Time-based" checkbox (clock icon) enabled on an "Action" Single Select property.

A few rules keep the feature predictable:

  • Mutually exclusive with property visibility rules. A property can be time-based or gated by a visibility rule, not both β€” toggling one disables the other in the modal.
  • Never a rule controller or dependent. Time-based Select properties don't appear in the controller pickers for option or property visibility rules, and the per-option chain icon is disabled on them. Their value isn't a single constant, so it can't drive a rule.
  • Not on tag classes. Item- and video-scoped tags have no timeline, so the flag is stripped when a time-based property is copied to a tag class (it becomes a plain constant property there, and the copy picker flags the drop).
  • Group / Order. Time-based properties are excluded from group-by / order-by in the panel (the value isn't constant). Where a same-named property exists as constant on one class and time-based on another, the group/order list labels the time-based variant with a "(time-based)" suffix so the two are distinguishable.

For how annotators set and read these values in the editor, see Time-Based Property Editing.

Copying properties between classes

Most projects end up with the same property defined on several classes β€” a Confidence Numeric on a handful, a Quality Single Select on every class. Recreating each one by hand is tedious and error-prone. Every property row in the Properties modal has a small copy icon next to the remove (Γ—) button that opens a picker for replicating that property across other classes and tags in one step.

Property row with the copy icon highlighted next to the remove button.

The picker lists every class and tag in the project. Each row carries a state badge that tells you what will happen if you select it:

Row stateMeaningWhat you can do
Will addThe target has no property by this name. Safe paste.Tick the row to include it.
Already identical β€” will skipThe target already has a property with the same name and the same shape (type, options, prompt, numeric range, etc.). Pasting would be a no-op.Locked off β€” nothing to do.
Conflict: name exists with different shapeThe target has a property with the same name but a different definition (e.g. it's a Free Text on one class and a Select on another).Tick the row, then choose Overwrite property to replace the target's definition with the source's, or Add as duplicate to add a second property with a " (2)" suffix on its name.
Source β€” excludedThis is the class you're copying from.Always excluded; you can't copy a property onto itself.

The footer shows a running summary ("3 to add Β· 1 to overwrite Β· 2 already identical") and the Copy button only enables once at least one row is in the to-add / to-overwrite / to-duplicate set.

A few details worth knowing:

  • Copies are independent. Each paste mints a fresh property ID β€” there's no hidden link back to the source. Editing the original later does not propagate to the copies, and vice versa. Think of this as a faster "create the same property again" rather than a shared definition. The editor's table view and panel still aggregate properties across classes by name, so a Confidence column will show every class's annotation regardless of which class the property was originally created on.
  • Visibility rules are remapped where possible. If the source property carries any option visibility rules or a property visibility rule, the copy tool tries to remap each rule's controller references against the target class's properties: it looks for a sibling property with the same name (case-insensitive) and whose option list contains every value the rule references. When all of a rule's conditions can be remapped this way, the rule carries through fully into the target. When even one condition cannot be remapped (controller absent, or its option list is missing required values), the entire rule is dropped on that target β€” partial remapping is refused because keeping a "best-effort" subset of an "all conditions match" rule would silently weaken it.
  • Quiet on success β€” warns on drops. The copy modal stays silent when every rule carries through cleanly and only surfaces a per-target warning when one or more rules will actually be dropped, so you can spot the targets where shape divergence matters before confirming.
  • Role visibility β€” the Copy role visibility (Hide From / View Only) checkbox at the top of the modal controls whether the source property's role rules travel with the copy. Turn it off when target classes have their own role-restriction conventions you don't want to overwrite. On the Overwrite property path, the target's existing role visibility is preserved when this option is off.
  • AI Text / AI Select on tag classes β€” AI Text and AI Select properties are not supported on tag classes (item or video scope). When copying an AI Text property into a tag class, it is automatically downgraded to Free Text; when copying an AI Select property, it is downgraded to plain Select. In both cases the default prompt and "Enable Editing" setting are dropped, and the picker row flags this with a small note.
  • Time-based on tag classes β€” a time-based property copied into a tag class loses its time-based flag and is pasted as a constant property, since tags have no timeline. The picker row notes this on its own line alongside any other downgrade warnings (e.g. an AI downgrade).
  • Overwrite is destructive on the target's definition. Annotators' stored values for the property remain wired to the same row (the property's ID is preserved), but the type, options, and other settings switch to the source's. If a stored value no longer matches the new shape (e.g. an option that was removed from a Single Select), the destructive-warnings banner in the Properties modal will flag it at publish time.

Option Visibility Rules

When a class or tag has multiple Select properties, you can create dependencies between them. An option visibility rule makes one property's options conditionally visible based on what is selected in another property of the same class/tag. This lets you build hierarchical relationships β€” for example only showing relevant subcategory options when a particular category is selected.

Option visibility rules apply to Select and AI Select properties alike. An AI Select property can be a controller or a dependent in a rule chain β€” the AI pre-selection respects the same filtering, and cascade clearing applies to AI-chosen values exactly as it does to manual ones.

When to Use

  • Category β†’ Subcategory β€” An "Object Category" property has 5 options (Person, Vehicle, Animal, Sign, Other); a "Subcategory" property has 20 options. Instead of showing all 20 regardless, you configure each subcategory option to only appear when its parent category is selected.
  • Conditional attributes β€” A "Vehicle Type" dropdown controls which "Body Style" options are relevant.
  • Multi-level filtering β€” Rules can reference multiple controller properties and combine with AND/OR logic for complex taxonomies.

Key Concepts

TermMeaning
Controller propertyThe Select property whose value determines what options appear on the dependent property. Must be a sibling (in the same class or tag class).
Dependent propertyThe Select property whose options are conditionally shown/hidden based on the controller's value.
Visibility ruleA per-option configuration that says "only show this option when condition X is met on the controller".
Unconditional optionAn option with no visibility rule β€” always shown regardless of what the controller says. This is the default.

Setting Up a Rule (Configuration Screen)

  1. Open the property modal for a class or tag class.
  2. On any Select property that has at least one sibling Select property, each option row shows a chain icon (β›“).
  3. Click the chain icon on the option you want to make conditional. The inline Visibility Rule Editor expands below that option.
  4. Click + Add condition. Choose the controller property from the dropdown, then select which of the controller's option values must be active for this option to be visible.
  5. For multi-condition rules, choose All (AND) or Any (OR) at the top to control how conditions combine.
  6. When done, click the collapse arrow or click the chain icon again to close the editor.
The inline visibility rule editor showing a condition: Object Category has Vehicle.

Rule Logic

  • Single-select controller β€” The condition passes if the controller's stored value is any one of the listed values (implicit OR across the selected values in the rule picker).
  • Multi-select controller β€” You choose any (at least one of the listed values is selected) or all (every listed value must be selected).
  • Multiple conditions β€” Combined with a top-level All (every condition must pass) or Any (at least one must pass).
  • Empty controller β€” An empty/blank controller value always counts as "unsatisfied" β€” the dependent option stays hidden.

Behavior in the Editor

Once rules are published, annotators see them enforced immediately in both the property popover and the table view:

  • Option filtering β€” The dependent property's dropdown only shows options whose rule is currently satisfied by the controller's value on that same row (annotation or tag).
  • Cascade clearing β€” If the annotator changes the controller value and a previously-selected dependent option is no longer valid, it is automatically cleared. This cascades: if A controls B and B controls C, changing A can clear both B and C in one step.
  • Controller indicator β€” Dependent properties show a small chain icon on their label with a tooltip listing which properties control their options (e.g. "Options here are filtered by: Object Category, Vehicle Type").
  • Config-triggered cleanup β€” If an admin changes rules after annotations already exist, the next time an annotator opens an item, any stored values that violate the new rules are cleaned in memory. The cleanup persists on the annotator's next save.
Editor property popover showing filtered subcategory options based on the selected object category.

Interaction with Default Values

Default values and visibility rules are mutually exclusive on the same option. An option marked as Default cannot have a visibility rule, and vice versa. The configuration UI enforces this:

  • If "Default" is checked on an option, the chain icon is disabled (tooltip explains why).
  • If a visibility rule exists on an option, the Default checkbox is disabled.

This prevents the scenario where a default value would be immediately cascade-cleared on instance creation because its rule isn't satisfied.

Cross-Property Copy

When copying a property that has visibility rules to another class, the copy tool attempts to remap each rule's controller references against the target class's properties. For a rule to carry through, every controller referenced by its conditions must exist in the target by name (case-insensitive) and the target controller's option list must contain every value the rule references. If even one condition can't be remapped, the entire rule is dropped on that target β€” partial remapping is refused because silently dropping conditions from an "all conditions match" rule would weaken its logic (e.g. A AND B collapsing to just A).

The copy modal stays quiet when every rule carries through cleanly, and surfaces a per-target warning only on targets where one or more rules will be dropped. The same name + shape check applies whether the rule is a per-option rule on this property or a property-level visibility rule. See Copying properties between classes for the full copy flow.

Broken References

If a controller property is deleted or its type is changed away from Select while a dependent still references it, the condition is shown with a red border and alert icon in the configuration screen. The broken condition is preserved during the config session so admins can see what happened. On publish, broken conditions are automatically stripped.

AI Proxy

Note: AI property extraction is being rebuilt to work from the video frame. The proxy setup below (creating and selecting a proxy) is unchanged, but how AI Text / AI Select draw their input will be revised when that feature lands.

The AI features in this tool β€” AI Text and AI Select autofill and the documentation Ask AI assistant β€” communicate with external providers (OpenAI or Gemini) through a single SuperAnnotate Proxy. Proxies act as secure intermediaries: your team's API keys live in SuperAnnotate, never in the browser.

Why proxies?

  • Security β€” API keys stay server-side. Annotators never see or handle raw keys.
  • Central management β€” Team admins create and rotate proxies in one place; all projects inherit the change.
  • Audit & control β€” Proxy usage is logged per team, making cost tracking and rate limiting easy.

Provider & model

The provider is auto-detected from the proxy's allowed domain:

ProviderDetected viaChat model
OpenAIapi.openai.comAdmin-selected (see below)
Geminigenerativelanguage.googleapis.comAdmin-selected (see below)

Step 1 β€” Create a proxy in SuperAnnotate

  1. Open SuperAnnotate β†’ Team Settings β†’ Security β†’ Proxies.
  2. Click Create Proxy. Give it a descriptive name (e.g. "OpenAI Proxy").
  3. Set Allowed domain to either https://api.openai.com or https://generativelanguage.googleapis.com β€” this is what determines the provider in this tool.
  4. Under Secrets, add a header:
    ProviderHeader keyHeader value
    OpenAIauthorizationBearer sk-proj-…
    Geminix-goog-api-keyAIza…
  5. Save the proxy and note its name β€” you'll select it in the next step.
Team Settings β†’ Security β†’ Proxies page with example proxies Proxy setup with the authorization header configured for OpenAI

Step 2 β€” Select the proxy in configuration

In the configuration screen's AI Proxy Settings card, open the Select Proxy dropdown and pick the proxy you created. The dropdown is populated from your team's available proxies. A provider badge (OpenAI / Gemini) appears once a proxy is selected.

Once a proxy is selected, a Model dropdown appears next to it. Three models are offered for each provider, sorted from cheapest/fastest to most capable β€” the middle option is selected by default. The currently available models are:

ProviderModels (cheapest β†’ most capable)
OpenAIgpt-5.4-nano, gpt-5.4-mini, gpt-5.5
Geminigemini-3.1-flash-lite, gemini-3.5-flash, gemini-3.1-pro-preview

The selected model is used for property extraction chat calls and the Ask AI assistant. Changing the proxy to a different provider resets the model to that provider's default (middle tier). Annotators in the editor are not affected and do not see which model is active, except when a property has its own proxy/model override.

Bulk annotation panel extraction toggle

Below the AI Property Proxy card, the checkbox Allow Bulk Extraction of all AI Properties controls whether annotators see the panel-header bulk extract control in the editor (see Bulk annotation panel extraction). It is off by default β€” enable it when you want annotators to run AI extraction across every visible row in the annotation panel in one action. The toggle does not change single-property, row-level, or table-cell extract controls; it only exposes the all-rows shortcut. Works in both Instance View and Table View. Requires an AI Property Proxy to be configured (or at least one AI property with a per-property override and runnable empty values).

AI Proxy Settings card with a Select Proxy dropdown, Model dropdown, and a provider badge.

Troubleshooting

  • "No team available" β€” the component could not detect your team. Make sure it's loaded inside the SuperAnnotate platform.
  • "Failed to load proxies" β€” network error fetching the proxy list. Refresh and retry.
  • "No AI proxy configured" at runtime β€” return to configuration and pick a proxy.
  • "Data is too large for Gemini" β€” Gemini's inline-data path has a ~12 MB ceiling per request. Reduce the payload or switch to an OpenAI proxy.
  • Errors from the model itself β€” verify the API key on your provider's side (OpenAI or Gemini dashboard) β€” valid, not revoked, with remaining quota / billing in good standing.

See API Rate Limits for guidance when running autofill across large datasets.

Advanced Settings

Advanced Settings contains project-wide behaviour choices, primarily for video-heavy workflows:

  • Video Loading β€” sets how each video starts. Download First (default) downloads the whole file (with a progress bar) before playback, giving the most reliable seeking and frame stepping; Stream First starts playback sooner by streaming from the source. Each file adapts to its host: a Download First file whose host blocks cross-origin downloads (CORS) falls back to streaming, and a Stream First file whose host doesn't support range requests falls back to a full download (needed for reliable seeking). On any fallback, a toast appears β€” stacking for multiple files, shown regardless of the active file or view β€” and a persistent yellow warning icon marks the file: left of the card title in Split View, left of the mute button in single view, with a hover tooltip explaining why. Cross-origin (CORS-blocked) videos still play and annotate normally; only frame extraction may be limited. Applies to both timeline and frame panel modes.
  • Split frame seek fallback FPS β€” used only when a video has no imported frame metadata and no per-video FPS value; exact frame timestamps and per-video FPS metadata take priority.
  • FPS Control β€” controls whether annotators can edit the FPS field in the Frame Panel. When off, the field is still visible but disabled: it shows the stored per-video FPS when present, otherwise the project fallback FPS.

Project Instructions

Project Instructions are PDF guidance documents attached per role. Each role can have its own PDF, so annotators and QAs see the instructions relevant to their job. Admins can see and manage all instruction files.

  • Upload one PDF per role β€” annotation conventions, edge cases, video-frame guidance, etc.
  • Change any time β€” users pick up the new file on next load.
  • The PDF is opened from the editor toolbar's Instructions button (when configured for the user's role).
Project Instructions section with a per-role file picker and a list of uploaded PDF instruction files

Item Context

Item Context adds an optional strip of rich-text slots above the editor canvas. Use it for per-item system prompts, task-specific notes, or short instructions that arrive with the item or are written by annotators in the editor. Slot content supports the same rich text formatting as rich-text properties (bold, italic, headings, lists, blockquotes, code, links, and tables). Off by default; toggle it on from the Item Context card and click Configure slots… to manage the slot list.

  • 1–10 slots per project β€” each one becomes a tab in the editor's Item Context section. Add slots with the + Add slot button; drag the handle to reorder; click the Γ— to delete.
  • Stable internal id β€” every slot gets an opaque id (e.g. ctx-abc123) at creation. Renaming or reordering a slot in config never moves stored item data; values stay attached to the same id forever. The id is also exposed in name2id.json so JSONL authors can address slots by name on upload.
  • Unique slot names β€” names must be unique per project (case-insensitive), same rule as classes and tags.
  • Per-role visibility β€” each slot has independent Hide From and View Only role pickers (same widget as class and tag visibility). Defaults for new slots are Hide From: No Roles and View Only: All Roles β€” i.e. visible read-only to everyone until admin opts a role into editing. If a role is on both lists, Hide From wins.
  • Default section height β€” admin sets the initial height of the strip in the editor (100–500 px, default 200 px). Annotators can drag-resize it for their session, but resized values are not persisted β€” every reload starts at the admin default.
  • Disabling is non-destructive β€” toggling Item Context off keeps the configured slots and any per-item values on disk; turning it back on later restores everything as it was.
  • Deleting a slot leaves prior values on disk as orphans β€” they no longer appear in the editor but ride through subsequent saves and downloads. Adding a new slot later generates a fresh id; orphan values do not reattach automatically.
  • Minimum one slot when enabled β€” the last slot can't be deleted while the feature is on. Disable Item Context to clear the strip entirely.
Item Context configuration card showing the on/off toggle, Configure slots button, and the slot management modal with drag handles, name fields, role visibility pickers, and add/delete controls

Import / Export

The whole configuration β€” classes (with tool types), tags, properties, access control, feature toggles, AI proxy selection, relationships β€” can be exported as a single JSON file and re-imported into another project.

  • Export config β€” downloads a JSON file with the full schema. Version-control it alongside your project code for reproducibility.
  • Import config β€” reads a previously exported config JSON and replaces the current configuration. A confirmation prompt is shown first.
  • Use this to clone a proven configuration across projects, back up before a risky change, or share a template with another team.

The header also includes a Download name2id.json button that exports the name-to-ID mapping file directly from the config screen. This is the same name2id.json included in annotation ZIP downloads, but available here so admins can obtain it without creating items or entering the editor β€” useful when preparing JSONL imports or integrating with external pipelines.

Import / Export card with Export config and Import config buttons

Editor

The editor is where the actual work happens β€” uploading video, drawing segments, boxes, cuboids, and keypoints, filling properties, reviewing. The layout puts the video front-and-centre and surfaces the right controls for the task at hand.

Editor Layout

Three regions, each with a purpose:

  • Top toolbar β€” tool / class selectors, upload, download, instructions, split-view toggle, shortcuts, documentation, theme, video adjustments, fullscreen, undo / redo.
  • Center video area β€” the video player. Below it sits a row of playback controls and the Frame Panel timeline; above it, a tab strip on multi-file items.
  • Right annotation panel β€” the list of segments, boxes, cuboids, keypoints, and tags, with grouping, ordering, filtering, and quick access to properties, comments, and relationships. Can be collapsed.
Editor layout: top toolbar, video player at the centre, playback controls and the Frame Panel timeline underneath, annotation panel on the right.

Layout Conveniences

The top toolbar exposes three layout helpers:

  • Fullscreen (F) β€” maximises the tool area within its host page to reduce visual clutter.
  • Fit video to view (Shift+F) β€” when the video viewport is zoomed, reset it back to the fitted view.
  • Dark mode toggle β€” flips the UI to a dark palette. The same preference is applied to this documentation popup.

Video Sources

Video reaches the editor through one of two paths:

  • Uploaded β€” the user drops video files onto the upload zone or into the Upload modal. The bytes live in SuperAnnotate storage; the editor references them via a uniqueName.
  • URL-linked β€” the JSONL payload contains a url with a urlKind (public, presigned, or integration). The editor signs / fetches the URL on load. See URL-linked video.

Both kinds are equally annotatable. The difference is only where the bytes come from β€” the editor doesn't gate any feature on the source.

Video only. The tool accepts video files exclusively. If an item's linked source is not a valid video (e.g. an audio file or another media type), the editor refuses to load it and shows an informative banner instead of an empty canvas β€” the item needs a valid video source.

In-Editor Upload

When the user's role is on the Upload Files allow-list, the Upload button on the top toolbar opens the upload modal. The modal lets you drag or browse for files and shows an "X of 10 files used" indicator (the per-item cap is 10 video files).

Accepted video formats: MP4, WebM, OGG, MOV (QuickTime). Non-video files are rejected with a banner.

The empty drop zone shown when an item has no video yet supports drag-and-drop directly onto the canvas in addition to the modal. Uploads that exceed the 10-file cap are rejected with a banner. Uploading a video marks the item as having unsaved changes, so you are warned before leaving with un-persisted uploads.

Upload modal with a dropzone, supported video formats, an Add Files button, and a counter showing how many files are already in the item

Multi-File Items

A single item can contain up to 10 video files. Each file has its own annotations and video-scoped tags.

Tab Navigation

When an item has more than one video file, a tab strip appears above the player. Click any tab to switch the active file. The active file's video fills the player and its annotations populate the panel.

  • Adding files β€” use the Upload button or drop new files into the item.
  • Per-file state β€” annotations and video-scoped tags are stored per file. Item-scoped tags apply to the whole item regardless of which tab is active.

Panel & Annotations

The annotation panel aggregates annotations across all files in the item. Annotations from every file are shown regardless of which tab is active. Clicking an annotation from another file switches the active tab to that file and scrolls / seeks to it. The panel groups video-scoped tags under file sub-headers (Video tags), while item-level tags appear at the top independently.


Item Context

When Item Context is enabled in the project configuration, the editor renders a dedicated section at the very top of the canvas β€” above the multi-file tab strip and the player area β€” for the configured slots.

  • Tab strip β€” one tab per visible slot, in the order set in config. The active tab uses a neutral grey accent stripe so it's clearly distinguishable from the blue file-tab strip directly below.
  • Collapse / expand β€” a chevron button at the leading edge of the tab strip collapses the section down to just the tab row (hiding toolbar, content, and resize handle). The chevron is sticky-left and stays visible when the tab strip overflows and you scroll horizontally. When collapsed, clicking the chevron or the empty area of the strip expands the section; clicking a non-active tab expands and switches to that tab in a single action; clicking the active tab simply expands. Always starts expanded on load.
  • Rich text editing β€” editable slots show a formatting toolbar between the tabs and content area. Available formatting: bold, italic, headings (H1/H2), bullet lists, numbered lists, blockquotes, inline code, code blocks, hyperlinks, and tables. The toolbar sits within the section's height and does not consume additional space.
  • Read-only slots β€” slots set to View Only for the user's role render with a light grey background and no toolbar. Rich text content still renders fully formatted (headings, lists, tables, etc.) β€” only editing is disabled.
  • Hidden slots β€” slots with the user's role on the Hide From list are not shown in the strip at all. If every slot is hidden for the user, the entire Item Context section disappears.
  • Resize handle β€” drag the thin grey grip at the bottom of the section to resize it (clamped between roughly 80 px and 50 % of the editor height). The resized height is session-only; reloading the item resets to the admin's default height.
  • Autosave β€” edits feed the same debounced auto-save pipeline as the rest of the editor; the unsaved-changes indicator picks them up like any other change.
  • Source of values β€” slot content is either typed directly by the annotator or pre-populated when the item arrives via JSONL upload (see the payload schema).
Editor canvas showing the Item Context section at the top with a tab strip, an active tab with a grey accent stripe, and a textarea filled with task-specific notes

Split View

For items with multiple video files, the Split toggle in the top toolbar lays out every file side-by-side as a grid of live, fully playable cards. Split View is built for cross-file work β€” comparing, tagging, and reviewing several files in parallel β€” without leaving the editor.

  • Split 0 (default) β€” standard single-file editable view with tabs.
  • Split 1 / 2 / 3 β€” renders all of the item's files as a grid that wide. Each cell is an independent mini-player with its own video frame and controls.

The toggle only appears when the item has more than one video file. The single-pane tab strip, playback controls, and wide-view toggle are hidden while Split View is active β€” each card owns its own loading state and chrome, following the project's Video Loading mode. The editor reuses cached / resolved video state when moving between Split View and single view, so tabs and cards can continue loading in the background without losing their playhead or overlays when they become ready.

Card Anatomy

Every card in the grid contains:

  • Header β€” file name, plus a hover-revealed "Open" pill that disambiguates exit-split affordances from the in-card playback affordances.
  • Video frame β€” a live <video> element that plays inline. Box, cuboid, and keypoint annotation overlays render on top of the frame at the card's current time. Display only β€” no annotation editing in Split View.
  • Control strip at the bottom β€” mute toggle, play / pause button, current-time / duration readout, and an interactive seek bar. Click or drag on the seek bar to scrub the card's playback position.

All cards use a consistent row height so video frames stay legible across the grid.

Click Targets & Exit Behaviour

Card surfaces are split into two zones with different effects:

  • Card playback zone β€” the bottom control strip (play / pause, mute, time readout) and the seek bar. Clicks here drive playback for that card only and stay in Split View. The hover pill is suppressed here so the interactive area is unambiguous.
  • "Open in single view" zone β€” the header and video frame. Clicking here collapses to Split 0 and switches the active file to that card's file. The hover pill fades in to signal this behaviour.

When you exit by clicking a card: any other cards still playing are paused, and the file you opened resumes from wherever it was in Split View (auto-resumes if it was playing in the card).

Parallel Playback & Keyboard Focus

Multiple cards can play simultaneously β€” useful for A/B comparing similar takes or aligning content across files. Audio mixing is the user's responsibility (mute the cards you don't want to hear).

The global transport strip above the card grid provides controls that apply to every card at once: play / pause all, mute / unmute all, seek all by seconds, seek all by frame, and a shared playback speed.

Keyboard shortcuts in Split View follow one of two modes:

  • Focused mode (default) β€” shortcuts target whichever card you most recently interacted with directly (play, seek, mute, or selecting one of its annotations from the panel).
  • Broadcast mode β€” when you interact with the global transport strip (e.g. play all, mute all), shortcuts automatically shift to apply to every card at once. Clicking any individual card returns to focused mode.

Available shortcuts in both modes:

  • Space β€” play / pause.
  • Shift+Space β€” play / pause even while typing in property fields.
  • , / . β€” seek 3 s back / forward.
  • < / > β€” seek 10 s back / forward.
  • M β€” mute / unmute.

Tool shortcuts (S, G, B, D, K) and class shortcuts (1–9) are ignored in Split View β€” Split View is for playback and tagging only; annotation editing happens in Split 0.

Position Persistence

The current playback position of every file is preserved as you move between Split 0 and the higher split modes:

  • Play a file in Split 0 to 0:30, switch to Split 2, drag two other cards' minimaps to 0:10 and 0:45, then click into either of those β€” it opens at 0:45 (or 0:10) in single view.
  • Return to Split View afterwards: every card is mounted at its last-known position, including files you only adjusted by dragging the minimap (without ever pressing play).
  • Positions are session-only β€” closing the item or refreshing the page resets every file to 0.

Panel Interaction in Split View

Selecting an annotation, tag, or instance from the annotation panel while in Split View does not collapse the view. The corresponding file's card is scrolled into view, briefly highlighted, and becomes the keyboard-focused card so you can drive playback from the keyboard immediately.


Top Toolbar

Left to right, the top toolbar exposes:

  • Tool selector β€” Select / Segment / Box / Rotated Box / Cuboid / Keypoint. Picking a class auto-switches to its matching tool, but the dropdown lets you switch tools manually.
  • Class selector β€” pick the active class for new annotations. Searchable; first nine classes carry 1–9 shortcuts.
  • Upload β€” opens the upload modal (when allowed).
  • Download β€” exports the current item as a ZIP (when allowed). See Download / Export.
  • Instructions β€” opens the Project Instructions PDF for the user's role (when uploaded).
  • Split (multi-file items only) β€” toggles between Split 0/1/2/3. See Split View.
  • Keyboard shortcuts β€” opens an in-app cheat sheet on hover.
  • Documentation β€” opens this popup.
  • Dark mode β€” toggles the UI palette (preference is saved per browser).
  • Video adjustments β€” slider dropdown for Brightness, Contrast, Saturation, Shape Opacity, and Keypoint Size. See Video Adjustments.
  • Fullscreen (F) β€” expands the tool within its host.
  • Undo / Redo β€” see Undo / Redo.
Top toolbar: tool / class selectors on the left; Upload, Download, Instructions, Split, shortcuts, docs, theme, adjust, fullscreen, undo, redo on the right.

Tool Selector

Five tools, plus a class-driven auto-pair behaviour:

ToolShortcutUse
SelectSFree cursor β€” click annotations to inspect, drag handles to resize, drag bodies to move. No new annotations are created.
SegmentGAdd a time interval from the frame panel. Auto-selects when picking a class with type Segment.
BoxBDrag a rectangle on the video frame. Auto-selects when picking a class with type Box.
Rotated BoxShift+BThree-click oriented-box drawing on the video frame. Auto-selects when picking a class with type Rotated Box.
CuboidDFour-click cuboid drawing on the video frame. Auto-selects when picking a class with type Cuboid.
KeypointKClick to place a single point, or each skeleton joint in turn, on the video frame. Auto-selects when picking a class with type Keypoint.

The tool selector only lists tools that have at least one matching class configured. Shortcuts for hidden tools are disabled.

Class Selector

The class dropdown lists every class visible to the user's role, with a colour swatch, the class name, and a shortcut badge for the first nine. Type to filter by name. Selecting a class:

  • Sets it as the active class for new annotations.
  • Auto-selects the matching tool (Segment / Box / Rotated Box / Cuboid / Keypoint) so the next gesture draws the right kind of annotation.
  • Classes flagged as view-only for the user's role show a small lock icon and cannot be selected for new annotations.

Video & Overlays

The center area renders the video frame with all annotation overlays drawn on top of it.

Video Player

The video plays in the center area, with the Frame Panel timeline below it for frame-level navigation and editing. While a video is resolving, downloading, or loading metadata, the player shows a loading state or progress instead of a blank canvas.

  • Box overlay β€” when the active tool is Box, drag on the video frame to draw a rectangle. Existing boxes are rendered on top of the frame at their current time and respect the Shape Opacity setting.
  • Rotated Box overlay β€” when the active tool is Rotated Box, use the three-click workflow to draw an oriented rectangle. Existing rotated boxes render at their current angle and respect the Shape Opacity setting.
  • Cuboid overlay β€” when the active tool is Cuboid, use the four-click workflow to draw a cuboid. Existing cuboids render with transparent side/floor faces, a translucent front face (controlled by the Shape Opacity setting), and solid edges.
  • Keypoint overlay β€” when the active tool is Keypoint, click to place a single point or each skeleton joint in turn. Existing keypoints render on top of the frame at their current time; skeletons also draw their connecting bones. See Keypoint & Skeleton.
  • Zoom and pan β€” mouse wheel zooms around the cursor; drag pans while zoomed. Overlay geometry stays aligned with the video under the transform.
  • Overlay labels β€” toggled with O or the labels button: when on, hovering an annotation shows a small label chip with its class and primary text/value.
  • Shape class names β€” toggled with Shift+O from the canvas label button: shape labels switch between number-only labels and class-name-plus-number labels.

Keyframes

Box, cuboid, and keypoint annotations can hold multiple keyframes to track changes over time. For boxes, each keyframe stores a (time, rect) pair; for cuboids, a (time, eight-point shape) pair; for keypoints, a (time, point positions) pair. Between keyframes, geometry is interpolated linearly so the annotation tracks moving objects without creating a separate instance per frame.

A keyframe diamond is shown on the Frame Panel at every frame where geometry is explicitly stored. Re-drawing or moving an annotation at a new frame creates a keyframe there; the first placement of an instance establishes its starting pose without cluttering the timeline with a redundant diamond.

Cuboid redraw direction: When redrawing a cuboid at a new keyframe, it is important to draw in the same direction as the original (e.g. both left-to-right). Drawing in the opposite direction swaps point indices and causes the cuboid to "flip inside out" during interpolation. When you select a cuboid and click Redraw, labels 1 and 2 appear at the original first and second click positions with a directional arrow to guide consistent drawing.

Interpolation

Keyframes are sparse: you set geometry at a handful of frames and the editor fills in everything between them. For every frame inside an annotation's visible range, the displayed geometry is computed by linear interpolation between the nearest keyframe before and the nearest keyframe after the current frame.

  • Between two keyframes β€” each value (box edges, cuboid corners, or keypoint positions) moves in a straight line at a constant rate from the earlier keyframe's value to the later one. A box that is small on frame 10 and large on frame 40 grows smoothly across the frames in between.
  • Before the first / after the last keyframe β€” geometry is clamped (held constant) at the nearest keyframe's value, so the annotation never disappears or drifts outside the keyframed span.
  • Outside visible ranges β€” the annotation is simply not drawn. Interpolation only happens within a visible range.

Per-point keyframes (keypoints)

Keypoint skeletons interpolate per point, using a forward-fill (left-keyframe-wins) model. Each point's value persists from its most recent keyframe until the next keyframe that explicitly changes or removes it:

  • A point present at keyframe A and again at keyframe C interpolates smoothly between the two.
  • If you visit a frame B between A and C and remove that point there, the point holds its A value (frozen, not interpolating toward C) from A up to B, then disappears from B onward until a later keyframe re-introduces it.
  • Dragging a single joint creates a keyframe that also captures the positions of every other point visible at that frame, so nothing else is accidentally dropped.

Editing a range boundary

When you drag the start or end of a visible range inward and that move drops keyframes that fell outside the new boundary, the editor first computes the interpolated pose at the new boundary and writes it as a fresh keyframe. This keeps the annotation's geometry continuous instead of snapping to whatever keyframe is left β€” moving a boundary never causes a visible "jump."

Video Adjustments

Video adjustments button in the top toolbar opens a settings dropdown:

  • Brightness / Contrast / Saturation β€” applied as a CSS filter on the video frame so the original bytes are never mutated.
  • Shape Opacity β€” controls the fill opacity of bounding boxes and cuboid front faces rendered on top of the video. Useful for keeping the underlying frame readable when many overlapping annotations are present.
  • Keypoint Size β€” slider (2–10, default 5) controlling the visual size of keypoint dots only. Saved per user in browser local storage rather than the project config, so each annotator can pick a comfortable size; the hit/select area scales up with larger sizes but never shrinks below the default for small sizes, keeping small points easy to click.
  • Reset β€” restores all sliders and the keypoint size to their defaults.

Frame Panel

In Frame Mode (the tool's player mode), a full frame-based timeline appears below the video as the primary navigation surface. The Frame Panel is designed for frame-level annotation work with boxes, cuboids, and keypoints.

Controls

The Frame Panel control bar provides:

  • Play / pause, mute / unmute, frame-by-frame navigation (previous / next frame buttons).
  • Current-frame number entry, time display, and playback speed.
  • Alt+, / Alt+. shortcuts to step one frame backward / forward (frame mode only, Split 0).
  • A sticky frame ruler that remains visible while annotation rows scroll below. Click anywhere on the ruler to seek.

Instance Rows

Each box, cuboid, keypoint, or segment annotation appears as a row in the Frame Panel timeline (a skeleton occupies one row, not one row per joint):

  • Visible ranges shown as coloured spans using the instance class colour.
  • Range handles β€” drag the start / end edges of a visible range to adjust boundaries.
  • Keyframe diamonds β€” mark frames where geometry is explicitly stored; between keyframes, position is interpolated.
  • Row actions β€” open Instance View, add visible range, cut (split) range at the current frame, delete range, delete instance.

Instance View

Instance View is a focused mode for the selected annotation. Clicking the Instance View button on a row opens a dedicated single-instance panel that replaces the multi-row timeline.

The panel shows an 8-pixel-per-frame horizontal bin strip for that instance, using the class colour for visible frames and grey for gaps. Navigation:

  • The strip auto-scrolls to keep the current frame visible, preserving scroll position during range / keyframe edits.
  • Every 20th frame is labelled on the ruler.
  • A green cursor marks the current frame.
  • Clicking the ruler seeks without leaving Instance View.

Range and keyframe operations are available directly in the selected-instance header:

  • Add a new visible range at the current frame.
  • Cut (split) a range at the current frame.
  • Delete the visible range under the playhead (when more than one range exists).
  • Delete keyframes from the focused instance.

An X button in the upper frame timeline exits Instance View and returns to the full multi-row Frame Panel.

FPS

If the current video has per-video FPS metadata, frame stepping uses it. Otherwise the editor falls back to the project-level FPS value from Advanced Settings. The FPS field remains visible either way: when FPS Control is enabled, annotators can edit per-video FPS (or clear it to use the fallback); when disabled, the field is read-only and still shows the stored value or fallback.


Playback Controls

A row of controls under the player exposes everything needed to drive playback and switch view modes:

  • Play / Pause (Space, or Shift+Space while typing), Mute (M).
  • Time display β€” current / total in seconds.
  • Overlay labels (O).
  • Shape class names (Shift+O, video canvas only).
  • Playback speed β€” dropdown with values from 0.25x to 3x.
  • Toggle wide view β€” switches to a wider layout that gives the player more horizontal space.

Use , / . to seek 3 s back / forward and < / > for 10 s jumps. Press M to toggle mute. Press O to toggle overlay labels on hover, and press Shift+O to toggle class names on shape labels. Press F to toggle fullscreen, and press Shift+F to fit the zoomed video back to view. Press Shift+Space to play / pause even while typing in property fields. Alt+, / Alt+. step one frame backward / forward in the Frame Panel. All shortcuts also work in Split View, where they target the focused card (or all cards in broadcast mode).

Keypoint drawing shortcuts. While the Keypoint tool is active with a skeleton class (or while editing a skeleton), , and . become point navigation (previous / next joint) instead of seeking, so you can walk through joints without moving the video. They revert to seeking once you leave the drawing / editing state.

Creating Annotations

The exact gesture depends on the class's tool type:

Segment

  1. Pick a class of type Segment from the dropdown β€” or press 1–9. The Segment tool selects automatically.
  2. Use + Segment in the Frame Panel to add a time interval around the current playhead.
  3. The new segment appears as a coloured row in the Frame Panel and as a row in the annotation panel.
  4. Drag the range's start / end handles to trim it, or use the row's cut / split actions in the Frame Panel.

Box

  1. Pick a class of type Box. The Box tool selects automatically and the video frame becomes the drawing surface.
  2. Pause at the desired frame, then drag a rectangle on the video. The box receives a start / end time around the current playhead by default.
  3. To track movement, scrub to a later frame, select the box, and add a new keyframe β€” the box position interpolates between keyframes.

Rotated Box

  1. Pick a class of type Rotated Box (or press Shift+B). The Rotated Box tool selects automatically and the video frame becomes the drawing surface.
  2. Click three points on the video frame in sequence:
    1. Point 1 β€” first corner of the box's "top" edge.
    2. Point 2 β€” the other end of the top edge. This sets the box width and its rotation angle; an oriented preview follows the cursor.
    3. Point 3 β€” drag away from the top edge to set the height, then click. The side you drag toward becomes the box's depth direction.
  3. The rotated box is created with a start / end time around the current playhead.
  4. To edit, switch to Select (S) and click the box: drag any of the eight resize handles (corners + edge midpoints) to reshape, the round handle above the top edge to rotate, or the body to move. Add keyframes at later frames to track movement and rotation β€” position, size, and angle all interpolate between keyframes (rotation along the shortest angle).

Cuboid

  1. Pick a class of type Cuboid (or press D). The Cuboid tool selects automatically and the video frame becomes the drawing surface.
  2. Click four points on the video frame in sequence:
    1. Point 1 β€” first point of the front bottom edge (e.g. bottom-left corner of the object).
    2. Point 2 β€” second point of the front bottom edge (e.g. bottom-right corner). A solid preview line connects the two points as you move the cursor.
    3. Depth point β€” click to define the depth of the cuboid. A live parallelogram (the bottom face) previews as you move the cursor.
    4. Height point β€” click to define the height. This point is constrained to move vertically (same X as the depth point), keeping the cuboid upright. The full 3D cuboid previews live as you move the cursor.
  3. The cuboid is created with a start / end time around the current playhead.

Point Ordering

The eight corner points of a cuboid are stored in a specific order. Points 1–4 define the front face and points 5–8 define the back face. Each face follows the same winding: the first click's side bottom β†’ second click's side bottom β†’ second click's side top β†’ first click's side top. For example, if you draw left-to-right the order is BL β†’ BR β†’ TR β†’ TL; if you draw right-to-left it is BR β†’ BL β†’ TL β†’ TR.

  • Point 1 (p0) β€” front bottom, first click's side (your first click)
  • Point 2 (p1) β€” front bottom, second click's side (your second click)
  • Point 3 (p2) β€” front top, second click's side
  • Point 4 (p3) β€” front top, first click's side
  • Point 5 (p4) β€” back bottom, first click's side
  • Point 6 (p5) β€” back bottom, second click's side (your third click)
  • Point 7 (p6) β€” back top, second click's side (your fourth click)
  • Point 8 (p7) β€” back top, first click's side

The drawing order maps to: Click 1 β†’ p0, Click 2 β†’ p1, Click 3 β†’ p5 (depth), Click 4 β†’ p6 (height). The remaining points are derived automatically to form a consistent cuboid shape.

Cuboid Editing

Switch to the Select tool (S) and click a cuboid to select it. Selected cuboids display point handles at each corner and special center handles for advanced editing:

  • Move β€” drag anywhere inside the cuboid's body to translate the entire shape.
  • Back face handle β€” drag the center handle on the back face to translate all four back points uniformly, adjusting depth and perspective without changing the front face.
  • Top face handle β€” drag the center handle on the top face to translate all four top points (p2, p3, p6, p7), allowing you to skew the cuboid vertically. Hold Shift while dragging to constrain movement to vertical only (resets the cuboid to an upright orientation).
  • Front point editing (pillars) β€” dragging a first-click-side front point (p0 or p3) moves the entire first-click-side pillar (p0, p3, p4, p7). Dragging a second-click-side front point (p1 or p2) moves the entire second-click-side pillar (p1, p2, p5, p6). For example, if you drew left-to-right, p0/p3 control the left pillar and p1/p2 control the right pillar. Front and back face shapes stay equal.
  • Back point editing β€” dragging any individual back point (p4–p7) translates the entire back face uniformly, identical to the back face center handle.
  • Redraw β€” click the redraw icon (near p6) to replace the cuboid's geometry at the current frame using the four-click workflow. Labels 1 and 2 appear at the original p0 and p1 positions along with a directional arrow, guiding you to draw in the same direction to avoid interpolation flips.

Keypoint & Skeleton

A Keypoint class is either a single point or a multi-point skeleton, depending on how the class is configured.

Single-point keypoints

  1. Pick a single-point Keypoint class (or press K). The Keypoint tool selects automatically.
  2. Pause at the desired frame, then click once on the video frame to place the point. The keypoint receives a start / end time around the current playhead.
  3. The tool stays selected so you can place the next single-point keypoint right away (matching the image tool).
  4. To track movement, scrub to a later frame, select the point, and drag it β€” a keyframe is created and the position interpolates between keyframes.

Skeleton keypoints

  1. Pick a skeleton Keypoint class. The Keypoint tool selects automatically and a hint shows which joint you're placing.
  2. Click to place each joint in turn, in the order defined by the skeleton. Connecting bones draw automatically as you go.
  3. Skip a joint with the next-point control (or .); step back with ,. A joint left unplaced is simply absent on that frame. If you skip every joint, the tool switches back to Select without creating an instance.
  4. When the skeleton is finished, the tool switches to Select and the new instance is selected in the annotation panel (matching the image tool).

Selecting & moving skeletons

  • A selected skeleton shows a dashed bounding box and a draggable move handle sitting above the box; drag the handle to move the whole skeleton at once.
  • Drag an individual joint to reposition just that point. Either kind of move writes a keyframe at the current frame, preserving the positions of the other visible joints.

Editing a skeleton

Select a skeleton and use its edit control (the time-based redraw icon) to re-place its joints at the current frame, creating a keyframe there. During editing, , / . (and the on-screen arrows) navigate between joints, and the trash / delete control removes the joint under the cursor. If editing leaves every joint unchanged, no redundant keyframe is added.

To remove any annotation, select it (panel row, segment row, box, cuboid, or keypoint) and press Delete or Backspace.


Annotation Panel

The annotation panel is the command-centre for structured data. It lists every annotation in the item and offers two complementary views.

Instance View

The default layout: one row per annotation. Each row shows:

  • An eye icon for per-annotation visibility, copy-id button, the class chip (click to change class), and the annotation's start / end times.
  • Quick-action icons β€” comments, relationships, property popover icon (opens property popover).

Click a row to seek the playhead to the annotation's start. The panel supports:

  • Video filter β€” (multi-file items only) a dropdown at the top of the panel filtering annotations and tags to a specific video file.
  • Group By β€” Video Name (default for multi-file), Class Name, or Tool Type.
  • Order By β€” JSON Export (default), Class Name, Tool Type, Start Time, Created By, Creator Role, Created At.
  • Filter β€” by class, by property, by comments (when comments are enabled).
  • Reordering β€” when using Group By Video Name and Order By JSON Export, drag handles appear on instance rows. Drag to reorder instances within the same video file. Reordering is reflected in the data and export.
Annotation panel Instance View grouped by Video Name with rows showing start/end times, class chips, and per-row action icons.

Table View

Toggle to Table View for a spreadsheet-style grid: one row per annotation, one column per property. This is the fastest way to scan and edit properties across many annotations at once, and ideal for bulk AI autofill review (both AI Text and AI Select).

  • Fixed columns: Video (multi-file only), Class, Tool Type, Start, End, optional Comments column when comments are enabled, one column per relationship type, plus the three Created-By / Role / At meta columns (hidden by default).
  • Property columns adapt to the class of each row β€” properties not defined on a class show as empty cells.
  • Sort by any column; filter via column headers. Rating columns use the same numeric min/max filter as Numeric. Approval columns offer a fixed three-state picker β€” Approved, Disapproved, (Blank) β€” regardless of which states currently appear in the data, so you can always pre-filter for "no verdict yet" before any rows have been approved.
  • Inline edit each cell; changes auto-save immediately.
  • AI extraction column (Table View) β€” when a class has AI Text / AI Select properties, the table adds a leading AI column with row-level actions: Extract (all empty, runnable AI properties on that row) and, when Enable Editing is on, Edit prompt. These mirror the action bar at the top of the property popover.
  • Per-property extract icons (Table View) β€” individual AI Text and AI Select cells also show compact extract (and optional edit-prompt) icons beside the field, matching the per-property icons beside each AI field label in the property popover.
  • Use the Columns dropdown to reorder, hide, or pin columns for the current session. Your starting order and pin defaults come from the project-wide Table Column Settings.
  • Pin columns β€” clicking the pin icon next to a column glues it to the leading edge of the table. Pinned columns always render before unpinned ones (preserving relative order within each cluster); the leading utility cells (eye icons, drag handle, copy-id) and group subheaders also stick to the leading edge once any column is pinned, so per-row controls and group labels stay visible during horizontal scroll. Drag-reordering inside the dropdown is restricted to within a cluster (pinned↔pinned or unpinned↔unpinned). Pin state is per-session.
Annotation panel Table View with columns: Video, Class, Tool Type, Start, End, plus property and relationship columns.

Column Group Chips

When an admin has configured column groups, a row of toggle chips appears above the table. Each chip represents one group and shows its label. Click a chip to show or hide all columns in that group at once. Chips display three visual states: active (all group columns visible), partial (some columns individually hidden), and inactive (all group columns hidden). Hovering a chip shows a tooltip listing the columns it contains. Editors can still show or hide individual columns from the Columns dropdown regardless of group state.

Grouping & Bulk Edit

Both Instance View and Table View can group annotations by Video Name, Class Name, Tool Type, or any individual Property. In Table View, groups display visual subheader rows that break the grid into collapsible sections β€” one per group value. Group headers include collapse / expand controls.

Editable groups expose an Edit action next to the group label. Clicking it opens a bulk-edit popover where you can apply changes to every annotation in the group at once:

  • Change the class of all grouped annotations. See Class Changes for class eligibility, property retention, and confirmation details.
  • Edit shared property values across the group.

Changes from the bulk-edit popover are applied immediately and feed the standard undo stack.


Property Editing

Click the property popover icon on a row in the Instance View to open the property popover. The popover anchors next to the row so the source annotation and the structured fields stay visible together. For AI Text and AI Select fields, compact extract icons sit beside each property label (single-property scope); a separate action bar at the top of the popover runs extraction for the whole row. In Table View, fields are inline-editable in their cells.

  • Free Text β€” inline editable; its Text Display mode controls presentation: Inline (default), Modal (a roomy verbatim plain-text modal), or Rich Text (a formatted rich-text modal).
  • AI Text β€” auto-fill at three scopes: a single property (extract icon beside the field in the property popover or table cell), a whole row (popover action bar or table AI column), or all visible panel rows when bulk extraction is enabled. Manual edit if Enable Editing is on. Supports the same Text Display modes (Inline / Modal / Rich Text).
  • Select β€” always a dropdown; the Allow multi-select property option controls whether one or multiple options can be picked at the same time.
  • AI Select β€” dropdown with predefined options, pre-selected by AI autofill through the same single-property, row-level, or bulk panel entry points. The model picks from the configured option list using the per-property prompt. Manual override is always possible; when Enable Editing is on, annotators can also tweak the prompt before extraction.
  • Numeric β€” number input with optional bounds and unit.
  • Rating β€” orange/gold star picker rendered in the popover, Table View cell, bulk edit dialog, and Frame Panel instance view. Click a star to store that number; click the currently selected star again to clear the value. Hover previews fill from the first star through the hovered star. Required-and-empty editable ratings get the same thin red wrapper outline as Approval. View-only access keeps the palette but dims the stars and disables clicks. Table search matches the displayed number. Time-based Rating writes a rating keyframe at the current playhead and clears by writing an empty keyframe value.
  • Approval β€” a compact two-button picker (thumbs-up / thumbs-down) for capturing a three-state verdict. Click the up icon to mark the row approved (stores "true"), the down icon to mark it disapproved ("false"); clicking the active icon again clears the verdict, and clicking the opposite icon swaps it in place. The property popover and Table View cell render the same picker, and changes flip on click without needing to dismiss the popover or refresh the panel. In view-only contexts (role lacks edit access, class is view-only) the icons keep their green / red palette but read as dimmed so the verdict stays legible at a glance; the buttons are not interactive. Approval columns are excluded from the table's free-text search β€” filter by verdict via the column dropdown's three-state picker. Time-based approval works exactly like any other time-based property: each click writes a keyframe at the current playhead carrying "true" / "false" / "", the frame panel's keyframe popover lists the verdict as plain text (true, false, or (cleared)), and the table / popover picker reflects the value resolved at the current frame.
  • Required indicator β€” required properties are visually flagged when empty so incomplete annotations are easy to spot.

AI Property Autofill

Being rebuilt. AI property extraction is being reworked to draw on the video frame (similar to the image tool). The extraction scopes and bulk controls below reflect current editor behaviour; the exact input the model receives will change when that feature lands.

The AI Text and AI Select property types send annotation context and each property's configured prompt to your AI proxy. By default the model and proxy come from project configuration; individual properties can override that routing.

Where to trigger extraction

AI extraction is available at three scopes. Single-property and row-level controls exist in both the property popover and Table View; bulk extraction runs from the annotation panel header regardless of which panel mode you are in.

  • Single property β€” run one AI Text or AI Select field at a time.
    • Property popover β€” each AI property shows compact Extract (and, when Enable Editing is on, Edit prompt) icons beside its label.
    • Table view β€” the same per-property icons appear inside that property's table cell. See Table View.
  • Whole row β€” run every empty, runnable AI property on one annotation row at once.
    • Property popover β€” the AI action bar at the top of the popover offers Extract and Edit prompt (when editing is enabled for any AI property on the row).
    • Table view β€” the leading AI column mirrors those same row-level actions.
  • Full annotation panel β€” when bulk extraction is enabled, the panel-header extract button runs AI extraction across every visible instance row in the panel, in Instance View or Table View. See Bulk annotation panel extraction.
  • Edit prompt modal β€” opened from any Edit prompt entry point above; shows editable per-property prompts before running.

Prompts and routing

  • System prompts are configured per property as the Default Prompt and can be overridden per-run when editing is enabled.
  • Per-property proxy / model β€” properties with a configuration override route independently. A single row or popover extract may issue multiple API batches when its empty AI properties resolve to different proxy/model pairs.
  • For each request the tool sends a built-in system message and a user payload describing the annotation in context.
  • For AI Select, the model returns one (or more, if multi-select is enabled) option labels from the property's predefined list; unrecognised values are silently dropped.
  • Requires a configured route for each property being extracted β€” either the project AI Property Proxy or a per-property override.
  • The same models also power the Ask AI assistant in this in-app documentation popup β€” that path always uses the project proxy, not per-property overrides.
  • When Enable Editing is on, annotators can tweak a property's prompt before pressing Extract; when off, the configured prompt is used as-is. Errors (rate limits, provider failures, missing proxy) surface as toasts.

Bulk annotation panel extraction

When an admin enables Allow Bulk Extraction of all AI Properties, a compact extract button appears in the annotation panel header (alongside the view / group-by controls). Click it to run AI extraction across every visible instance row in the panel β€” whether you are in Instance View or Table View.

  • Scope β€” respects the current panel filters, table search (when in Table View), column filters, video/class filters, and collapsed group sections. Collapsed sections are skipped; only expanded groups contribute rows.
  • What runs β€” for each qualifying row, the bulk job extracts the same set of properties the row-level Extract button would β€” empty AI Text / AI Select fields that pass visibility and accessibility checks. Already-filled values and view-only AI properties are skipped.
  • Confirmation & progress β€” a confirm dialog shows the row count. During the run a non-dismissible progress banner counts completed rows; row-level and per-property extract icons show a spinner while that row is queued. Outcome toasts stack beneath the banner.
  • Summary β€” when finished, a dismissible banner reports how many rows were fully filled, partially filled, failed, or skipped.
  • Concurrency β€” rows are processed in parallel (up to 15 at a time); each row still batches its own properties by proxy/model route.
  • The button is hidden entirely when the configuration toggle is off, and disabled when no visible rows have anything left to extract.

Text Display Modals (Modal & Rich Text)

Free Text and AI Text properties whose Text Display mode is set to Modal or Rich Text render as a compact pill in the popover / table cell; clicking it opens a full-page editor instead of editing inline. The same modals are reused for tag-level properties.

  • Modal (plain text) β€” opens the same kind of full-page popup as the Rich Text modal, but with a plain editing area and no formatting toolbar. What you type is stored exactly as-is β€” whitespace, line breaks, and literal markup (raw HTML, JSON, code) are preserved verbatim, with no formatting or conversion applied. Use it for comfortable reading and editing of long or structured plain text.
  • Rich Text β€” a formatting editor supporting bold, italics, headings, bulleted and numbered lists, blockquotes, inline code, code blocks, links, and tables. Sized for multi-paragraph content like detailed image captions, OCR transcriptions of long passages, or scene descriptions. Content round-trips through a formatted representation, so it is not intended for preserving arbitrary literal markup β€” use Modal for that.

Both modals offer a View only state for read-only roles and close on Save & Close, Cancel, or Esc.

Property & Option Visibility Rules

Configurations defined as property visibility rules and option visibility rules are evaluated and enforced live as the annotator works β€” there's no separate "validate" step, and the same logic applies in both the floating property popover and the table view.

Property Visibility Rules β€” apply to any property type

A property visibility rule can be set on any property type (Free Text, AI Text, Select, AI Select, Numeric, Rating, Approval β€” all of them, except time-based properties which are mutually exclusive with rules). When the rule is unsatisfied for the current row, the whole field is treated as inaccessible:

  • The field still renders in the popover and as a table column so annotators can see the field exists, but it's dimmed and read-only, with a not-allowed cursor and a hover tooltip explaining what controls it (e.g. "Controlled by: Object Category = Vehicle").
  • Any stored value on that property is automatically cleared the moment the rule flips to unsatisfied β€” and the clear cascades, so if A controls B and B controls C, changing A can clear both B and C in a single step.
  • Required validation is suppressed while the property is inaccessible β€” the red required indicator on the annotation / tag row only reactivates when the rule becomes satisfied again.
  • AI extraction is skipped on AI Text / AI Select properties whose rule is unsatisfied. The row-level Extract / Edit prompt controls, the per-property icons in the property popover, and the per-cell extract icons in the table all hide or grey out for these fields, and re-appear the instant the controller flips back β€” no popover reopen needed.
  • Modal / Rich Text properties gated by an unsatisfied rule render as a plain "β€”" placeholder; their modal (plain-text or rich-text) cannot be opened. Approval columns behave the same way in the table β€” the cell collapses to "β€”" rather than rendering a dimmed picker, matching the convention used by every other column type. The property popover keeps the dimmed-disabled picker so users still see what the field would look like.

Option Visibility Rules β€” apply only to Select / AI Select

Select and AI Select properties additionally support per-option visibility rules. These don't hide the whole field β€” they filter the contents of the dropdown:

  • Each option appears in the dropdown only when its own rule is satisfied by the current controller values on that same annotation / tag row. Options with no rule are always shown.
  • If the annotator changes a controller value and a previously-selected option is no longer valid, the dropdown's stored value is cascade-cleared the same way property-level rules cascade β€” so the row never holds an option that can't be re-picked from the visible list.
  • For AI Select, the model's pre-selection respects the same filtering β€” values the model returns that fail the active rules are silently dropped before being written to the row.

How the two layers combine on a Select / AI Select property

A Select / AI Select property can carry both kinds of rules at once: a property visibility rule on the field itself, and option visibility rules on one or more of its individual options. The editor evaluates them in a fixed order β€” property first, then options β€” so they can't contradict each other:

  1. The property rule runs first. If it is unsatisfied, the whole field is dimmed and read-only as described above; option rules on that field are never evaluated, because there is nothing to pick from while the field is inaccessible.
  2. If the property rule passes (or no property rule exists), the option rules filter what appears in the dropdown.

In short: the property rule decides whether the field is in play; the option rules then decide which choices are valid inside it. Cascade clearing covers both layers in one pass β€” a stored value can be cleared because the option it points to is no longer valid (option-rule failure) or because the whole property hosting it is no longer visible (property-rule failure). The chain icon on a property's editor label, and the small chain badge in the table column header, both surface the active rule's controller(s) on hover so annotators can quickly see why a field is dimmed or why their list of options is narrower than expected.

Time-Based Property Editing

A property marked time-based in configuration holds a timeline of values rather than one constant. Annotators edit it exactly like a normal field (popover, table cell, or the frame-panel instance view) β€” the difference is when the value applies. A small clock icon next to the field label (and inside the table cell) marks these properties so they're easy to tell apart from constant ones.

Reading the value

Every time-based field shows the value that applies at the current playhead β€” specifically the value of the most recent property keyframe at or before the current frame (a step function, no interpolation). As you scrub or play, the displayed value updates to match the timeline. The panel refreshes these fields on seek so the popover, table, and instance view always reflect "now".

Setting values

  • First value anchors at the instance start. The first value you set for a time-based property applies from the instance's start through to its end β€” like a constant β€” and shows no marker, mirroring how the first geometry keyframe is invisible.
  • Later edits create a keyframe at the current frame. Once a starting value exists, changing the value at a different frame writes a property keyframe there: the new value applies from that frame forward until the next keyframe (or the end).
  • Redundant changes collapse automatically. Setting a value to what it already shows is a no-op (no keyframe). Setting Aβ†’Bβ†’A at the same frame removes the keyframe again. Setting a value equal to the next keyframe's value moves that change earlier (the later keyframe collapses away).
  • Out-of-range is disabled. When the playhead sits outside the instance's visible range, the field is shown blank and read-only β€” there's no valid frame to attach a value to. Opening the property popover from the panel automatically seeks into range so the fields are editable.
  • Bulk edits from grouped table editing write a keyframe at the current frame for each in-range instance and skip instances whose range doesn't cover the playhead (the toast reports how many were updated vs. skipped).

Markers & deletion

On the Frame Panel, property keyframes appear as a circle in a thin lane just above the geometry bar β€” distinct from the geometry diamond, so a frame where both change reads as a diamond + circle stacked. The circle is an aggregate: one marker per frame where any time-based property changes, regardless of how many do.

Hovering any marker (diamond or circle) on the main timeline or the instance-view strip opens a small keyframe popover listing every change recorded at that frame β€” the geometry change and/or each property change β€” each with its own trash icon. This is the single place to delete an individual change at a frame; deleting a property keyframe re-resolves the value from the previous surviving keyframe.

Range edits & type changes

  • Dragging a range boundary prunes property keyframes the same way it prunes geometry. Moving the start past a keyframe drops earlier keyframes and re-anchors the start value; keyframes that fall into an interior gap are pruned outright (the following region forward-fills from the nearest surviving earlier keyframe).
  • Toggling a property's time-based flag (in configuration) applies a clean overwrite on the next editor load: constant β†’ time-based seeds a single start keyframe from the current constant value; time-based β†’ constant keeps the start value as the new constant and drops the keyframes.

Comments

Comments let reviewers and annotators leave scoped notes on a specific annotation without cluttering the source video. Typical uses:

  • Flagging ambiguous segments for a second opinion.
  • Recording rationale for borderline class decisions.
  • QA feedback that doesn't belong in property values.

Each comment has an author, a timestamp, the message text, and a resolved flag. Comments are a flat list per annotation β€” there is no nested reply threading. Resolving a comment is gated by the Resolve Comments (Roles) allow-list, and deleting by Delete Comments (Roles). Comments are exported alongside the rest of the structure.


Relationships

Relationships capture the links between annotations β€” which object refers to which, how two things are related. They turn a flat list of annotations into a graph suitable for relation extraction, event modelling, or tracking the same object across instances.

  • Enabled when Instance Relationships is on in configuration.
  • The relationship-type taxonomy is admin-curated under Feature Control β†’ Relationship Types; annotators pick from that list (no freeform types).
  • From an annotation row, click the relationship icon, pick a relationship type, then pick the target annotation.
  • Each annotation can hold one target per relationship type (a same-type, same-source link replaces the previous target).
  • Relationships are directional (source β†’ target). Symmetry isn't a per-edge flag β€” model it by adding a second relationship type, or by adding the inverse link manually.

Class Changes

To reclassify one annotation, click its class chip in the annotation panel and choose a class from the menu. The annotation's timing or geometry stays unchanged; only its class and property values are updated. To reclassify a group, use the Edit action described in Grouping & Bulk Edit.

  • Eligible classes. The menu lists only visible, editable classes with the same tool type as the annotation. A Box can become another Box, but not a Cuboid, because their geometry differs. To convert across tool types, delete the original and redraw it under the new class.
  • Strict property matching. A populated value is retained only when the destination class has one property with the exact same name and type and an identical value-shape configuration. This includes Select options and order, single/multi-select mode, defaults, visibility rules and their controllers, text display mode, numeric bounds/step/unit, rating maximum, role-visibility settings, and whether each of those fields is absent or explicitly set. Property IDs are remapped as they are unique and can't match.
  • What does not block retention. Required status, helper text, and AI extraction settings such as prompts, model routing, and prompt-edit permission can differ. They affect future validation, help, or extraction rather than the stored value itself.
  • Rules and access are enforced. The destination property must be editable for the current user. After all compatible values are mapped, the destination's property and option visibility rules are evaluated together; a value whose controller does not allow it is removed. Invalid or stale values are not retained. Destination defaults fill properties that have no retained value.
  • Time-based properties. A time-based property is retained only when its time-based setting also matches. Its complete keyframe timeline is moved under the destination property ID; a timeline with no matching destination property is removed.
  • Confirmation and Undo. If any populated value or time-based timeline cannot be retained, the confirmation dialog reports retained and removed counts before applying the change. The same summary is used for a grouped class change. One Undo restores the original class, property values, and keyframes.

Unknown class

When a class is deleted, or its tool type is changed in configuration, any existing annotations that referenced it can no longer be drawn as that class. Instead of guessing, those instances are shown as Unknown β€” rendered in a neutral grey across the canvas, the annotation panel, and the Frame Panel.

  • An Unknown instance keeps its geometry and its place on the timeline; only its class identity is unresolved.
  • It can be reclassified β€” the class menu offers the classes whose tool type is compatible with the instance's geometry.
  • Stored properties remain unchanged but are unavailable while the instance is Unknown. AI extraction does not run on Unknown instances.

Annotation Isolation

Annotation Isolation is a configuration-level privacy mechanism, not a per-annotation dim toggle. When isolation is set to By User, by default each user only sees the annotations they themselves created. A role on Bypass Isolation (Roles), or the item's current status in Bypass Isolation (Statuses), lets that viewer see everyone's annotations. Matching either bypass is enough.

  • Use isolation to prevent annotator bias by hiding peer annotations during the labelling pass.
  • Reviewers in the bypass list can see all annotators' work side by side for QA.
  • Creator filter chips β€” when isolation is on and the user is a bypasser, a row of chips appears at the top of the annotation panel labelled by creator. Toggle a chip off to hide that creator's annotations on the video and in the panel; toggle back on to bring them back.
  • The eye icons in the panel let users hide individual annotations from their own view independently of isolation.

Tags under isolation

System-generated tags (item-scope and video-scope) participate in isolation alongside instances, but with a few rules of their own:

  • Lazy creator stamping (ON and OFF) β€” tag rows are rendered in the panel as soon as an item is opened, but no createdBy / createdAt is written to the JSON until the user makes their first JSON change anywhere in the item. That first change synchronously stamps every visible placeholder with the current viewer's email, role, and timestamp. An item that's only been viewed produces zero tag rows in the saved JSON and downloads.
  • Isolation ON β€” one row per user, per scope β€” the system auto-generates one tag row per user per visible tag class, on each scope (item-scope or video-scope), excluding admins (role id 3). Two annotators opening the same item end up with two independent rows for each tag class β€” each can edit their own row's properties and comments without seeing the other's, and a bypass reviewer sees all rows side by side. Re-opening an item where the user already has a row never creates a duplicate.
  • Mid-project rollback β€” if isolation is turned off after items have already accumulated multi-user copies, all existing copies stay intact. New users opening those items don't get a fresh copy; they edit whichever row already exists for the class. Brand-new items opened after the rollback follow the OFF rule (one row per class).
  • Admins leave no footprint on passive view β€” admins never trigger tag materialization or stamping on open. An admin only becomes a tag's createdBy if they actively create a row that didn't exist yet (no row for their email under iso ON, or no row at all under iso OFF). Admin edits to a tag created by someone else preserve the original creator and only land the property / comment change.
  • Creator chips and table columns extend to tags β€” the bypass-mode creator-chip filter buckets tag rows by their stamped creator just like it buckets instances. The Created By, Creator Role, and Created At columns in the panel's table view populate for tag rows once stamped, and they're searchable / filterable.
  • Deletion stays locked β€” tags are system artefacts and cannot be deleted by any role, including bypass viewers. Bypass viewers can read and edit other users' tag properties and comments; non-bypass viewers only ever see their own rows.

Undo / Redo

The tool maintains a single history stack of annotation actions β€” drawing, moving, keyframe edits, range edits, class changes, and property edits. Ctrl(⌘)+Z reverts to the previous snapshot; Ctrl(⌘)+Shift+Z (or Ctrl(⌘)+Y) re-applies it.

Import / Export

Items arrive into a project through JSONL bulk upload at the SuperAnnotate platform level. The editor reads each item's data.video_annotation_tool.value payload when it's opened. Items leave through the editor's Download button as a ZIP β€” round-trip-safe, so an exported annotations.jsonl can be re-imported into another project. Video bytes can either be uploaded to SuperAnnotate storage or URL-linked from elsewhere; the editor handles both via the same payload shape.

JSONL Import

JSONL (one JSON object per line) is the platform ingest format. Each line is one item. The editor doesn't have a direct JSONL upload button β€” items appear in the editor after the platform creates them from the JSONL.

Payload Shape

Each item must have:

  • metadata.name β€” display name (required).
  • data.video_annotation_tool.value β€” the tool-specific payload. Inside value, items use a videos array (one entry per video file).

Each entry in videos is a StoredVideoFile with exactly one of uploadedFile or url:

  • uploadedFile β€” { uniqueName, fileName, fileType, fileSize }. Bytes live in SuperAnnotate storage; the platform resolves the bytes via uniqueName.
  • url β€” a string URL with a sibling urlKind (see URL-linked video) and optional fileType / fileSize hints.

Each entry can also carry instances and tags arrays.

Video only. Linked sources must be valid video files. If an item's source resolves to a non-video file, the editor refuses the item with a banner rather than loading a broken canvas.

Minimum required keys: metadata.name and data.video_annotation_tool.value.videos (at least one entry). Each videos entry needs a name (or, for URL-linked entries, the editor falls back to the trailing path segment of url) and exactly one of uploadedFile or url. Everything else β€” urlKind, instances, tags, itemTags β€” is optional and can be added incrementally.

Uploaded Video β€” Two Files

{
  "metadata": { "name": "traffic-clip-001" },
  "data": {
    "video_annotation_tool": {
      "value": {
        "videos": [
          {
            "name": "Camera A",
            "uploadedFile": {
              "uniqueName": "abc123.mp4",
              "fileName": "camera-a.mp4",
              "fileType": "video/mp4",
              "fileSize": 48231040
            },
            "instances": [
              {
                "id": "ann-1",
                "instanceNumber": 1,
                "classId": "class-vehicle",
                "type": "bbox",
                "start": 12.34,
                "end": 18.7,
                "bbox": { "x": 0.41, "y": 0.52, "width": 0.18, "height": 0.12 },
                "propertyValues": { "prop-label": "Sedan" }
              }
            ],
            "tags": [
              { "tagClassId": "tc-quality", "propertyValues": { "prop-score": "0.95" } }
            ]
          },
          {
            "name": "Camera B",
            "uploadedFile": {
              "uniqueName": "def456.mp4",
              "fileName": "camera-b.mp4",
              "fileType": "video/mp4",
              "fileSize": 51023210
            },
            "instances": [],
            "tags": []
          }
        ],
        "itemTags": [
          { "tagClassId": "tag-indoor", "propertyValues": {} }
        ]
      }
    }
  }
}
Name uniqueness: Each video file's name is required. Duplicate names are auto-deduplicated with (1), (2) suffixes on import.

URL-Linked Video

To point at video that lives outside SuperAnnotate, replace uploadedFile with a url + urlKind pair:

{
  "metadata": { "name": "drone-flyover" },
  "data": {
    "video_annotation_tool": {
      "value": {
        "videos": [
          {
            "name": "Flyover",
            "url": "https://storage.example.com/video/flyover.mp4",
            "urlKind": "presigned",
            "fileType": "video/mp4",
            "fileSize": 81234560
          }
        ]
      }
    }
  }
}

urlKind tells the editor how to access the URL:

ValueMeaning
"uploaded"Bytes live in SuperAnnotate (rare in JSONL β€” usually carried by uploadedFile instead).
"public"Publicly accessible URL β€” fetched directly.
"presigned"Pre-signed URL (e.g. AWS S3) β€” fetched directly but may expire.
"integration"Requires platform integration credentials β€” the platform signs the URL before fetching.
"asset"Reserved for SA-internal asset URLs that need re-signing on each load.
Default behaviour: When urlKind is omitted, the URL is treated as an integration / asset URL and routed through the platform's signing path. If you are providing public or pre-signed URLs, you must set urlKind to "public" or "presigned" explicitly, otherwise the signing step will fail and the video will not load.

Structure Keys

KeyWhereDescription
metadata.nametop levelItem display name (required).
data.video_annotation_tool.valuetop levelThe tool-specific payload. Other tools may add their own keys under data.
videosvalueArray of StoredVideoFile β€” one per video file in the item (max 10).
videos[].namefileDisplay name for the file tab (required, auto-deduped if not unique).
videos[].uploadedFilefile{ uniqueName, fileName, fileType, fileSize } for SA-stored bytes. Mutually exclusive with url.
videos[].url + urlKindfileExternal URL with access kind. See URL-Linked Video.
videos[].videoFrameMetadatafileOptional { fps?, totalFrames?, frameTimestamps?, source? } used for frame-accurate stepping in the Frame Panel.
videos[].instancesfileArray of StoredAnnotation for this video file.
videos[].tagsfileArray of video-scoped tags: { tagClassId, propertyValues }.
itemTagsvalueArray of item-scoped tags: { tagClassId, propertyValues }. Apply to the whole item regardless of file count.
itemContextvalueOptional plain-text values for the Item Context slots β€” see Item Context for the shape and the orphan-key rules.
instances[].typeannotationOne of "segment", "bbox" (Box), "obbox" (Rotated Box), "cuboid", "keypoint".
instances[].classIdannotationReferences a class ID from the project's class list.
instances[].instanceNumberannotationOptional user-facing sequential number (#1, #2, …) shown next to the class name in the instance panel, table, canvas labels and Frame Panel. Unique across the whole item (all video files). Auto-assigned on load when absent (next free number, max+1) and persisted on the next save, so it can be omitted from preannotations.
instances[].start / endannotationTime interval in seconds from the start of the video. Present on every type.
instances[].bboxbbox{ x, y, width, height } β€” the axis-aligned rectangle on the video frame, in normalised coordinates (top-left origin).
instances[].bboxKeyframesbboxOptional array of { time, x, y, width, height } keyframes for tracking box movement across frames. Between keyframes, position and size are interpolated linearly.
instances[].obboxobbox{ cx, cy, width, height, rotation } β€” the oriented rectangle on the video frame, in normalised coordinates. cx/cy are the box centre and rotation is in radians. This matches the image tool's oriented-box format exactly. Rotated Box instances carry this instead of bbox.
instances[].obboxKeyframesobboxOptional array of { time, cx, cy, width, height, rotation } keyframes for tracking a rotated box across frames. Between keyframes, centre and size are interpolated linearly and rotation along the shortest angle.
instances[].cuboidcuboid{ points } β€” an array of eight { x, y } corner points in normalised coordinates defining the cuboid shape. Points 0–3 are the front face and points 4–7 are the back face, each wound from the first click's side to the second click's side. See Cuboid drawing for the full ordering.
instances[].cuboidKeyframescuboidOptional array of { time, points } keyframes for tracking cuboid changes across frames. Each entry has the same eight-point structure as cuboid. Between keyframes, points are interpolated linearly.
instances[].keypointskeypointArray of { pointId, x, y } points in normalised coordinates. A single-point keypoint has one entry; a skeleton has one entry per placed joint (skipped joints are simply absent).
instances[].keypointKeyframeskeypointOptional array of { time, points } whole-skeleton keyframes. The point set per keyframe may be partial; per-point interpolation uses the forward-fill model.
instances[].visibleRangesbbox / obbox / cuboid / keypointOptional array of { start, end } frame spans defining when the instance is visible. Used in the Frame Panel to allow an instance to appear and disappear without creating separate rows.
instances[].propertyValuesannotationObject keyed by property ID. Values are strings; multi-select values are option labels joined with ", ". For time-based properties this mirrors the timeline's start value, so time-agnostic consumers still work.
instances[].propertyKeyframesannotationOptional object keyed by time-based property ID; each value is an array of { time, value } entries sorted by time (seconds). The value applies forward from its time until the next entry (step function, no interpolation). See Time-Based Property Editing.
instances[].commentsannotationOptional flat array β€” see Comments.
instances[].relationshipsannotationOptional Record<relationshipTypeId, targetInstanceId>.
instances[].createdAt / createdByannotationAudit metadata. createdBy is { email, role }.

Download / Export

The Download button (when allowed by Access Control β†’ Download Annotations) produces annotations.zip containing the current item.

Export Structure

The ZIP always contains:

FilePurpose
annotations.jsonThe full payload β€” the videos array (with per-file video references, instances, tags) plus item-level tags.
name2id.jsonReference mapping: class names β†’ IDs (with their tool type), property names β†’ IDs, tag class names β†’ IDs, relationship type names β†’ IDs, and (when configured) Item Context slot names β†’ IDs under the itemContext key.
annotations.jsonlOne-line JSONL in the same shape accepted by JSONL Import.

The ZIP does not include original video bytes. Per-file URL references and uploaded-file metadata remain in annotations.json and annotations.jsonl, so imports retain the source information.

File download dialog showing annotations.zip with annotations.json, name2id.json, and annotations.jsonl.

Tags

Tags are split into two scopes in the export:

  • Item-level tags β€” stored in the top-level itemTags array. Apply to the whole item.
  • Video-level tags β€” stored per-file in videos[i].tags. Apply to that specific file only.

Each tag entry references a tag class by ID and carries its own propertyValues object. The name2id.json file maps tag class IDs back to names.

// Item-level
"itemTags": [
  { "tagClassId": "tag-indoor", "propertyValues": {} }
]
// Per-file (video-level)
"videos": [{ ..., "tags": [
  { "tagClassId": "tc-quality", "propertyValues": { "prop-score": "0.95" } }
]}]

Properties

Each annotation carries a propertyValues object keyed by property ID. Values are stored as strings:

  • Free Text / AI Text β€” the raw string value.
  • Numeric β€” the number serialised as a string.
  • Rating β€” the selected star count serialised as a string ("1" through the configured max); the key is omitted when unset. For time-based Rating the same strings appear inside each keyframe's value; a cleared keyframe carries an empty string ("").
  • Select / AI Select (single) β€” the option label.
  • Select / AI Select (multi) β€” option labels joined with ", ".
  • Approval β€” the literal string "true" when approved or "false" when disapproved. The key is omitted from propertyValues when no verdict has been given, matching how other property types treat blank values. For time-based approval the same strings appear inside each keyframe's value; a "cleared" keyframe carries an empty string ("").
"propertyValues": {
  "prop-label":      "Sedan",
  "prop-color":      "Red",
  "prop-tags":       "Moving, Occluded",
  "prop-confidence": "0.92",
  "prop-verdict":    "true"
}

Time-based properties additionally export a propertyKeyframes object next to propertyValues. It is keyed by property ID, and each value is a time-sorted array of { time, value } entries (time in seconds); each entry's value applies forward until the next entry. The matching propertyValues entry mirrors the first keyframe's value so time-agnostic readers (grouping, filtering, flat export) keep working. Constant properties never appear in propertyKeyframes. The example below has one constant property (prop-color) and one time-based property (prop-action):

"propertyValues": {
  "prop-color": "Red",
  "prop-action": "Idle"          // mirror of the first keyframe
},
"propertyKeyframes": {
  "prop-action": [
    { "time": 0.0, "value": "Idle" },
    { "time": 4.5, "value": "Driving" },
    { "time": 9.2, "value": "Parked" }
  ]
}

Relationships

Relationships are stored on the source annotation as a single Record<relationshipTypeId, targetInstanceId> map. Each relationship type can hold one target per source annotation β€” adding a new target on the same type replaces the previous one. Relationships are directional; model bidirectional links by adding the inverse relationship from the target side.

"relationships": {
  "rel-replies-to":  "ann-2",
  "rel-references": "ann-7"
}

Comments

Comments are exported as a flat array per annotation. Each comment captures author identity, message text, resolved state, and a creation timestamp. There is no nested replies structure.

"comments": [
  {
    "id": "cmt-1",
    "authorEmail": "reviewer@example.com",
    "authorName": "Pat Reviewer",
    "text": "Confirmed β€” box aligned with the vehicle's front bumper.",
    "resolved": false,
    "createdAt": "2026-04-20T14:02:11Z"
  }
]

Item Context

Item Context values are serialised as a top-level itemContext map of { slotId: string }. Keys are the stable slot ids from the project's Item Context configuration (the same ids surfaced under itemContext in name2id.json). Values use the same markdown-like plain-text format as rich-text properties β€” the editor renders them with full formatting but the on-disk representation stays plain text for backward compatibility.

"itemContext": {
  "ctx-abc123": "You are reviewing a traffic-camera clip.\n\n**Key rules:**\n- Box every vehicle that fully enters the frame\n- Mark uncertain cases with `[REVIEW]`\n\n> Focus on the nearest lane first.",
  "ctx-def456": "## Labelling guidelines\n\nTrack each subject across the clip with a stable Track ID.\n\n1. People β€” full skeleton where visible\n2. Vehicles β€” bounding box only"
}
  • Role-hidden slots are still exported. Per-role visibility is a UI concern; downloads always carry the full set of stored values so QA / export pipelines see everything.
  • Orphan keys are preserved. If a slot was deleted in config (or arrived via JSONL with an id no longer in config), its value is kept on disk and carried through every save and export. This mirrors the comments-style "non-destructive" precedent β€” admins can re-enable a feature later without rebuilding past data.
  • Empty strings are valid values β€” they represent "user explicitly cleared the field". The itemContext key is omitted from the output entirely only when the merged map is empty.
  • JSONL upload β€” the same itemContext shape is accepted on the inbound side. Use the itemContext mapping in name2id.json to translate human-readable slot names to ids when authoring upload payloads.

Explore Keys

The tool automatically publishes four top-level summary values on every item β€” instance_count, comment_state, class_list, and valid β€” surfaced to the SuperAnnotate Explore view so you can search, filter, and sort items by their annotation state. They are computed for you and written alongside the item's annotation data; there is nothing to configure.

KeyTypeWhat it captures
instance_countNumberTotal number of annotation instances in the item. Tags are not counted. It is 0 for an item with no annotations.
comment_stateStringThe combined comment status across every row (instances and tags): "Unresolved" if any comment thread is unresolved; otherwise "Resolved" if there is at least one comment and all are resolved; otherwise "None" when there are no comments at all.
class_listString arrayThe sorted, de-duplicated list of class names that have at least one instance in the item (based on instances, not tags). A class appears once no matter how many instances it has, and drops off when its last instance is removed. Deleted / unknown classes are omitted.
validStringA completeness gate for the current user: "True" when every required property they can edit has been filled, or "" (empty) when at least one is still missing. Covers required properties on both instances and tags.
No setup required. These keys are registered and computed by the tool itself β€” you don't add them in the Explore key configuration, they appear automatically. They are calculated the moment an item opens and kept up to date as you work (creating or deleting instances, changing classes, editing comments, filling required properties, undo / redo, and so on), then written on the next save.

A few details worth knowing:

  • valid gates submission. It is registered as a required Explore key, so the platform blocks an item's status change by non-Admin users until the value is truthy ("True"). An empty value ("") prevents submission.
  • valid is per-user / per-role. It reflects what the current user can see and edit β€” properties on hidden or view-only classes, or rows hidden by isolation rules, never count against them. Because required fields can differ by role, the same item can read "True" for an annotator and "" for a reviewer who has additional required fields to fill.
  • Opening an item is non-destructive. Simply viewing an item does not create an unsaved change. The one exception is a safety case: if an item was stored as "True" but is no longer complete for the user who just opened it, valid is corrected to "" and saved immediately, so an incomplete item can't be submitted by mistake.
Time-based properties & valid. A required time-based property counts as complete only when it has a starting value and is never cleared at any keyframe within the instance's visible range β€” a blank gap anywhere in that range leaves the item incomplete. Emptiness outside the visible range never counts against valid (the property isn't editable there). This whole-range check is what drives valid and the annotation panel's required indicator; the per-frame red outline in the property modal and table still reflects the value at the current frame only.

Auto-Save

Users should never lose work. The auto-save system runs on two tiers:

  • Debounced local save β€” annotation actions (draw, resize, keyframe edit, property change, comment, relationship, tag) coalesce and persist to the in-tool data layer ~1 s after the last change. Rapid edits collapse into a single save. Uploading a video also marks the item dirty so its bytes aren't lost on an early reload.
  • Server auto-save (60 s interval) β€” while the item has unsaved changes, the editor pushes to the SuperAnnotate server every 60 seconds in the background.

There is no manual Save button on the main editor toolbar β€” auto-save handles persistence. (A "Save & Close" button exists inside the Rich Text Modal for property values.) See Auto-Save Timing for browser-close guidance.

Solutions

The tool's value isn't a feature list β€” it's how features combine to solve real video annotation challenges end-to-end. Each solution below walks through a common workflow: the goal, the configuration, and the step-by-step flow, with links to every relevant part of the tool. Adapt the class names, tags, and prompts to your domain and you have a production-ready pipeline.


Video Bounding-Box Tracking Workflow

Goal: Track an object across a video clip with a moving bounding box and a class label, suitable for object-tracking model training.

Configuration

  • Access control: admins, annotators, reviewers; isolation set to By User with admins / reviewers in the bypass list.
  • Classes: per-object classes of type Box β€” e.g. Person, Vehicle, Animal.
  • Properties: a Single Select Visibility (Full / Partial / Occluded), Numeric Confidence, and a Free Text ID if multiple instances of the same class need to be distinguished.

Workflow

  1. Admin uploads the dataset to the project at the SuperAnnotate platform level as JSONL (with uploadedFile entries or URL-linked clips).
  2. Annotator opens the item; the video appears with the Frame Panel timeline below it.
  3. They scrub to the first frame where the object is visible, pick the class (the Box tool auto-selects), and drag a rectangle on the video frame.
  4. They scrub forward to a frame where the object has moved, select the same box, and drag it to a new position β€” a keyframe is created and the box interpolates between keyframes.
  5. Repeat at each "kink" in the trajectory; the box smoothly tracks the object across the clip. Trim the instance's visible range to the frames where the object is present.
  6. Use Video Adjustments to dial Brightness / Contrast for hard-to-see footage and turn down Shape Opacity when overlapping annotations obscure the frame.
  7. Switch to Table View to sort by start time and verify each box has a complete track and visibility property.
  8. Export β€” each Box annotation carries its box rect plus a keyframes array of (time, rect) pairs. Cuboid annotations carry a cuboid eight-point shape plus an optional cuboidKeyframes array.

Keypoint / Pose Tracking Workflow

Goal: Track an articulated subject (a person, an animal, a machine) across a clip using a skeleton of named joints, suitable for pose-estimation model training.

Configuration

  • Classes: a Keypoint class per subject type β€” e.g. Person. Open Edit Skeleton and define the joints (head, shoulders, elbows, wrists, hips, knees, ankles…) and the bones connecting them.
  • Properties: a Single Select Visibility, a Free Text ID, and any task-specific attributes.

Workflow

  1. Annotator opens the item and scrubs to the first frame where the subject is visible.
  2. They pick the Keypoint class (the Keypoint tool auto-selects) and place each joint in turn, using . to skip joints that are out of frame or occluded. When the last joint is placed, the tool switches to Select and the instance is selected.
  3. They scrub forward and reposition joints (drag an individual joint, or grab the move handle to shift the whole skeleton) β€” each move writes a keyframe and the pose interpolates between keyframes, per point.
  4. If a joint becomes occluded part-way through, edit the skeleton at that frame and remove the joint β€” it forward-fills from its last keyframe up to that point, then drops out until re-introduced.
  5. Trim the instance's visible range to the frames where the subject is present.
  6. Export β€” each Keypoint annotation carries its keypoints array plus a keypointKeyframes array of (time, points) snapshots.

Tips & Limitations

Small tricks that compound across thousands of annotations, plus the edges of the tool you should know before rolling out a large project.

Efficiency Tips

Class Shortcuts (1–9)

The first nine classes in your project bind to 1–9. With hundreds of annotations to draw per session, keyboard shortcuts save real minutes β€” and because picking a class auto-selects its matching tool (Segment / Box / Cuboid / Keypoint), pressing the digit before each draw is the fastest possible flow. Put the nine most-used classes first in configuration and train the muscle memory.

Tool Shortcuts (S / G / B / D / K)

Even though picking a class auto-selects a tool, you can switch tools manually with S (Select), G (Segment), B (Box), Shift+B (Rotated Box), D (Cuboid), K (Keypoint). S in particular is worth memorising β€” drop into Select mode to inspect / move existing annotations without accidentally drawing new ones.

Fast Seeking

Sub-frame precision matters for tight keyframes. The seek shortcuts skip dropdown-hunting:

  • Space β€” play / pause.
  • , / . β€” seek 3 s back / forward (these become joint navigation while drawing / editing a skeleton).
  • < / > β€” seek 10 s back / forward.
  • Alt+, / Alt+. β€” step one frame back / forward in the Frame Panel.
  • M β€” mute / unmute.
  • Tab / Shift+Tab β€” jump to the next / previous annotation.

Every shortcut on this list works in Split View as well β€” they target the card you most recently played, paused, seeked, muted, or selected from the panel.

Filtering & Grouping

Reviewing 500 annotations in an unsorted list is impractical. The annotation panel filtering, grouping, and ordering controls turn QA from random browsing into structured inspection.

  • Group By β€” Video Name (multi-file default), Class Name, or Tool Type.
  • Order By β€” JSON Export, Class Name, Tool Type, Start Time, Created By, Creator Role, or Created At.
  • Class filter β€” narrow to one class at a time.
  • Property filter β€” filter by configured property values.
  • Table View + column sort / filters β€” fastest way to catch outliers.

Tags vs Properties

Both store structured metadata β€” the question is scope:

  • Item-level tags describe the whole item. Use for dataset partition, source, capture session.
  • Video-level tags describe a single video file. Use for per-file quality, camera, environment.
  • Properties describe a single annotation. Use for instance-level attributes (label, confidence, visibility).

If you find yourself wanting a property on every annotation in a video file, it probably belongs as a video-level tag instead.

Auto-Save Timing

Auto-save debounces to the local data layer ~1 second after annotation actions; the server push runs on a 60-second interval whenever unsaved changes exist. There's no manual Save button on the main toolbar, so wait a couple of seconds after your last edit before closing the tab to ensure the local layer has captured your work β€” and ideally wait for the next 60-second server push cycle for full server-side persistence.


Limitations

Browser Compatibility

Best in Chrome and Edge (Chromium), where the video decode and frame-stepping paths are most reliable. Safari and Firefox are supported with minor rendering differences (especially around video overlay positioning and frame-accurate seeking).

Multi-File Cap

An item supports up to 10 video files (MAX_VIDEO_FILES = 10). Additional in-editor uploads beyond that limit are rejected. If imported item data contains more than 10 video files, the editor does not open a partial item: it shows an unsupported-item message and leaves the stored data unchanged. Reduce the source item to the supported limit before opening it here. If your workflow regularly hits this cap, split sessions into separate items rather than packing everything in one.

Gemini Inline-Data Limit

Gemini's inline_data path used for AI calls has a request-size ceiling around 20 MB; the editor enforces a safer ~12 MB per call to leave room for base64 bloat and JSON wrapping. Calls over this cap fail upfront with a clear error message. Mitigations:

  • Keep AI payloads small for Gemini-routed projects.
  • Switch to an OpenAI proxy β€” it accepts larger uploads.

API Rate Limits

AI autofill calls are routed through your AI proxy, and the underlying provider (OpenAI or Gemini) enforces its own rate limits. Running autofill on hundreds of annotations back-to-back will eventually hit those limits β€” the tool surfaces the upstream error inline. Mitigations:

  • Fill properties in batches and pause briefly between batches.
  • Check quota in SuperAnnotate β†’ Team Settings β†’ Security β†’ Proxies.
  • Switch to a higher-tier key if you routinely hit limits.

Cross-Type Class Changes

Reclassifying an annotation only allows the new class to share the same tool type as the old one β€” a Box can become another Box but not a Cuboid (or vice versa), since the underlying data shape is different. To convert across types, delete the original annotation and redraw it under the new class. If a class is deleted or its tool type is changed in configuration, existing instances become Unknown until reclassified.