I Scanned My Gym Into a Database
Five minutes of walkthrough footage, 342 frames, two AI vision models reading them independently and then argued against each other. The complete equipment inventory of one gym — because you cannot program for equipment you never actually counted.
I train at the same branch every day and I could not have told you, with any precision, what is actually in it. Not really. I knew where *my* machines were — the eight or nine stations on my current program — and the rest of the floor was peripheral vision. Two hundred-odd pieces of equipment I walk past and never see.
That is a stupid way to run a training program, and it became obvious the moment I sat down to plan the next cycle. The plan I have been running for months was written before I ever set foot in this gym. It assumes equipment that may not exist here and ignores equipment that does.
So on Sunday, after arms, I walked the entire floor twice with the camera running — five minutes and forty-two seconds of continuous footage — and then pointed the same AI stack I use for everything else at the problem. Not to describe the gym. To enumerate it.
What follows is the complete inventory of Smart Fit La 10, produced by two independent vision models reading the same 342 frames and then reconciled against each other. It is the raw material for the next article, where this gets turned into an actual program.
The input: 2 walkthrough videos, 5m42s total, 1080p at 30fps.
The method: transcode → 1fps frame extraction → 342 frames → 39 labelled contact sheets → two independent AI vision passes (Claude + Codex) → reconciliation.
The output: every machine, rack, bar, plate and attachment on the floor, grouped by function, with what each one is actually for.
The point: the follow-up article rebuilds my training plan around what this gym actually has — replacing a program written for a gym I do not train in.
How You Actually Get a Machine to Read a Room
This is the part I find more interesting than the inventory, so it goes first.
Step one: transcode. The source clips came off the phone as HEVC in a .mov container — 173MB and 327MB. Before anything touches a model, they get normalised. The gym footage was also shot in portrait but stored landscape with a rotation matrix in the metadata, which means naive frame extraction silently produces sideways images. Worth checking, because a model reading a rotated gym will confidently describe furniture.
Step two: sample. Video is a terrible input format for vision models — massively redundant, since 30 frames per second of a slow walk are 29 frames of nothing new. One frame per second is the sweet spot for a walking pan: fast enough that nothing leaves the frame unseen, sparse enough to be tractable.
# normalise, then sample at 1fps and drop visually-identical frames
ffmpeg -i gym1.mov \
-vf "fps=1,mpdecimate=hi=64*24:lo=64*12:frac=0.33" \
-vsync vfr -q:v 2 frames/gym1_%03d.jpg
# 127 frames out of 3,802 packets — and mpdecimate dropped nothing,
# which tells you the pan never held stillStep three: batch into contact sheets. 342 individual images is a lot of calls. Nine frames tiled into one labelled sheet cuts that to 39, and — this matters more than it sounds — it gives the model *temporal context*. Consecutive frames of the same machine from three angles are far easier to identify together than apart. Every tile is burned with its frame ID and timestamp so any claim can be traced back to a specific second of footage.
A small production note, since the whole point is that this is reproducible: the Homebrew ffmpeg bottle on this machine ships without libfreetype, so the drawtext filter does not exist and the obvious labelling approach fails. Rather than rebuild ffmpeg from source for one filter, the sheets get composed in Pillow — which is faster, gives exact control over the label bar, and removes a dependency instead of adding one.
Step four: two models, independently. This is the load-bearing decision. I ran the identical prompt and the identical sheets through two different vision models with no knowledge of each other — the same two-model pattern I use on code, applied to pixels. One model alone gives you a confident inventory with no error bars. Two models give you something far more useful: a map of where they disagree, which is exactly where the uncertainty actually lives.
Step five: reconcile. Agreements get promoted to confirmed. Disagreements get flagged and resolved by going back to the specific frame. Anything neither model could read stays explicitly marked as unverified rather than being quietly guessed.
Where the two models disagreed — and why that is the valuable part
That table is the honest output of the exercise. A single-model inventory would have told me there are 3 Smith machines and URX plates, with the same confident tone it used for everything it got right.
The Inventory
Counts are deduplicated physical units, not frame appearances, with mirror reflections excluded. Where a row continues past the edge of frame, the number is a floor, not a total — marked "at least". Anything unreadable is marked as such rather than filled in with what a gym like this usually has.
1. Cardio
2. Free weights
3. Plate-loaded machines
A full yellow-and-black plate-loaded line — the Hammer-Strength-style equipment where you load Olympic plates onto lever arms instead of pulling a pin. Manufacturer not legible; possibly a Smart Fit-specific line.
4. Selectorized (pin-stack) machines
The long machine hall. Stations are numbered for the Smart Fit app and colour-coded by body region — purple Piernas for legs, plus Brazos, Tronco and Abdomen y lumbar zone decals. Station numbers observed: 01–04, 20, 25, 26, 30, 40, 43, 50, 51, 52, 53. Stacks appear to run in roughly 4.5 kg increments to about 91 kg.
5. Cable and functional training
6. Functional and conditioning tools
7. Facility
Not training equipment, but it constrains programming more than people admit — you cannot superset across a floor you have to cross twice.
What neither model could confirm
Stated plainly, because an inventory that hides its gaps is worse than one that admits them: exact treadmill, elliptical and bike totals (rows continue past frame); the manufacturer of the yellow/black plate-loaded line; all Matrix model numbers; whether the strength line is Matrix or Movement; the exact Smith machine count; dumbbell and plate weight ranges; and whether battle ropes, sleds or chalk exist anywhere on the floor. None of those are guesses in the tables above — they are absent from them.
Why Any of This Matters
The program I have been running for months is the Monster bodybuilding plan — a six-day split I wrote long before I trained here. It is a good plan. It is also a plan for an *abstract* gym, and it has been quietly colliding with reality: exercises prescribed on equipment this branch does not have, and a floor full of equipment the plan never mentions. Two plate-loaded leg-press variants, a hip-thrust station, four independent cable stacks, a stepmill and a rowing erg do not appear anywhere in it.
There is also a timing argument. I am three months into a protocol, a blood panel lands this week, and the next cycle steps the doses up. Running the same program into a new stimulus is the one thing you can be confident will not work — the body adapted to it months ago. New cycle, new plan.
So the next article does the actual work: take this inventory, take the Monster plan, and rebuild the split around equipment that verifiably exists, twelve metres from where I stand. Every exercise mapped to a specific machine on a specific floor.
This one just had to count them first.
Related Reading
- Monster Bodybuilding Workout Plan — the six-day split this inventory is about to rebuild.
- Next Level Preps — the blood panel and the cycle the new plan is being written for.
- Two Models, One Branch — the same two-model reconciliation pattern, applied to code.
- The Bar Doesn't Lie — what happened last time the training stimulus changed.
- Where Biology Meets Engineering — instrumenting the body — and now the room it trains in.