# Episodes_SplitEpisodes

`POST /v1/accounts/{account}/datasets/{dataset}/episodes:split`

Splits episodes at given cuts, around kept windows or at their markers: each split is drawn on the episode's draft
(EpisodeDraft), its pieces the windows kept, each tagged with the labels
of the markers that closed it, inside the window the draft keeps (else
the episode's trim). No episode is made until a version is published
from a Publish preview. An episode whose draft draws a split already is
refused (marker cuts skip it); one another person is editing is left as
it is and reported in `locked`.

- Base URL: `https://junction-api.qualiastudios.dev`
- Authentication: an API key in the `X-API-Key` header

## Parameters

- `account` (path, string, required): The account id.
- `dataset` (path, string, required): The dataset id.

## Request body

Required: `application/json` `qualia.v1.SplitEpisodesRequest`

## Responses

- `200` OK: `application/json` `qualia.v1.SplitEpisodesResponse`
- `default` Default error response: `application/json` `google.rpc.Status`

## Schemas

```yaml
qualia.v1.SplitEpisodesRequest:
  required:
    - parent
  type: object
  properties:
    parent:
      type: string
      description: "accounts/{account}/datasets/{dataset}: must be the upload."
    cutPlan:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.SplitEpisodesRequest_CutPlan"
      description: Explicit cuts.
    markerCuts:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.SplitEpisodesRequest_MarkerCuts"
      description: Marker cuts.
    validateOnly:
      type: boolean
      description: Report the children without writing them.
  description: Request for Episodes.SplitEpisodes.
qualia.v1.SplitEpisodesRequest_CutPlan:
  type: object
  properties:
    episodes:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.SplitEpisodesRequest_Cuts"
      description: One entry per episode, at most 500.
  description: "Explicit cuts for several episodes, drawn together: all or none."
qualia.v1.SplitEpisodesRequest_Cuts:
  type: object
  properties:
    episode:
      type: string
      description: accounts/{account}/datasets/{dataset}/episodes/{episode}
    cutSeconds:
      type: array
      items:
        type: number
        format: double
      description: |-
        Cut points, seconds from the start of the recording. An episode is
        cut inside the one stretch its draft keeps, else inside its trim: its
        pieces keep only those frames, and a cut outside them places nothing.
    keepWindows:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.Episode_Trim"
      description: |-
        The windows to keep instead, seconds from the start of the
        recording, in time order and not overlapping: each becomes one child,
        and what lies outside every window is in no child. Two windows that
        touch are two children. A window may keep frames the episode's trim
        cut (kept_trimmed_frame_count says how many). Not with cut_seconds.
  description: Where to cut one episode.
qualia.v1.Episode_Trim:
  type: object
  properties:
    startSeconds:
      type: number
      description: First second kept.
      format: double
    endSeconds:
      type: number
      description: Last second kept.
      format: double
  description: The trim window, in seconds from the start of the recording.
qualia.v1.SplitEpisodesRequest_MarkerCuts:
  type: object
  properties:
    selection:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.EpisodeSelection"
      description: Episodes to cut.
    labels:
      type: array
      items:
        type: string
      description: |-
        Marker labels to cut at; empty means every marker (none when
        start_labels or end_labels is set).
    startFirstMarker:
      type: boolean
      description: Drop what comes before the first marker.
    endLastMarker:
      type: boolean
      description: Drop what comes after the last marker.
    startLabels:
      type: array
      items:
        type: string
      description: |-
        Start each episode at its first marker among these labels instead,
        dropping the lead-in. Not with start_first_marker. Without `labels`,
        nothing is cut: each episode becomes one child, its narrowed window.
    endLabels:
      type: array
      items:
        type: string
      description: |-
        End each episode at its last marker among these labels instead,
        dropping the run-out. Not with end_last_marker. Without `labels`, as
        start_labels.
  description: |-
    Cut every selected episode at its recorder markers, inside its trim
    when it is trimmed: a marker the trim cut names nothing.
qualia.v1.EpisodeSelection:
  type: object
  properties:
    names:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.EpisodeNames"
      description: Episode names under the request's parent.
    filter:
      type: string
      description: A ListEpisodes filter over the parent (e.g. what the filter bar leaves).
  description: |-
    Which episodes a bulk ruling acts on: an explicit list, or a filter. Names
    must be under the request's parent (INVALID_ARGUMENT otherwise); a filter
    only ever matches the parent's own episodes (a mixture: its pool).
qualia.v1.EpisodeNames:
  type: object
  properties:
    names:
      type: array
      items:
        type: string
      description: accounts/{account}/datasets/{dataset}/episodes/{episode}, at most 10000.
  description: A list of episode names.
qualia.v1.SplitEpisodesResponse:
  type: object
  properties:
    splits:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.SplitEpisodesResponse_Split"
      description: One per parent that was cut.
    lockedCount:
      type: integer
      description: Parents left uncut because another person holds their edit lease.
      format: int32
    locked:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.LockedEpisode"
      description: The first 100 of them, with their holders.
    skipped:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.SplitEpisodesResponse_Skipped"
      description: |-
        Marker splits left unchanged for a reason other than an edit lease.
        Includes refusals found while planning and while saving the drawing.
  description: Response for Episodes.SplitEpisodes.
qualia.v1.SplitEpisodesResponse_Split:
  type: object
  properties:
    episode:
      type: string
      description: The parent episode.
    children:
      type: array
      items:
        type: string
      description: |-
        Empty: the split is drawn on the parent's draft (`draft`), and its
        pieces are made only when a version is published from it. With
        validate_only, a name for each piece, which never exists.
    droppedLeadFrameCount:
      type: string
      description: |-
        Frames of the recording before the first child that no child keeps
        (the dropped lead-in, with what the episode's trim cut there).
    droppedTailFrameCount:
      type: string
      description: |-
        Frames of the recording after the last child that no child keeps (the
        dropped run-out, with what the episode's trim cut there).
    droppedBetweenFrameCount:
      type: string
      description: Frames between children that no child keeps (keep_windows apart).
    keptTrimmedFrameCount:
      type: string
      description: |-
        Frames the children keep that the episode's trim had cut: keep_windows
        may reach past the trim, cut_seconds and marker cuts never do. 0 for an untrimmed episode.
    draft:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.EpisodeDraft"
      description: |-
        The parent's draft, drawn with the split: the pieces it keeps, each
        an episode once a version is published from it. Unset with
        validate_only.
    pieceCount:
      type: integer
      description: How many pieces the split keeps.
      format: int32
  description: One parent and what it became.
qualia.v1.EpisodeDraft:
  required:
    - drawing
  type: object
  properties:
    name:
      type: string
      description: accounts/{account}/datasets/{dataset}/episodes/{episode}/draft
    drawing:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.EpisodeDraft_Drawing"
      description: What a version published from it holds.
    baseRevision:
      type: integer
      description: The Episode.revision the drawing began on.
      format: int32
    base:
      allOf:
        - $ref: "#/components/schemas/qualia.v1.EpisodeDraft_Drawing"
      description: |-
        The editor as read when drawing began (the take's trim and subtasks then),
        so a return can tell what moved under the drawing.
    baseSplit:
      type: string
      description: "Reserved for re-splits: the split take's pieces the drawing began on."
    state:
      readOnly: true
      enum:
        - STATE_UNSPECIFIED
        - OPEN
      type: string
      description: Always OPEN.
      format: enum
    createActor:
      readOnly: true
      allOf:
        - $ref: "#/components/schemas/qualia.v1.Actor"
      description: "Who drew it first: a person, or an API key acting for none."
    updateActor:
      readOnly: true
      allOf:
        - $ref: "#/components/schemas/qualia.v1.Actor"
      description: "Who last changed the drawing: a person, or an API key acting for none."
    createTime:
      readOnly: true
      type: string
      description: When it was first saved.
      format: date-time
    updateTime:
      readOnly: true
      type: string
      description: When it was last saved.
      format: date-time
    etag:
      type: string
      description: |-
        Changes with every save of the draft. Sent back on UpdateEpisodeDraft
        and DeleteEpisodeDraft, and as UpdateEpisodesRequest.Edit's
        `expected_draft_etag`.
  description: |-
    An edit of a take drawn and not yet in a version: one per take, read the same
    through every dataset that reads the take. It is never applied to the
    dataset: head keeps the take as recorded, and only a version made from a
    Publish preview holds the edit. Written by whoever holds the take's edit
    lease (Episode.lease), or, while no other person holds one, by any caller
    with write access, a person or an API key. It stays when its author's
    lease ends, for whoever edits the take next, and through a re-ingest of
    the take.

    Served by qds-api.
qualia.v1.EpisodeDraft_Drawing:
  type: object
  properties:
    pieces:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.EpisodeDraft_Piece"
      description: |-
        The take as pieces, in time order and not overlapping, within the
        recording; at most 512 kept. Stored end to end over the recording:
        what lies between the pieces sent is stored as dropped pieces.
    subtasks:
      type: array
      items:
        $ref: "#/components/schemas/qualia.v1.Episode_Subtask"
      description: Subtask spans, bounded as UpdateEpisodes bounds Episode.subtasks.
  description: The editor at one moment.
qualia.v1.EpisodeDraft_Piece:
  type: object
  properties:
    startSeconds:
      type: number
      description: Start, in seconds from the start of the recording.
      format: double
    endSeconds:
      type: number
      description: End, in seconds.
      format: double
    keep:
      type: boolean
      description: |-
        Whether the stretch is kept: one kept piece is a trim, two or more a
        split.
    tags:
      type: array
      items:
        type: string
      description: |-
        Tags the episode this piece becomes carries (a marker split's labels),
        beside the take's own. Kept only on a kept piece; at most 64, each
        non-empty, without surrounding whitespace, at most 1024 bytes.
  description: A stretch of the take as drawn.
qualia.v1.Episode_Subtask:
  type: object
  properties:
    startSeconds:
      type: number
      description: Start, in seconds from the start of the recording.
      format: double
    endSeconds:
      type: number
      description: End, in seconds.
      format: double
    label:
      type: string
      description: The subtask's one name (also one of the episode's tags).
    review:
      enum:
        - REVIEW_UNSPECIFIED
        - PROPOSED
        - ACCEPTED
        - REJECTED
      type: string
      description: Proposed, accepted or rejected.
      format: enum
    origin:
      enum:
        - ORIGIN_UNSPECIFIED
        - HUMAN
        - MODEL
        - HEURISTIC
      type: string
      description: Who proposed it.
      format: enum
  description: One subtask span.
qualia.v1.Actor:
  type: object
  properties:
    kind:
      readOnly: true
      enum:
        - KIND_UNSPECIFIED
        - PERSON
        - VALIDATION
        - RULE
        - MODEL
        - OPERATOR
        - SYSTEM
      type: string
      description: What kind of actor it is.
      format: enum
    user:
      readOnly: true
      type: string
      description: The person's user id when `kind` is PERSON; empty otherwise.
    displayName:
      readOnly: true
      type: string
      description: The person's display name at the time, for rendering without a lookup.
    agent:
      readOnly: true
      type: string
      description: |-
        The rule code, or for a MODEL the Qualia model tier (e.g. "qualia-vlm";
        "qualia" for any other model), when not a person.
    run:
      readOnly: true
      type: string
      description: The run a model or rule finding came from, when it has one.
    apiKey:
      readOnly: true
      type: string
      description: |-
        The API key's id when a person acted through one; empty for a session.
        Never the key itself.
    attribution:
      readOnly: true
      allOf:
        - $ref: "#/components/schemas/qualia.v1.Attribution"
      description: |-
        Signed identity evidence recorded with the change, kept apart from the
        principal above. Unset on older records and wherever none was signed.
  description: Who did something. Every decision, issue and reply names one.
qualia.v1.Attribution:
  type: object
  properties:
    authentication:
      readOnly: true
      enum:
        - AUTHENTICATION_UNSPECIFIED
        - SESSION
        - API_KEY
        - SERVICE
      type: string
      description: How the principal authenticated.
      format: enum
    initiator:
      readOnly: true
      type: string
      description: |-
        The user id of a person verified as starting the work: the person of a
        session, or the person a trusted service's signed job record names.
        Empty when nobody was verified.
    initiatorDisplayName:
      readOnly: true
      type: string
      description: The initiator's display name at the time, never their email.
    credentialCreator:
      readOnly: true
      type: string
      description: The user id of the key's creator at the time. Not who used the key.
    credentialOwner:
      readOnly: true
      enum:
        - CREDENTIAL_OWNER_UNSPECIFIED
        - PERSON
        - SPACE
      type: string
      description: Who owned the key at the time.
      format: enum
    credentialOwnerSpace:
      readOnly: true
      type: string
      description: |-
        The owning space's id (a workspace or the organization) when
        `credential_owner` is SPACE.
  description: |-
    How a change was authenticated and who verifiably started it.
    Only the trusted mesh signs it. It never authorizes anything, and a key's
    creator or owner is never the person who used the key.
qualia.v1.LockedEpisode:
  type: object
  properties:
    episode:
      type: string
      description: |-
        accounts/{account}/datasets/{dataset}/episodes/{episode}, in the scope
        the write was made in.
    holderName:
      type: string
      description: The holder's display name; empty when they have none.
  description: |-
    An episode a write left alone, or refused, because another person holds
    its edit lease (Episodes.AcquireEpisodeLease). Bulk responses list at most
    100 of these beside a count of all of them.
qualia.v1.SplitEpisodesResponse_Skipped:
  type: object
  properties:
    episode:
      type: string
      description: The parent episode left unchanged.
    reason:
      type: string
      description: Why no split was drawn, including an already drawn split or no marker.
  description: A marker split that could not be drawn. Other selected takes proceed.
google.rpc.Status:
  oneOf:
    - $ref: "#/components/schemas/ApiError"
    - $ref: "#/components/schemas/GatewayError"
  description: "The body of a failed call: one of the two shapes below."
ApiError:
  title: API error
  type: object
  required:
    - code
    - message
    - retryable
    - details
  properties:
    code:
      type: string
      description: The gRPC code name in upper case, e.g. `NOT_FOUND`.
    message:
      type: string
    retryable:
      type: boolean
      description: Whether the same call may succeed if retried.
    details:
      type: array
      items:
        type: object
      description: "Empty, except when a dataset copy or move is refused: then one `google.rpc.ErrorInfo` with the refusal's `reason` code, its `domain` and, in `metadata`, the datasets it names."
  description: A refusal from the API itself.
GatewayError:
  title: Gateway error
  type: object
  required:
    - detail
  properties:
    detail:
      type: string
      description: What went wrong.
  description: A refusal from the gateway before the call reaches the API, for example `401` bad or missing API key, `403` key lacks the scope or environment closed, `413` body too large.
```
