def export_to_scale(
    sample_collection,
    json_path,
    video_labels_dir=None,
    video_events_dir=None,
    video_playback=False,
    label_field=None,
    frame_labels_field=None,
    progress=None,
):
    """Exports labels from the FiftyOne samples to Scale AI format.

    This function is useful for generating pre-annotations that can be provided
    to Scale AI via the ``hypothesis`` parameter of the following endpoints:

    -   `General Image Annotation <https://docs.scale.com/reference/general-image-annotation>`_
    -   `General Video Annotation <https://docs.scale.com/reference/general-video-annotation>`_
    -   `Video Playback <https://docs.scale.com/reference/video-playback>`_

    The output ``json_path`` will be a JSON file in the following format::

        {
            <sample-id1>: {
                "filepath": <filepath1>,
                "hypothesis": {...}
            },
            <sample-id2>: {
                "filepath": <filepath2>,
                "hypothesis": {...}
            },
            ...
        }

    The format of the ``hypothesis`` field depends on the label type:

    -   Sample-level classifications, detections, polylines, polygons, and
        keypoints::

            {
                "annotations": [...],
                "global_attributes": {...}
            }

    -   Video samples::

            {
                "annotations": {
                    "url": <filepath>
                }
            }

    When exporting labels for video datasets, the ``url`` field will contain
    the paths on disk to per-sample JSON files that are written to
    ``video_labels_dir`` as follows::

        video_labels_dir/
            <sample-id1>.json
            <sample-id2>.json
            ...

    When ``video_playback == False``, the per-sample JSON files are written in
    `General Video Annotation format <https://docs.scale.com/reference/general-video-annotation>`_::

        [
            {
                "annotations": [...],
                "global_attributes": {...}
            },
            {
                "annotations": [...],
                "global_attributes": {...}
            },
            ...
        ]

    where the n-th element in the list contains the labels for the n-th frame
    of the video.

    When ``video_playback == True``, the per-sample JSON files are written in
    `Video Playback format <https://docs.scale.com/reference/video-playback>`_::

        {
            "annotations": {...}
        }

    When exporting labels for videos and the ``video_events_dir`` parameter is
    provided, the ``hypothesis`` fields of the JSON written to ``json_path``
    will include an ``events`` field::

        {
            "annotations": {
                "url": <filepath>
            },
            "events": {
                "url": <filepath>
            }
        }

    whose ``url`` field will contain the paths on disk to per-sample JSON files
    that are written to ``video_events_dir`` as follows::

        video_events_dir/
            <sample-id1>.json
            <sample-id2>.json
            ...

    where each per-sample JSON file contains the
    `events in the video <https://docs.scale.com/reference/events>`_::

        {
            "events": [...]
        }

    Args:
        sample_collection: a
            :class:`fiftyone.core.collections.SampleCollection`
        json_path: the path to write the JSON export
        video_labels_dir (None): a directory to write the per-sample video
            labels. Only applicable for video datasets
        video_events_dir (None): a directory to write the per-sample video
            events. Only applicable for video datasets
        video_playback (False): whether to export video labels in a suitable
            format for use with the
            `Video Playback <https://docs.scale.com/reference/video-playback>`_ task.
            By default, video labels are exported for in a suitable format for
            the `General Video Annotation <https://docs.scale.com/reference/general-video-annotation>`_
            task. Only applicable for video datasets
        label_field (None): optional label field(s) to export. Can be any of
            the following:

            -   the name of a label field to export
            -   a glob pattern of label field(s) to export
            -   a list or tuple of label field(s) to export
            -   a dictionary mapping label field names to keys to use when
                constructing the exported labels

            By default, no labels are exported
        frame_labels_field (None): optional frame label field(s) to export.
            Only applicable to video datasets. Can be any of the following:

            -   the name of a frame label field to export
            -   a glob pattern of frame label field(s) to export
            -   a list or tuple of frame label field(s) to export
            -   a dictionary mapping frame label field names to keys to use
                when constructing the exported frame labels

            By default, no frame labels are exported
        progress (None): whether to render a progress bar (True/False), use the
            default value ``fiftyone.config.show_progress_bars`` (None), or a
            progress callback function to invoke instead
    """
    fov.validate_collection(
        sample_collection, media_type=(fomm.IMAGE, fomm.VIDEO)
    )
    is_video = sample_collection.media_type == fomm.VIDEO

    # Get label fields to export
    label_fields = sample_collection._parse_label_field(
        label_field,
        allow_coercion=False,
        force_dict=True,
        required=False,
    )

    # Get frame label fields to export
    if is_video:
        frame_label_fields = sample_collection._parse_frame_labels_field(
            frame_labels_field,
            allow_coercion=False,
            required=False,
            force_dict=True,
        )

        if frame_label_fields and (
            video_labels_dir is None and video_events_dir is None
        ):
            raise ValueError(
                "Must provide `video_labels_dir` and/or `video_events_dir` "
                "when exporting labels for video datasets"
            )

    sample_collection.compute_metadata()

    # Export the labels
    labels = {}
    anno_dict = {}
    for sample in sample_collection.iter_samples(progress=progress):
        metadata = sample.metadata

        # Get frame size
        if is_video:
            frame_size = (metadata.frame_width, metadata.frame_height)
        else:
            frame_size = (metadata.width, metadata.height)

        # Export sample-level labels
        if label_fields:
            labels_dict = _get_labels(sample, label_fields)
            anno_dict = _to_scale_image_labels(labels_dict, frame_size)

        # Export frame-level labels
        if is_video and frame_label_fields:
            frames = _get_frame_labels(sample, frame_label_fields)
            make_events = video_events_dir is not None
            if video_playback:
                annotations, events = _to_scale_video_playback_labels(
                    frames, frame_size, make_events=make_events
                )
            else:
                annotations, events = _to_scale_video_annotation_labels(
                    frames, frame_size, make_events=make_events
                )

            # Write annotations
            if video_labels_dir:
                anno_path = os.path.join(video_labels_dir, sample.id + ".json")
                etas.write_json(annotations, anno_path)
                anno_dict["annotations"] = {"url": anno_path}

            # Write events
            if video_events_dir:
                events_path = os.path.join(
                    video_events_dir, sample.id + ".json"
                )
                etas.write_json(events, events_path)
                anno_dict["events"] = {"url": events_path}

        labels[sample.id] = {
            "filepath": sample.filepath,
            "hypothesis": anno_dict,
        }

    etas.write_json(labels, json_path)
