Skip to content

Frame State Filter

Filter intervals by per-frame player state thresholds. Find moments where players meet specific physical criteria — sprinting, pressing close to opponents, etc.

Requires Data Version 3+

This filter requires analysis data version 3 with frame_state data available. Use the Schema endpoint to check availability.

Parameters

Parameter Type Required Description
type string Yes Must be "frame_state"
players array Yes Player IDs to check (e.g. ["0-5", "1-13"])
column string Yes State column to threshold on
gte number No Minimum value (greater than or equal)
lte number No Maximum value (less than or equal)
min_duration_ms integer No Minimum interval duration in milliseconds (default: 500)

Available Columns

Column Type Description
timestamp int32 Milliseconds from match start; join key. Same format as tracking.parquet (= frame / fps * 1000).
player_id str Identity-resolved 'team-jersey' id; join key.
speed_mps float32 Smoothed speed in m/s — Savitzky-Golay (window=9, order=2) over per-track xy. Pinned in the schema; changing the smoother bumps data_version_external.
nearest_opp_id str player_id of the closest opposite-team player at this frame. Null when no opponent is on-frame.
nearest_opp_dist_m float32 Distance to nearest_opp_id in metres.

Basic Examples

Player sprinting (speed >= 7 m/s)

{
  "filters": [
    {
      "type": "frame_state",
      "players": ["0-10"],
      "column": "speed_mps",
      "gte": 7.0,
      "min_duration_ms": 1000
    }
  ]
}

Player jogging (moderate speed)

{
  "filters": [
    {
      "type": "frame_state",
      "players": ["0-10"],
      "column": "speed_mps",
      "gte": 2.0,
      "lte": 4.0,
      "min_duration_ms": 2000
    }
  ]
}

Player pressing (close to opponent)

{
  "filters": [
    {
      "type": "frame_state",
      "players": ["0-7", "0-8", "0-10"],
      "column": "nearest_opp_dist_m",
      "lte": 2.0,
      "min_duration_ms": 500
    }
  ]
}

Combining with Other Filters

High-speed runs during possession

{
  "operator": "AND",
  "filters": [
    {
      "type": "frame_state",
      "players": ["0-10"],
      "column": "speed_mps",
      "gte": 6.0,
      "min_duration_ms": 1000
    },
    { "type": "team_possession", "teams": ["team_0"] }
  ]
}

Sprint into the final third

{
  "operator": "AND",
  "filters": [
    {
      "type": "frame_state",
      "players": ["0-10"],
      "column": "speed_mps",
      "gte": 7.0,
      "min_duration_ms": 1000
    },
    { "type": "ball_location", "x_min": 70, "x_max": 105 }
  ]
}

How It Works

The filter identifies consecutive frames where the player meets the threshold condition, groups them into intervals, and filters out intervals shorter than min_duration_ms. This ensures you only get meaningful stretches of activity, not single-frame spikes.

Response Structure

{
  "start": 340.2,
  "end": 343.8,
  "label": "speed_mps >=7.0",
  "type": "frame_state"
}

Response Fields

Field Type Description
start float Start time in seconds
end float End time in seconds
label string Column name and threshold used
type string Always "frame_state"