> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ochy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Analysis workflow

> Understand the full lifecycle of a video analysis -- from upload to retrieving results.

This guide walks through the complete analysis lifecycle: uploading a video, monitoring
progress, and retrieving different levels of result data.

## Video requirements

Before uploading, make sure your video meets these constraints:

| Constraint | Requirement                          |
| ---------- | ------------------------------------ |
| File size  | 30 MB maximum                        |
| Duration   | 10 seconds maximum                   |
| Format     | MP4, MOV, AVI, or WEBM               |
| Resolution | 1080p recommended (max 1080p height) |
| Frame rate | 30 fps minimum, 60 fps recommended   |

### Orientation

Required orientation depends on the analysis type and running condition (see the `treadmill`
parameter below). Submitting a video with the wrong orientation will produce poor results or
cause the analysis to fail.

<Tip>
  See [example videos](/guides/example-videos) for the full orientation matrix, typical
  resolutions, and reference input/output clips per scenario.
</Tip>

## Analysis types

Choose the analysis type based on the camera position:

<Tabs>
  <Tab title="Side view">
    Camera is positioned to the side of the runner. Set `analysis_type=side_view`.

    **Produces:**

    * Overall biomechanical score (0 -- 1)
    * Running metrics: speed, step length, cadence, ground contact time, time of flight, duty factor
    * Overstride analysis with angle and score
    * Foot landing classification per step (rearfoot, midfoot, forefoot)
    * Joint angles: ankle, knee, hip, shoulder, elbow
    * Running style classification with confidence percentage
  </Tab>

  <Tab title="Back view">
    Camera is positioned behind the runner. Set `analysis_type=back_view`.

    **Produces:**

    * Gait cycle analysis with stance phase means per leg
    * Pronation / supination per foot
    * Pelvic drop
    * Knee adduction
    * Step-by-step landing data with frame timestamps

    Set `full_body=false` to limit analysis to pronation/supination only.
  </Tab>
</Tabs>

<Tip>
  See [example videos](/guides/example-videos) for sample input and output videos of each analysis type.
</Tip>

## Parameters

| Parameter       | Type    | Required    | Default     | Description                                                                                   |
| --------------- | ------- | ----------- | ----------- | --------------------------------------------------------------------------------------------- |
| `video`         | file    | Yes         | --          | Video file to analyze                                                                         |
| `analysis_type` | string  | Yes         | `side_view` | `side_view` or `back_view`                                                                    |
| `height`        | number  | No          | 1.70        | Runner height in meters                                                                       |
| `weight`        | number  | No          | 70          | Runner weight in kilograms                                                                    |
| `pace`          | string  | Conditional | --          | Running pace `MM:SS`. Required when `treadmill=true`. Auto-calculated for overground running. |
| `language`      | string  | No          | `en`        | Result language: `en`, `fr`, `de`, `zh`, `ko`, `pt`, `es`, `it`, `ja`                         |
| `treadmill`     | boolean | No          | `false`     | Whether the runner is on a treadmill                                                          |
| `full_body`     | boolean | No          | `true`      | Full body analysis (back view only). Set `false` for pronation only.                          |
| `subject_id`    | string  | No          | --          | Subject ID to link the analysis to. See [subject management](/guides/subject-management).     |

## Lifecycle

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant API as Ochy API

    Client->>API: POST /analysis/start (video + params)
    API-->>Client: 202 { video_id }

    loop Poll every 3-5 seconds
        Client->>API: GET /analysis/{id}/results
        alt pending
            API-->>Client: 200 { status: pending, percentage: 0 }
        else analyzing
            API-->>Client: 202 { status: analyzing, percentage: 45 }
        else success
            API-->>Client: 200 { status: success, biomechanical_analysis, ... }
        else failed
            API-->>Client: 400 { status: failed }
        end
    end

    Client->>API: GET /analysis/{id}/results/calculated_data
    API-->>Client: 200 { metrics, overstride, foot_landing, ... }

    Client->>API: GET /analysis/{id}/results/raw_data
    API-->>Client: 200 { frames, video_input_information }
