Squash CoachYour court, measured.
DrawingWSF singles court, plan
ScaleTrue, in court metres
StatusIn build · not released

One iPhone on the gallery rail · one Watch on the racket wrist

Your court,
measured.

A fixed phone films the court. A pipeline on your own Mac solves the camera from the court’s known geometry, tracks both players’ feet in real metres, and cuts the rallies out of the sound of the room.

Not released. There is no App Store listing, no beta link, no download and no price. This is a personal tool being built for one court and one player. The demo opens the real app in your browser on sample rows.

Front wall · tin 0.48 m 9.75 m 6.40 m
Illustration — a World Squash Federation singles court drawn to true size: 9.75 m from front wall to back, 6.40 m across, the short line 5.49 m from the front wall, two 1.6 m service boxes, the tin along the front wall and glass at the back. The solid dot is the T. The dashed ring is the T zone, roughly 1.5 m across. The line is a schematic movement track leaving the T four times and returning; the four small rings are where a shot was played. It is a drawing of what gets measured, not a recorded session.
Camera
One iPhone, fixed, on the viewing gallery rail. 1080p at 120fps, segmented to disc.
Sensor
One Apple Watch on the racket wrist — wrist motion and heart rate, started and stopped from the wrist.
Processing
Python, on your own Mac. Nothing is uploaded.
Court
WSF singles, 9.75 × 6.40 m. Geometry is configuration, not code.
01

What it measures

What comes back is where you stood, how far you were from the T, how long you took to get back there, and how long the rallies lasted — in metres and seconds, on a court that is the same size everywhere on earth.

Two sensors produce all of it. A camera that can see the whole court, and the sound of the court itself. Positions are solved in court metres rather than pixels, so a number here means the same thing on any court anywhere.

Less timeMore

Illustration — an occupancy heatmap: how long one player spent in each 0.40 × 0.41 m cell of the court, 16 cells across by 24 deep, darker meaning longer. The dark mass sits on the centre of the court just in front of the short line, which is the T, and fades towards the front corners and the back wall. Drawn by scripts/render-court-diagrams.mjs from the example session file that ships with the app.

From that one picture

2.43 mMean distance from the T
46.8 %Share of rally time holding the T
1.51 sMedian recovery to the T after a shot
1284 mDistance covered
44 / 56Front half / back half, per cent
96.4 %Frames that produced a measurement

These six numbers are read from the same example session file as the heatmap beside them. That file describes itself, in its own quality block, as “fixture data — not a measurement”. No session has been recorded and processed with this build, so nothing on this page is a result.

The last of the six is the one that governs the other five. Below about 90 per cent of frames tracked, the numbers above it are soft and the app says so rather than printing them straight.

Rallies, cut from the sound of the court

A four-wall court is a sealed acoustic box, and racket, front wall, floor and tin each make a different transient. Onsets are detected and clustered, then grouped into rallies by the gaps between them. Indoors, with two players and four hard walls, audio is a better event sensor than vision.

Rally 1 — 9.72s, 7 shots Rally 2 — 9.42s, 6 shots Rally 3 — 16.56s, 12 shots Rally 4 — 12.25s, 9 shots Rally 5 — 3s, 3 shots Rally 6 — 13.49s, 8 shots Rally 7 — 6.55s, 4 shots Rally 8 — 10.77s, 8 shots Rally 9 — 12.54s, 9 shots Rally 10 — 19.58s, 15 shots Rally 11 — 7.9s, 5 shots Rally 12 — 10.46s, 8 shots Rally 13 — 8.76s, 5 shots Rally 14 — 17.1s, 11 shots Rally 15 — 13.13s, 8 shots Rally 16 — 17.53s, 10 shots Rally 17 — 10.47s, 6 shots Rally 18 — 10.69s, 6 shots Rally 19 — 14.34s, 11 shots Rally 20 — 12.81s, 9 shots Rally 21 — 14.08s, 9 shots Rally 22 — 4.67s, 2 shots Rally 23 — 17.44s, 10 shots Rally 24 — 12.2s, 10 shots Rally 25 — 3s, 2 shots Rally 26 — 7.32s, 4 shots Rally 27 — 16.51s, 12 shots Rally 28 — 13.17s, 11 shots
00:0006:3513:10
Illustration — a rally timeline across thirteen minutes and ten seconds of recording. Twenty-eight red bars, one per rally, each as wide as the rally was long; the gaps between them are the rest. Five minutes and twenty-five seconds of it was play, seven minutes and forty-five seconds was not.
28Rallies detected
12.3 sMedian rally length
0.70Work to rest, played against paused
13:10Recording length

Same example file. The work-to-rest figure is recomputed from the twenty-eight bars actually drawn above rather than read from the fixture’s stored field, because the two disagree and the page may only print what its own diagram shows.

02

How it works

One phone, fixed. One Watch, on the racket wrist. Then four steps on your own machine, none of which involve a server.

  1. Calibrate, once

    Click six to eight known court points on a still. The court is its own calibration target — standard dimensions, red lines at known heights — so one camera is enough to solve where it is standing.

  2. Track the feet

    Per-frame pose estimation finds both players’ ankles, and the ankles project through the known floor plane into court coordinates. Feet rather than bounding boxes, because a lunge is still a position.

  3. Cut the rallies

    Onsets in the audio are clustered by spectral shape into racket, front wall, floor and tin, then grouped into rallies by the gaps. The Watch’s impact spikes are cross-correlated against the same onsets, which is how the two streams check each other.

  4. Report, with receipts

    Heatmaps, T-dominance, distance from the T, recovery time, rally length and work-to-rest — and then the coaching, which is held to the rule in section 04 and may not say anything it cannot point at.

The pipeline is Python and runs on the owner’s own Mac. The video never leaves it. There is no server to send it to, which is the single largest simplification in the whole design and the reason there is nothing here to sign up for.

03

The threshold, published before the result

A system like this can close the loop end to end while measuring badly, and every number downstream then inherits the error quietly. So the measurement is held to a fixed threshold, written down in advance, before a single line of the coaching layer is built. This is that threshold.

Measured against roughly five minutes of hand-labelled footage. Half a metre is not a round number chosen for looking rigorous: the T zone is about 1.5 m across, so an error much above half a metre makes T-dominance meaningless.
What is measuredMust clear
Player court position, against hand labelsmedian < 0.5 m, p90 < 1.0 m
Correct player identity> 95% of frames
Rally boundaries, within ±0.5 sF1 > 0.90
Shots per rally, against a manual countwithin ±10%

This gate has not been run. When it is, the result goes here — pass or fail, with the labelled footage it was measured against. Until then this page describes what is measured and how it is measured, and publishes no accuracy figure, because there is no measured accuracy figure to publish. If the gate fails, the coaching layer does not get built until the measurement is fixed.

04

A claim must cite

The failure mode of an AI coach is fluent, confident, generic advice. “Get back to the T faster” is true of every squash player alive and worth nothing. So a finding may not exist without a number, a rally and a timestamp, and it renders with those clips beside it. A claim that cannot cite is dropped before rendering rather than softened.

Work on — movement

You are standing 2.43 m from the T on average, and you are losing the T in the second half.

Across 28 rallies you held the T zone for 46.8% of rally time against your opponent’s 53.2%, with a median 1.51 s to recover after playing a shot. You covered 1284 m; they covered 1211 m for less of the court.

  • Rally 10 · 04:03
  • Rally 16 · 07:00
  • Rally 23 · 10:17

Illustration. Built from the same example session file, laid out the way the app renders a finding. It is not a recorded session, it is not advice, and it is not the output of any model that has been run.

05

What it is not