---
title: "Get Multiple Frame"
method: GET
path: "/v1/videos/{video_id}/frames"
tags: ["Video Emotion API"]
---

# Get Multiple Frame

`GET /v1/videos/{video_id}/frames`

## Request

- Base URL: `https://api.imentiv.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.imentiv.ai/v1/videos/{video_id}/frames`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer
  - OAuth 2
    - Authorization code: `https://api.imentiv.ai/oauth/authorize`
    - Token URL: `https://api.imentiv.ai/oauth/token` scopes: `media.read`

Per-frame face detections.

Per-face emotion scores are on `processed_frames[].faces[].emotions`. Each face also carries
`valence`, `arousal` and `intensity` computed from those scores, so you do not need one
valence/arousal request per face per frame. They equal what
`GET /videos/{video_id}/frames/{frame_id}/valence_arousal?face_id=` returns for that face.
The top-level `circumplex_version` names the coordinate table behind them.

To reproduce the clip-wide `GET /videos/{video_id}/valence_arousal` result from this list, average
`valence` and `arousal` over the faces first, then take the length of that averaged vector; averaging the
per-face `intensity` values gives a different number (the average per-face intensity). This only holds for
the full, unfiltered listing (every frame, no `face_ids`): a window (`start_frame`/`length`) or a face
subset has a different set of faces to average over, so its mean is not the clip figure.

## Path parameters

- `video_id` string, required: The unique video ID of the video for which the frames to be fetched

## Query parameters

- `start_frame` string, nullable: Frame number to start from (inclusive). Defaults to the start of the video.
- `length` string, nullable: Number of frames to return from start_frame. Omit (or 0) for every stored frame. Page long videos: each frame also carries image URLs.
- `face_ids` string: Optional comma-separated list of face IDs (e.g., '1,2,3')

## Response `200`

Successful Response

- MultipleFramesResponse: Frames list. Per-face scores: processed_frames[].faces[].emotions.
  - `processed_frames` FramesResponse[], required
    - `original_frame_image` string, nullable
    - `frame_image` string, nullable: Deprecated: always null. Per-frame thumbnails are no longer produced.
    - `found_faces` integer[], nullable
    - `timestamp` integer, nullable
    - `faces` BoundingBox[], nullable
      - `face_id` integer, required: Detected face identifier.
      - `box` integer[], required: Bounding box as [x, y, width, height].
      - `emotions` object, required: Per-face emotion probability map. Typical keys: angry, contempt, disgust, fear, happy, neutral, sad, surprise. The map may be partial (a single {"sad": 0.9} is valid); missing keys are omitted, not zero-filled. Scores are model intensities in [0, 1].
      - `note` string, nullable
      - `face_analysis` FaceAnalysis: Per-face gaze / eye / lip / head-pose / brow / liveness signals from temporal analysis. Every named field is optional: the producer omits what it could not compute, and a face that never went through temporal analysis carries no ``face_analysis`` key at all. Blink rate and the eye-tracking heatmap are not stored — derive rate from ``blink`` onsets over time, and the heatmap from ``gaze_yaw`` × ``gaze_pitch``.
        - `gaze_yaw` number, nullable: Horizontal gaze in degrees. 0 = camera; negative = left; positive = right.
        - `gaze_pitch` number, nullable: Vertical gaze in degrees. 0 = level; negative = down; positive = up.
        - `eye_openness` number, nullable: Eye openness in [0, 1].
        - `blink` boolean, nullable: True when the eyes are closed on this frame.
        - `fixation_id` integer, nullable: Fixation identifier; the same id spans consecutive frames of one fixation.
        - `liveness` string, nullable: Liveness label, e.g. 'live'.
        - `lip_openness` number, nullable: Mouth aspect ratio / lip openness in [0, 1].
        - `lip_state` string, nullable: Lip state: idle, speaking, or yawning.
        - `head_yaw` number, nullable: Head yaw in degrees. 0 = facing the camera; negative = turned left.
        - `head_pitch` number, nullable: Head pitch in degrees. Negative = head down. What 0 means depends on where the camera sits, so judge it against the same person's usual, not an absolute angle.
        - `head_roll` number, nullable: Head roll (tilt toward a shoulder) in degrees.
        - `brow_eye_ratio` number, nullable: Brow-to-eye distance over the inter-ocular distance (a proxy for brow lowering). Lower = a lowered brow. Absent when the face is too small or turned too far.
        - `brow_furrow_ratio` number, nullable: Distance between the inner brow points over the inter-ocular distance. Lower = more furrowed. Absent under the same conditions as brow_eye_ratio.
        - `brow_source` string, nullable: Landmark model the brow ratios were measured with. Ratios from different sources are not comparable.
      - `valence` number, required: Valence of this face on this frame, -1 (negative) to 1 (positive): the sum of each emotion score times that emotion's valence coordinate. The scores are used as given (not renormalised); an emotion with no coordinate counts as 0. Computed from `emotions`, so it always agrees with them. Recomputing it yourself from the coordinate table agrees up to floating-point rounding.
      - `arousal` number, required: Arousal of this face on this frame, -1 (calm) to 1 (energetic): the sum of each emotion score times that emotion's arousal coordinate. Same conventions as `valence`.
      - `intensity` number, required: Length of this face's (valence, arousal) vector on this frame: how far from neutral it reads. Not additive across faces or frames: to summarise several, average `valence` and `arousal` first and take the length of the averaged vector (opposite expressions cancel); averaging `intensity` values instead gives the average per-face intensity, a different number.
    - `frame_id` integer, nullable
    - `note` string, nullable
  - `circumplex_version` string: Name of the valence/arousal coordinate table the numbers were computed with: each emotion label sits at a fixed (valence, arousal) point and a face's values are the score-weighted sum of those points. It reflects the table in use now, not the one in use when the video was analysed, and it changes only when the table does. Applies to every face's `valence`, `arousal` and `intensity`.

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-31** `bd825cd86e8c`: 10 info
  - added the optional property `circumplex_version` to the response with the `200` status
  - added the optional property `processed_frames/items/faces/anyOf[subschema #1]/items/face_analysis/anyOf[subschema #1: FaceAnalysis]/brow_eye_ratio` to the response with the `200` status
  - added the optional property `processed_frames/items/faces/anyOf[subschema #1]/items/face_analysis/anyOf[subschema #1: FaceAnalysis]/brow_furrow_ratio` to the response with the `200` status
  - added the optional property `processed_frames/items/faces/anyOf[subschema #1]/items/face_analysis/anyOf[subschema #1: FaceAnalysis]/brow_source` to the response with the `200` status
  - …6 more
- **2026-09-22** `536bf48bb9fb`: 3 info
  - the endpoint scheme security `ApiKeyAuth` was added to the API
  - the endpoint scheme security `BearerAuth` was added to the API
  - the endpoint scheme security `OAuth2Delegated` was added to the API
- …earlier changes not shown

[Operation history](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/changes/v1/videos/:video_id/frames/get.md)

---

[API](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai.md) - [All operations](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/llms.txt) - [OpenAPI document](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/revisions/bc15cec7e794?raw)