```

### Status progression

| Status      | HTTP code | Meaning                                                        |
| ----------- | --------- | -------------------------------------------------------------- |
| `pending`   | 200       | Analysis is queued, waiting for a processing slot.             |
| `analyzing` | 202       | Processing is underway. The `percentage` field shows progress. |
| `success`   | 200       | Analysis is complete. Full results are available.              |
| `failed`    | 400       | Analysis could not be completed. No results available.         |

### Polling strategy

Poll the results endpoint every 3 -- 5 seconds. Most analyses complete within
10 -- 30 seconds depending on video length and server load.

```python theme={null}
import time
import requests

def wait_for_analysis(video_id: str, api_key: str, interval: float = 3.0) -> dict:
    """Poll until analysis completes or fails."""
    url = f"https://partner-api.ochy-prod.com/analysis/{video_id}/results"
    while True:
        response = requests.get(url, params={"apiKey": api_key})
        data = response.json()

        if data["status"] in ("success", "failed"):
            return data

        time.sleep(interval)
```

### Webhooks (optional)

You can register an HTTPS endpoint and enable notifications per analysis to receive progress
and completion events without polling. See [API keys and webhooks](/guides/webhooks-and-api-keys)

## Result levels

Once the status is `success`, you can access three levels of data:

<AccordionGroup>
  <Accordion title="Full results (GET /analysis/{id}/results)">
    The results endpoint returns everything in a single call: status, signed URLs
    (thumbnail and annotated video), and the `biomechanical_analysis` object containing
    scores, metrics, and classifications. Each segment's `texts` object includes
    `recap`, `consequences`, and `correction` for both side view and back view
    (side view may also include `coach_tips`).

    Each biomechanical segment includes `score_number`, `measured_value`, and
    score ranges such as `range_good`, `range_okay`, and sometimes `range_bad`.
    `measured_value` and all range values are expressed in degrees. Range
    boundaries can overlap: for example, with `range_good: [0, 102]` and
    `range_okay: [102, 111]`, values up to `102` are good and values strictly
    greater than `102` are okay.

    For side view, `total_score` is a weighted calculation, not a simple average
    of the segment scores.

    Use this when you need a complete snapshot of the analysis.
  </Accordion>

  <Accordion title="Calculated data (GET /analysis/{id}/results/calculated_data)">
    Structured numerical metrics without media URLs. Ideal when you need to process
    or display specific values.

    **Side view** includes: `metrics`, `overstride`, `foot_landing`, `joint_angles`,
    `running_styles`, and `total_score`.

    **Back view** includes: `gait_cycle` with stance means per leg (pronation,
    knee adduction, pelvic drop) and step-by-step data.
  </Accordion>

  <Accordion title="Raw data (GET /analysis/{id}/results/raw_data)">
    Frame-by-frame position data for every anatomical landmark detected. Includes
    `video_input_information` (resolution, FPS, duration) and a `frames` object
    keyed by frame number.

    Use this for custom visualizations, overlays, or your own biomechanical models.
  </Accordion>
</AccordionGroup>

## Error handling

Common errors during the analysis workflow:

| Error                | Code                   | Status | When                                               |
| -------------------- | ---------------------- | ------ | -------------------------------------------------- |
| File too large       | `file_too_large`       | 413    | Video exceeds 30 MB                                |
| Video too long       | --                     | 400    | Video exceeds 10 seconds                           |
| Invalid file type    | `invalid_file_type`    | 400    | Unsupported extension (not MP4, MOV, AVI, or WEBM) |
| Not completed        | --                     | 400    | Requesting calculated/raw data before `success`    |
| Insufficient credits | `insufficient_credits` | 402    | No credits remaining                               |
| Not found            | --                     | 404    | Invalid `analysis_id`                              |
