BOOK A CALL

All projects

Case study

Slate

Domain knowledge encoded as defaults. A Mac app that edits movie metadata and cover art without re-encoding — and knows what media servers actually read.

Platform
macOS
Stack
Swift shell · Python engine · ffmpeg · mutagen
Status
Working and in daily use
Scale
10,500 lines · one dependency · no bundler

The problem

A downloaded film arrives named for the release rather than the film, with no tags, no artwork, and its subtitles in a separate file. Turning that into something a media library understands is a dozen manual steps across three tools, repeated per file.

The insight the whole app is built on

Flags matter more than names

Plex, Emby and Jellyfin all build the label a viewer picks from out of a track’s language and flags, and only ever add the track name on top of that. So a subtitle track called “English (SDH)” that carries no SDH flag is offered as ordinary English, and a viewer whose player prefers SDH will never find it.

That single fact generates two features that read as obvious once you know it and are invisible until you do. Name from language fills every track name in a group from its language code, folding flags into the name. Flags from name goes the other direction, and it is the one servers read: it ticks Forced, SDH or Commentary wherever a track’s name already says so, across the naming styles that actually turn up in rips. It only ever adds a flag, never clears one, so a correctly flagged track whose name happens not to mention it survives.

Decisions

  1. A missing year beats a wrong year

    The filename parser errs toward returning no year, because a wrong year mismatches the film in a library while a missing one is merely blank. Two rules fall out of that: a year needs something in front of it — otherwise 1917 and 2012 are read as their own release dates — and release tokens are never matched at the first word, because films called Cam, It and Ma exist and cutting the title at word one leaves nothing.

  2. Illegal characters are dropped, not substituted

    The edit distance back to the real title stays smaller with an omission than a substitute, and that distance is what a library’s matcher scores. Face/Off files as FaceOff. Anything legal survives, so Amélie keeps its accent.

  3. Media kind decides what the editor is

    A film has no season number and an episode has no studio, so only fields belonging to the selected kind are shown — and the editor writes exactly what it shows. Switching a file from TV to film therefore removes its series, season and episode on save. That is a deletion, so it is never silent.

  4. Save & Move asks nothing

    It saves pending edits, then files the selection away — one press, no confirmation, because choosing it from the dropdown was the decision. A move can run for a while, and coming back to find it had saved and then stopped to ask permission is the one outcome worth designing out.

  5. A progress bar that cannot move is worse than none

    Retagging is instant but rewriting a container is not, so files save one at a time and ffmpeg is asked for its machine-readable progress stream, making the reported position a real fraction. Estimates are weighted by size, since a container rewrite and an in-place retag are not the same amount of work.

Two formats, one interface

The editor is identical for both container families — same fields, same cover panel, same track editor — while doing completely different things underneath. 44 of 48 fields map across; the four that do not are hidden on the format that cannot hold them rather than offered and silently dropped on save.

The choice not to use ffmpeg for MP4 writing was verified rather than assumed: it cannot write custom tags and cover art at the same time, silently discards unknown tags without the flag that breaks cover art, and rewrites the whole container on every save. The tag library edits the atom in place in about a millisecond regardless of file size.

The one with the best story

False Dolby Vision

Some releases declare Dolby Vision over a picture that was graded and encoded in ordinary SDR. A player that believes the declaration applies the wrong transfer curve and colour primaries to those pixels, and the film comes out violently oversaturated with a heavy red cast. Players that ignore the declaration honour the real tags and look fine — so the fault appears only on the one device you actually watch on, which is why it is so hard to diagnose.

In the files seen so far the claim is only a claim: no in-band metadata anywhere, just an element in the track header. The container format lets any element be replaced by padding of identical length, so the repair is a seek and one small write. The video bitstream is never read, decoded or moved — verified by comparing the video stream’s checksum either side of the patch.

Safety posture

Backups on by default, restored automatically if a write fails partway. A backup keeps the name the file had when it was made, so a rename leaves the original name visible next to the new one. Moves never delete before the copy is proven. Read-only files are reported rather than silently skipped. Nothing touches disk until Save, and undo reverses everything.

The local server binds to loopback, requires a random per-run token checked with a constant-time compare, and rejects foreign origins — because the API reads and writes arbitrary paths, and without it any page open in a browser could post to localhost and rewrite the user’s files.

Distribution as a design decision

The app is about 162MB and genuinely standalone: its own relocatable Python, its own statically linked ffmpeg, and the app code. It keeps working after a wipe, on another Mac, with no package manager installed. There is no installer, because an app bundle is a folder.

Two things reliably break a bundled Mac app and both are handled explicitly: a Finder-launched app does not inherit the shell path, so a package-manager ffmpeg is invisible to it; and a child process outlives a parent that is killed, so the server independently watches for its parent disappearing and exits when it is reparented.

Where it stands

Working and in use. The README doubles as a genuinely complete user manual.