DEV Community

Cover image for ParkRep: film your set, see how close to failure you got
Max
Max

Posted on

ParkRep: film your set, see how close to failure you got

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass

What I Built

For hypertrophy, a set does its job when it ends close to failure. The usual way to judge that is RPE: after the set you estimate how many more reps you had left. It's a feeling, and it moves with mood, fatigue and ego.

There is a physical signal for the same thing. Near failure, each rep goes up slower than the one before. ParkRep measures that from a phone video, so you can tell whether you trained close to failure without relying on a feeling. Prop the phone up, do your set, run one command on your laptop, and you get back the video with a HUD:

  • the reps, counted as they happen
  • how long each rep took to go up
  • how much slower the last reps were than reps 2–4 (the velocity loss)

It works the same on a pull-up bar in a park as on a machine in a gym. A phone is the only equipment.

Why I could test it on real sets: I've logged my training, food and sleep for years. Every set in Hevy has its reps, load and RPE. That gave me real labels to check ParkRep against: the count it should reach, and how hard I said the set was.

Demo

Pull-ups in the park. 7 reps. Reps 1–4 took about 0.7 s each to go up. Rep 6 took 1.7 s. Rep 7 took 3.75 s. Velocity loss over the last two reps: 59%. That was close to failure, and the video shows it.

Same weight, different effort. Two sets of 80 kg × 8 on a Hammer incline press, same session. My log shows them as the same set twice. I had written RPE 7 for the first and RPE 8 for the second:

Set Reps RPE I logged Last rep, time to go up Velocity loss, last 2 reps
Hammer, set 1 8 7 0.90 s 27%
Hammer, set 2 8 8 1.46 s 51%
Park pull-ups 7 — 3.75 s 59%

Two Hammer sets at 80 kg x 8: 26.7% vs 51.0% velocity loss

Same reps, same weight, nearly double the slowdown. The second set was much closer to failure than the log says.

What to do with the number

Velocity loss is a ratio inside one set, so it doesn't depend on the camera's units. Research with bar sensors uses it to decide when to stop a set. In one squat study, Pareja-Blanco et al. (2017) had one group stop each set at 20% velocity loss and another at 40%. Strength gains were similar, and the 40% group grew more quadriceps. It was a small study (about 22 men, 8 weeks, one exercise) and used a sensor in m/s, not a phone in pixels. I don't use it as a rule, only as a reference point: if my working sets for hypertrophy end under ~20%, I probably left reps in the tank.

Code

GitHub logo macksin / parkrep

Count reps and measure concentric slowdown from a phone video, locally, with open-weight point tracking (LocoTrack-S).

ParkRep

Film your set at the park with your phone. Back home, one command turns the clip into an Evangelion-style HUD video: reps counted, speed per rep, and how much you slowed down by the end Everything runs locally on a laptop (tested on a MacBook Air M3, 16 GB). Nothing is uploaded.

Last pull-up of a park set: the HUD shows the concentric slowing down

A rep count tells you what you did, not what it cost. Two sets of 80 kg × 8 on a Hammer incline press look the same in a training log. On video, the first lost 27% of its speed over the last two reps and the second lost 51%. I had logged them as RPE 7 and RPE 8.

Two sets of 8 reps at the same load: velocity loss 26.7% vs 51.0%

scripts/fetch_weights.sh            # LocoTrack-S weights, ~33 MB, checksum verified
uv sync
uv run parkrep my_pullups.mov --title "Pull-ups"
# -> out/my_pullups_parkrep.mp4, out/my_pullups_summary.json, out/my_pullups_summary.png
Enter fullscreen mode Exit fullscreen mode

Requires ffmpeg (brew install ffmpeg) and Python 3.11–3.12.

How it works

  1. Mesh…

scripts/fetch_weights.sh      # LocoTrack-S weights, ~33 MB
uv sync
uv run parkrep my_pullups.mov --title "Pull-ups"
Enter fullscreen mode Exit fullscreen mode

A 26-second clip takes about 45 seconds on a MacBook Air M3. Everything runs on the laptop.

Filming tips: keep the phone still (lean it on something), film from the side or front at a slight distance, and keep the moving part (bar, hands, handle) in frame for the whole set.

How I Built It

ParkRep has to find one point that moves with the rep: the bar, a hand, a machine handle. Everything else in the video (trees, a swinging body, other people) is noise.

  1. Find candidates. OpenCV optical flow follows a grid of points through the clip. Points that go up and down in a regular rhythm score high. Leaves and background don't.
  2. Track them with LocoTrack-S. LocoTrack (Cho et al., ECCV 2024, Apache-2.0) is an open-weight model that follows any pixel through a video and says when it's hidden. It runs on the Mac's GPU. Optical flow loses points when an arm passes in front. LocoTrack doesn't, and that is what makes the counts usable. The best of five tracked candidates is kept.
  3. Count reps. The track is split into up and down moves. Moves that don't fit the set (sitting back, adjusting the seat, getting off the bar) are marked as adjustments and not counted. Slow reps at the end are always kept, because they are the measurement. Time going up is measured from 5% to 95% of each rep's range, so a pause at the top doesn't count as slow lifting.
  4. Draw the HUD. Each rep's numbers appear when that rep reaches the top.

Does it count right?

I filmed two gym sessions (25 sets) and compared with the reps I logged in Hevy:

  • 20 of 25 match. In the 5 misses, the tracked point ended up on the wrong body part or left the frame. All 5 show a LOW CONFIDENCE warning in the video.
  • Park set: 7 of 7. I checked it with a separate script that follows my shirt's height frame by frame. Same 7 reps. Getting off the bar was not counted.
  • The same video always gives the same result.

Limits

  • Speed is in pixels per second. Compare reps within one video, not across days. The camera is never in exactly the same spot.
  • Velocity loss tells you how much you slowed down. It doesn't tell you exactly how many reps you had left.
  • My RPE comparison is one person and a few sets. It looks consistent, but it isn't validated.
  • It assumes the lifting phase moves up on screen. Rows filmed from the front don't work well yet.
  • Open issues, with screenshots: BACKLOG.md.

Why Does Open Innovation Matter?

Bar-speed sensors cost money and only work on a bar. Many apps that read video process it on a server. With open weights, LocoTrack runs on my laptop: my training videos stay with me, there's no account, and it works for a pull-up bar in a park as well as a machine in a gym. The code is open too, so if a count looks wrong you can see exactly why.

My Agent Session

I built ParkRep with AI coding agents (Claude Code, Codex and DeepSeek 4.1 Flash). I checked every rep count in this post against the video myself.

Prize Categories

No partner categories.

Top comments (0)