Skip to content

[ar-api] Add CLI video segment annotation (VID-59) - #544

Closed
digaobarbosa wants to merge 5 commits into
bc/VID-53from
bc/VID-59
Closed

digaobarbosa wants to merge 5 commits into
bc/VID-53from
bc/VID-59

Conversation

@digaobarbosa

@digaobarbosa digaobarbosa commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Action Recognition users can upload a native video from the CLI, but they could not submit its segment labels there. They had to switch to Python for the last step.

roboflow video annotate reads one complete video-coco document and sends it unchanged to the video ID that video upload reported. Native frame indices, uneven timestamps and the rational time base stay exactly as written. Users can pick a Dataset split, request --overwrite, and turn Dataset membership on or off. Without a membership flag, the API default applies: the video is added.

A conflicting save tells the user to re-run with --overwrite. An unknown video exits 3, and a rejected API key exits 2. The file is read as UTF-8 on every platform, so non-ASCII class names stay intact on Windows.

Stack and dependency

This draft targets bc/VID-53 / PR #541, which targets the SDK dependency PR #534. Merge #534 and #541 first. This PR includes #541's latest fixes through merge commits.

Verification

At head bb80ce8 (macOS, Python 3.12):

  1. Full unit suite: 1,147 tests pass, one skipped. 32 video CLI tests run through public command dispatch; the annotate tests cover each exit code (409, 400, 404, 401, network failure) and the file errors (malformed, non-object, missing, non-UTF-8) in table form. ruff check, ruff format --check and mypy roboflow pass.
  2. Staging E2E: 24/24 passed against api.roboflow.one / model-evaluation-workspace with the installed CLI. That is 9 upload/status cases from [ar-api] Add native video upload and ingestion status to CLI (VID-53) #541 and 15 annotate cases. Segments were read back through the SDK. The run used its own private Action Recognition project, then moved it to Trash and confirmed it was gone.
  3. CI: pre-commit.ci and both Socket Security checks pass. .github/workflows/test.yml runs its Python/Windows matrix only for PRs into main, so it does not run here.
Staging E2E results — annotate (head bb80ce8, 2026-10-05; also 24/24 at 2508af6)

RF="roboflow --json -k $KEY -w model-evaluation-workspace". A and B are fresh Sources from byte-unique stream copies of real 24 fps clips (time base 1/12288). The documents are real roboflow-video-coco exports.

# Case Command Exit Result
1 Help roboflow video annotate --help 0 PASS: lists -a -i -p, --add-to-dataset/--no-add-to-dataset, --overwrite, -s
2 Default annotate $RF video annotate -a a.json -i <A> -p $P 0 PASS: {"success": true, "inDataset": true, "createdClasses": ["hook", "punch"]}
3 Identical re-submit same 0 PASS: createdClasses: [], no --overwrite needed
4 Conflict $RF video annotate -a a_conflict.json -i <A> -p $P 1 PASS: server says already has annotations; hint Re-run with --overwrite
5 Conflict with overwrite … --overwrite 0 PASS
6 Text mode roboflow -k $KEY … video annotate … 0 PASS: Annotated video <A>. / In dataset: yes
7 Opt out of Dataset $RF video annotate -a b.json -i <B> -p $P --no-add-to-dataset 0 PASS: inDataset: false
8 Opt in with split … --add-to-dataset -s valid 0 PASS: inDataset: true
9 SDK readback project.image(<A>), project.image(<B>) 0 PASS: A keeps the overwritten coco-1 (frames 2–14, end PTS 7680, exact native PTS); B is valid with 2 segments
10 Unknown video ID … -i doesnotexist123 3 PASS: Video not found; hint names roboflow video upload
11 Zero segments … -a a_empty.json 1 PASS: The roboflow-video-coco document has no segments
12 Malformed JSON … -a bad.json 1 PASS: Invalid JSON …
13 Missing file … -a nope.json 1 PASS: Cannot read annotation file
14 Unknown project … -p no-such-project-xyz 3 PASS
15 Rejected API key roboflow --json -k bogus … video annotate … 2 PASS: This API key does not exist (exited 3 before this head)

The upload/status cases U1–U9 match the table in #541 and passed at this head too.

Notes

  1. Segments are stored on the Source. A re-upload of known bytes returns duplicate: true and links the existing Source into the new project. Annotating that Source changes every project that holds it. An early E2E pass overwrote one segment of a shared staging project this way. It was restored from the original export and verified, and the E2E now refuses deduplicated uploads.
  2. --no-add-to-dataset only skips adding. It does not remove a video that is already in the Dataset.
  3. An unknown project shows the server's generic --help hint. The shared output_error lets a server hint win for every command, so it is out of scope here.

🤖 Generated with Claude Code

digaobarbosa and others added 4 commits October 5, 2026 15:15
…(VID-59)

Route annotate rejections through output_api_error so a rejected key exits 2,
and give the video-coco hint only to 400s instead of transport failures.
Fold the annotate CLI tests into table-driven cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without an explicit encoding, Windows decodes the file with its locale
codepage and silently corrupts non-ASCII class names. A file in another
encoding (e.g. UTF-16 from PowerShell redirection) now gets an actionable hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@digaobarbosa digaobarbosa added the LGTJarb Approved by Jarbas Local label Oct 5, 2026
@iurisilvio
iurisilvio deleted the branch bc/VID-53 October 7, 2026 13:52
@iurisilvio iurisilvio closed this Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTJarb Approved by Jarbas Local

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants