Repository: voxel51/fiftyone

Issue:
[FR] Allow CVAT task assignee to be a list for video tasks
When uploading video samples to CVAT, every video is loaded into a new task. The current `task_assignee` argument of the CVAT `annotate()` method only accepts a single username that is then applied to every video task. It should be possible to provide a list of usernames that will be applied like the `job_assignees` argument to sequential video tasks. 

```python
import fiftyone as fo
import fiftyone.zoo as foz

dataset = foz.load_zoo_dataset("quickstart-video", max_samples=3)

results = dataset.annotate(
    "video",
    label_field="frames.detections",
    task_assignee=["user1", "user2", "user3"],
    launch_editor=True,
)
```

Images are all loaded into a single task so this functionality would be irrelevant.


Discussion:

Resolving patch:
diff --git a/fiftyone/utils/cvat.py b/fiftyone/utils/cvat.py
--- a/fiftyone/utils/cvat.py
+++ b/fiftyone/utils/cvat.py
@@ -2435,7 +2435,9 @@ class CVATBackendConfig(foua.AnnotationBackendConfig):
             result in reduced video quality in CVAT due to size limitations on
             ZIP files that can be uploaded to CVAT
         chunk_size (None): the number of frames to upload per ZIP chunk
-        task_assignee (None): the username to which the task(s) were assigned
+        task_assignee (None): the username(s) to which the task(s) were
+            assigned. This argument can be a list of usernames when annotating
+            videos as each video is uploaded to a separate task 
         job_assignees (None): a list of usernames to which jobs were assigned
         job_reviewers (None): a list of usernames to which job reviews were
             assigned
@@ -3263,6 +3265,7 @@ def upload_samples(self, samples, backend):
 
                 current_job_assignees = job_assignees
                 current_job_reviewers = job_reviewers
+                current_task_assignee = task_assignee
                 if is_video:
                     # Videos are uploaded in multiple tasks with 1 job per task
                     # Assign the correct users for the current task
@@ -3278,6 +3281,15 @@ def upload_samples(self, samples, backend):
                             job_reviewers[job_reviewer_ind]
                         ]
 
+                if task_assignee is not None:
+                    if isinstance(task_assignee, str):
+                        current_task_assignee = task_assignee
+                    else:
+                        task_assignee_ind = idx % len(task_assignee)
+                        current_task_assignee = task_assignee[
+                            task_assignee_ind
+                        ]
+
                 task_name = "FiftyOne_%s_%s" % (
                     samples_batch._root_dataset.name.replace(" ", "_"),
                     label_field.replace(" ", "_"),
@@ -3289,7 +3301,7 @@ def upload_samples(self, samples, backend):
                     schema=cvat_schema,
                     segment_size=segment_size,
                     image_quality=image_quality,
-                    task_assignee=task_assignee,
+                    task_assignee=current_task_assignee,
                 )
                 task_ids.append(task_id)
                 labels_task_map[label_field].append(task_id)


Test patch: