Compressatorium 4.5.0-beta-1
Released 2026-08-18. Convert your RomM library in place, on a schedule, without losing the metadata.
This is a pre-release. Everything below works and is tested, but the scheduler
has been exercised through forced runs and previews rather than across days of real
unattended operation — and a rule that converts a library and deletes the sources
once they verify has earned a beta's worth of scrutiny before it becomes the default
advice. Start with Preview.
Compressatorium and RomM look at the same files and know
different things about them. RomM owns the platform, the game name and the DAT match;
Compressatorium owns the conversion; neither could use the other. There is no
"convert my RomM library" tool today — RomM issue
#2619 is open and unanswered, and
#2241 shows the maintainers built the
hashing half of a converter integration but not the conversion half.
The payoff is a distinction the filesystem cannot make. A bare .iso is a PS2 disc or
a GameCube disc, and the extension will never tell you which — today you resolve that
by picking a tool tab. RomM's platform resolves it instead. Verified end to end on
identical files:
GameCube Metroid Prime file=Metroid Prime (USA).iso tools=['dolphin']
PS2 Gran Turismo 4 file=GT4 (USA).iso tools=['chdman', 'cso']
No ROM crosses the network. The catalog comes over RomM's API; the files are read
from disk. A remote RomM works by mounting its library over NFS/SMB/rclone — there is
no second transport mode to learn or configure.
The short version
- A new RomM view lists your library by platform, with real game names instead of
filenames, in the ordinary workspace — the same file list, row actions, Verify,
convert panel and job queue you already use on a volume. - The platform picks the tools. A GameCube
.isooffers Dolphin RVZ; the same
filename on PS2 offers CHD and CSO. Narrowing is conservative: an unrecognised
platform falls back to plain extension matching rather than leaving you stuck. - Per-platform automation. Every platform gets its own rule — target format,
codec and level, split output, output folder, what to do when the output exists,
verify, delete-after-verify, its own schedule (interval, a time-of-day window that
may wrap midnight, weekday mask, your timezone), queueing limits, and selection
filters by size, name pattern, and identified/unidentified. - Metadata survives the conversion. Provider IDs are snapshotted before the job
runs and re-applied by SHA-1 after RomM rescans, so an RVZ or CSO keeps its artwork
and its match instead of going unidentified. - Preview shows what a sweep would queue without queueing it and without moving
the schedule clock. - Everything is configured in the app — connection, credentials, library path,
and every automation rule. TheROMM_*environment variables are first-run
defaults only; nothing needs a redeploy to change. - Test connection reports three things separately — reachable, token accepted,
library mounted here — because they fail independently. - A rule that cannot be honoured is paused, never widened. See below; this is the
part worth reading before you enable anything unattended.
What you'll see
Open RomM in the sidebar, point it at your instance, and pick a platform. The rows
are RomM's games, and everything downstream is the workspace you already know — select,
convert, verify, watch the queue. A record that resolves to a directory (a decrypted
PS3 game folder) is listed as one, so makeps3iso's folder → ISO is reachable by hand
and not only from automation.
When a platform produces nothing, the editor says which of six reasons applies rather
than reporting an empty run: a tool that is not installed here, a format that is not
for this system, an output folder outside the configured volumes, a platform RomM
could not list, a destination another job already took, or a library that stopped
responding partway.
The view also reports library health per platform: how much is already converted, how
much is left, and an estimate of the space converting the rest would reclaim.
Automation, and what it refuses to do
This is the part to read before enabling a schedule, because the failure mode of
unattended conversion is not "it didn't run" — it is "it ran on more than you meant".
A rule that cannot be honoured is paused, not widened. An output folder outside
the configured volumes, a name filter that is not a valid regular expression or that
backtracks catastrophically, and a half-filled time window all stop the rule and say
so in the editor. Each of those had a "helpful" reading — no filter, no time
restriction — that would have converted more than you asked for, unattended. Unticking
every weekday means no days, not every day.
A conversion is never authorised to write over its own input, and two sources that
resolve to one destination are refused rather than run — with delete-on-verify that
would delete both for one surviving file.
Delete-after-verify is refused where the check is too weak to justify it. A Wii U
noverify conversion passes a structural check that proves the geometry is intact but
not that the stored sectors match the disc; it will not remove your only copy on that
basis.
A mode that would never terminate cannot be selected. CHDMAN's copy/recompress
turns Game.chd into Game_copy.chd, which RomM then rescans and the rule converts
again — full size, once per sweep, until the volume fills. It is not offered as an
automation target.
Sweeps are idempotent. Under skip, the filesystem is the state: a ROM is queued
only when its output is genuinely missing. Overwrite and write-alongside are the
two policies the filesystem cannot answer for, so each rule additionally records what
it has produced — and Forget history is the escape hatch after restoring a backup.
Metadata survives conversion
RomM's hash lookup already reads the SHA-1 embedded in a CHD's v5 header and an
archive's largest-member hashes, so CHD, ZIP and 7z keep their Redump/No-Intro
identity by themselves. RVZ, CSO, NSZ, WUX and Z3DS are matched on the container
hash, which conversion necessarily changes — those would go unidentified.
So the provider IDs are snapshotted before conversion (they are only readable while
the source is still the file RomM knows) and re-applied after RomM rescans, joined by
SHA-1. That is exact, and immune to a rename or a move in between. Press Re-match in
RomM, or leave it to run automatically when the view loads.
One case the promise cannot keep, and the UI now says so up front: a makeps3iso -s
build past 4 GB writes numbered parts and no single file, so there is nothing for RomM
to hash-match.
For anything scripting the API
New endpoints under /api/romm/ cover status, the platform list, the catalog,
settings, rules, preview/run, and the re-pin queue. GET /api/romm/roms returns a
platform's ROMs in the same DirectoryListing/FileEntry shape GET /files already
returns, so an existing client can consume it without a new parser.
No existing endpoint or mode string changed. Two new optional fields appear on
existing response models — display_name (nullable) on FileEntry and
verify_after (default false) on ConversionJob — but both are additive: an
existing client that ignores unknown keys sees no difference. Conversions are still
submitted through POST /api/jobs/batch; RomM is a listing source, not a second
pipeline.
Upgrade notes
There is a database migration. The schema head moves from 0003 to 0007 — four
new revisions, all adding the re-pin queue table and its columns. It runs
automatically at startup. Back up compressatorium.db first, as always; migrations
are forward-only, so a downgrade is a restore.
The API token is persisted, and that is new. ROMM_TOKEN seeds the first run, but
a token saved in the UI is stored in the preferences table of compressatorium.db.
It is never returned to the browser — callers only learn whether one is set — but that
file now holds a secret and should be backed up and permissioned accordingly. Clearing
the token in the UI persists a marker, so an env ROMM_TOKEN cannot silently take over
again. Scopes needed: platforms.read, roms.read, plus roms.write only for
re-pinning.
New environment variables, all optional and all first-run defaults only:
ROMM_URL, ROMM_TOKEN, ROMM_LIBRARY_ROOT, ROMM_AUTO_CONVERT,
ROMM_AUTO_CONVERT_INTERVAL_MINUTES, ROMM_AUTO_CONVERT_MAX_PER_RUN, ROMM_REPIN*,
ROMM_VERIFY_AFTER_CONVERT, ROMM_DELETE_SOURCE_AFTER_VERIFY. None were removed or
renamed, and everything they set is editable in the app afterwards. Leave them all
unset and RomM is simply absent.
Automation is off until you turn it on. The scheduler always runs but checks a
master switch that defaults to off, and every per-platform rule is disabled until you
enable it.
Handheld ROM now accepts more formats. It advertised itself for NES, SNES, N64,
Master System, Genesis, Game Gear, Virtual Boy, WonderSwan, Neo Geo Pocket, Lynx, C64
and Atari while only accepting Game Boy, GBA and DS dumps. It is a 7z wrapper with
no per-format logic, so all of those now work. .bin deliberately stays with the disc
tools.
The image is unchanged in size. No new binaries or runtimes ship with this release
— RomM is reached over HTTP, and the conversions use the tools you already have.
Nothing new is stored in your browser.
Full commit list since v4.4.3 (3 commits, oldest first)
51b2fafchore: sync package.json to v4.4.3 [skip ci]6e998d1Add RomM library integration (#274)9e1a359Update Web UI screenshots — Tue Aug 18 16:14:57 UTC 2026