Exports labels from the FiftyOne samples to Scale AI format.

    This function is useful for generating pre-annotations that can be provided
    to Scale AI via the ``hypothesis`` parameter of the following endpoints:

    -   `General Image Annotation <https://docs.scale.com/reference/general-image-annotation>`_
    -   `General Video Annotation <https://docs.scale.com/reference/general-video-annotation>`_
    -   `Video Playback <https://docs.scale.com/reference/video-playback>`_

    The output ``json_path`` will be a JSON file in the following format::

        {
            <sample-id1>: {
                "filepath": <filepath1>,
                "hypothesis": {...}
            },
            <sample-id2>: {
                "filepath": <filepath2>,
                "hypothesis": {...}
            },
            ...
        }

    The format of the ``hypothesis`` field depends on the label type:

    -   Sample-level classifications, detections, polylines, polygons, and
        keypoints::

            {
                "annotations": [...],
                "global_attributes": {...}
            }

    -   Video samples::

            {
                "annotations": {
                    "url": <filepath>
                }
            }

    When exporting labels for video datasets, the ``url`` field will contain
    the paths on disk to per-sample JSON files that are written to
    ``video_labels_dir`` as follows::

        video_labels_dir/
            <sample-id1>.json
            <sample-id2>.json
            ...

    When ``video_playback == False``, the per-sample JSON files are written in
    `General Video Annotation format <https://docs.scale.com/reference/general-video-annotation>`_::

        [
            {
                "annotations": [...],
                "global_attributes": {...}
            },
            {
                "annotations": [...],
                "global_attributes": {...}
            },
            ...
        ]

    where the n-th element in the list contains the labels for the n-th frame
    of the video.

    When ``video_playback == True``, the per-sample JSON files are written in
    `Video Playback format <https://docs.scale.com/reference/video-playback>`_::

        {
            "annotations": {...}
        }

    When exporting labels for videos and the ``video_events_dir`` parameter is
    provided, the ``hypothesis`` fields of the JSON written to ``json_path``
    will include an ``events`` field::

        {
            "annotations": {
                "url": <filepath>
            },
            "events": {
                "url": <filepath>
            }
        }

    whose ``url`` field will contain the paths on disk to per-sample JSON files
    that are written to ``video_events_dir`` as follows::

        video_events_dir/
            <sample-id1>.json
            <sample-id2>.json
            ...

    where each per-sample JSON file contains the
    `events in the video <https://docs.scale.com/reference/events>`_::

        {
            "events": [...]
        }

    Args:
        sample_collection: a
            :class:`fiftyone.core.collections.SampleCollection`
        json_path: the path to write the JSON export
        video_labels_dir (None): a directory to write the per-sample video
            labels. Only applicable for video datasets
        video_events_dir (None): a directory to write the per-sample video
            events. Only applicable for video datasets
        video_playback (False): whether to export video labels in a suitable
            format for use with the
            `Video Playback <https://docs.scale.com/reference/video-playback>`_ task.
            By default, video labels are exported for in a suitable format for
            the `General Video Annotation <https://docs.scale.com/reference/general-video-annotation>`_
            task. Only applicable for video datasets
        label_field (None): optional label field(s) to export. Can be any of
            the following:

            -   the name of a label field to export
            -   a glob pattern of label field(s) to export
            -   a list or tuple of label field(s) to export
            -   a dictionary mapping label field names to keys to use when
                constructing the exported labels

            By default, no labels are exported
        frame_labels_field (None): optional frame label field(s) to export.
            Only applicable to video datasets. Can be any of the following:

            -   the name of a frame label field to export
            -   a glob pattern of frame label field(s) to export
            -   a list or tuple of frame label field(s) to export
            -   a dictionary mapping frame label field names to keys to use
                when constructing the exported frame labels

            By default, no frame labels are exported
        progress (None): whether to render a progress bar (True/False), use the
            default value ``fiftyone.config.show_progress_bars`` (None), or a
            progress callback function to invoke instead
    
fiftyone/utils/scale.py