← Portfolio

Case study G

The limitations section

An urgent client request, a platform that wouldn't hand over the files, and five near-identical three-hour recordings named only by the minute they started. The delivery was seventeen gigabytes. The part I'd defend is the page that says what those files are not.

Role
Sole builder
Duration
2026, one day
Delivered
5 matches · ~17.6 GB · written audit
Stack
Python, ffmpeg, frame sampling, contact sheets
01

The problem

A client needed five of their own matches, urgently, and the platform holding them would not produce downloadable files. The only route was to play each one back and capture it.

That produced five recordings, all made the same afternoon, each named by nothing but the timestamp it started at. Every one is roughly three hours long. Every one looks identical in a file listing. And nothing in any filename says which match it contains.

The hard problem wasn't capturing the footage. It was proving, afterwards, which match was inside each file.

They also ran long — capture was unattended, so each recording kept going well past the end of its match. And a capture of a playback screen carries the playback interface with it: a persistent counter in one corner and a timer along the bottom, burned into every frame.

Getting this wrong has a very specific shape. Send a client a file labelled as one match that contains another and the error isn't discovered by you — it's discovered by them, at the moment they most need it.

02

The approach

03

The method

  1. Audit each file's real technical properties True duration, dimensions, frame rate, bitrate and audio format read from the container rather than assumed — because the thing you are about to spend an afternoon processing should be the thing you think it is.
  2. Sample frames into contact sheets Nine frames spread across each three-hour file, tiled into a single sheet. One image per recording, scannable in seconds, and enough to identify the match without scrubbing through hours of footage.
  3. Inspect the points that carry information Openings, several points through each game, the final rallies and score displays, and the transition into the frozen end screen — the places where the content actually identifies itself.
  4. Trim the dead tail, and record how much Roughly 94 minutes of post-match recording across the five, with one file carrying an hour and seventeen minutes of nothing at the end. Every trim is listed per file rather than summarised.
  5. Crop the interface without re-encoding 48 pixels off the top and 58 off the bottom, removing the counter and the timer while retaining the entire original horizontal field of view. Applied as display cropping, so the encoded picture is untouched and the audio is copied rather than recompressed. Result: a clean frame at full original quality, and not one pixel of artificial upscaling.
  6. Publish the source mapping Which capture became which delivered match, stated explicitly — plus a note that older recordings in the same folder were left alone, so the client knows the boundary of what was touched.

The delivery note, in shape

[CLIENT] - SEPTEMBER 2026

Edited from the five screen recordings dated September 17.
Match dates checked against the source library. Opponents
confirmed from the venue or the scoring display in shot.

MATCH            FINAL LENGTH     REMOVED FROM END
Match 1           1:37:56          1:16:56
Match 2             41:18             4:58
Match 3             35:27             2:34
Match 4             48:44             0:03
Match 5             43:20             9:29

FRAMING AND QUALITY
... crop applied as display cropping; original encoded
picture preserved; audio copied without recompression;
the original recordings are intact.

AUDIT SCOPE AND LIMITATIONS
... a sampled technical audit, not a play-by-play review.
The recordings begin roughly 13-18 seconds into the original
playback, and those seconds cannot be recovered from these
files. Mouse pointers over the court remain. The crop does
not reconstruct obscured pixels. The videos are not
represented as complete copies of every second of the
original footage.

SOURCE MAPPING
[capture timestamp] -> [match]   × 5

Real structure, names removed, timings unchanged. Note what the limitations section does: it tells the client the files are 13–18 seconds short at the front, that the loss is permanent, and that nobody watched every second. None of that was asked for, and all of it would otherwise have been found by the client.

04

The outcome

Five matches delivered the same day, roughly 17.6 GB, each correctly identified, trimmed, and free of the playback interface — at the original encoded quality, because nothing was re-compressed. Around 94 minutes of dead recording removed. Originals intact. One written audit alongside the files.

The delivery I'd point at isn't the footage. It's that a client can read one page and know exactly what they have: which file is which match, how it was identified, what was removed and how much, what was changed about the picture and what deliberately wasn't, and precisely where the files fall short of being complete copies.

A file that arrives with an honest account of itself is worth more than a slightly better file that arrives with assumptions attached.

05

What I'd do differently

The source mapping records the conclusion, not the evidence

The note says opponents were confirmed from the venue or the scoring display. It does not say, for each file, which of those confirmed it, or at what point in the recording. So the mapping is a claim a reader has to take on trust — from exactly the person whose work they'd be checking.

I had already solved this elsewhere. In the image work, every asset carries the evidence for its identification as a field, precisely so the conclusion can be re-checked without redoing the search. The same idea belongs here: one row per file, with the timestamp of the frame that proves it.

The lost opening seconds were a process failure, not a technical one

Each capture begins 13–18 seconds after playback started, so the first seconds of every match are gone and cannot be recovered. No amount of cleverness afterwards fixes it — the pixels were never captured.

That is purely an ordering mistake: start the capture, then start playback, and verify the first frames before walking away. The most expensive defect in this job was the one that cost nothing to avoid and could not be repaired at any price.

An hour and seventeen minutes of nothing should have stopped itself

One recording ran for well over an hour past the end of its match, because capture was unattended and nothing was watching. I trimmed it afterwards by hand.

The end of the content is visually obvious — the playback freezes on a static end screen. A check for a frame that stops changing would have ended each capture on its own, and would have removed the guesswork from the trimming as well. I did the detection with my eyes when the file had already told me in its pixels.

I built one-off tooling for something that will be asked for again

The scripts for this existed for one delivery. Nothing about the request was unusual — a client will want matches again, the platform will still not hand them over, and the same five problems will appear in the same order.

A short, parameterised tool with the audit note as a template would have made the second request an hour's work instead of a day's. This is the same instinct as copying a pipeline per run rather than parameterising it: under deadline I optimise for this delivery, and I keep paying for it on the next one.

And the thing I'd never change

Writing the limitations. It is the section nobody asks for, it makes the delivery look less impressive, and it is the reason the client can trust everything else on the page. Anyone can send files. Telling someone exactly where your work stops being certain is the whole job.