Web UI for converting game images
10K+
Fork notice: This is a fork of MarcTV's Docker CHD Converter. It adds a Web UI and more conversion tools on top of the original CLI converter. Thanks to MarcTV for the original.
A game image converter that wraps nine tools: CHDMAN (MAME), dolphin-tool (Dolphin Emulator), z3ds_compressor (Nintendo 3DS), nsz (Nintendo Switch), maxcso (PSP/PS2 CSO/ZSO), 7z (handheld ROM archives), makeps3iso (PS3 decrypted folder → ISO), nkit2iso (NKit-shrunk GameCube/Wii image → ISO), and JWUDTool (Wii U WUD ↔ WUX). Pick the tool that matches your files and convert from a browser, or run it headless from the command line.
.iso), NKit (an NKit-shrunk GameCube/Wii image restored to a full .iso), or Wii U (WUD ↔ WUX), chosen per job.| Tool | Platform / Use | Input Formats | Output Formats | Compression Control | External Keys | Binary |
|---|---|---|---|---|---|---|
| CHDMAN | CD / DVD / HD / LaserDisc discs | .gdi, .cue, .bin, .iso, .chd | .chd, .cue, .bin, .iso, .raw, .avi | Codec list (zstd, zlib, …) | None | mame-tools |
| Dolphin | GameCube / Wii discs | .iso, .wbfs, .rvz, .wia, .gcz | .rvz, .wia, .gcz, .iso | Codec + numeric level | None | dolphin-emu |
| 3DS | Nintendo 3DS ROMs | .cci, .cia, .3ds, .cxi, .3dsx, .zcci, .zcia, .z3ds, .zcxi, .z3dsx | .zcci, .zcia, .z3ds, .zcxi, .z3dsx, .cci, .cia, .3ds, .cxi, .3dsx | None (fixed) | None | z3ds_compressor |
| Switch | Nintendo Switch dumps | .nsp, .xci, .nsz, .xcz | .nsz, .xcz, .nsp, .xci | Layout + level | Yes (prod.keys) | nsz |
| CSO | PSP / PS2 game images | .iso, .cso, .zso, .dax | .cso, .zso, .dax, .iso, .chd | Effort preset (Fast/Default/Max); the cso_to_chd chain ignores it and uses chdman defaults | None | maxcso (+ chdman for cso_to_chd) |
| Handheld ROM | Game Boy / GBC / GBA / DS ROMs | .gb, .gbc, .gba, .nds, .7z, .zip | .7z, .zip, .gb, .gbc, .gba, .nds | Effort preset (Fast/Default/Max) | None | 7z (p7zip-full) |
| PS3 ISO | Decrypted PS3 disc / JB folders | a folder containing PS3_GAME/ (plus PS3_DISC.SFB for disc rips) | .iso (optional 4 GB FAT32 split) | None (fixed) | None | makeps3iso |
| Wii U | Wii U disc images | .wud, .wux | .wux, .wud | None (fixed); a verify-after-conversion toggle | None | JWUDTool (Java) |
| NKit | NKit-shrunk GameCube / Wii discs | .nkit.iso, .nkit.gcz | .iso, .rvz (via the nkit_to_rvz chain) | None (fixed) | None | nkit2iso (+ dolphin-tool for nkit_to_rvz) |
Most conversions above are lossless and fully reversible, including 3DS, which
now decompresses back to the original ROM as well. This uses
z3ds_compress (a fork that adds a
decompression mode and .cxi/.3dsx support to the original
energeticokay/z3ds_compress).
The compressed .z3ds can be read directly by Azahar, or restored to
.cci/.cia/.3ds with z3ds_decompress; see
Nintendo 3DS Support.
PS3 ISO is the clearest exception to the round trip. It packs a decrypted PS3
folder into a .iso that RPCS3 mounts directly; there is no reverse mode back to
a folder, and it never deletes the source. See
PlayStation 3 Support.
The CSO tool also has a one-step chain, cso_to_chd, that runs a .cso/.zso/.dax
through maxcso to a temporary .iso and then chdman to a .chd in a single job.
The disc image survives losslessly, but this one changes container: extracting the
resulting .chd gives you an .iso, not the original .cso/.zso/.dax, so
delete-on-verify here trades the compressed source for a CHD. See
PSP / PS2 Support.
NKit is one-directional for the opposite reason: this app never writes NKit,
it only restores it. nkit_restore rebuilds the original .iso — bit-exact and
CRC32-verified, except for a Wii image missing its update partition (see
NKit Support) — which you can then hand to Dolphin or
CHDMAN like any other disc image — or use the
one-step nkit_to_rvz chain, which restores and compresses to RVZ in a single job
so the full-size ISO never lands in your library. See
NKit Support.
Archive inputs: most input formats above can be converted straight from inside a ZIP, 7z, or RAR archive, including 3DS ROMs, Dolphin game images, Switch dumps, and Wii U images. Browse into the archive, pick a member, and convert. This even covers CHDMAN's extract modes pulling a
.chdout of an archive and decompressing it back to a game image. A few exceptions: CHDMAN's copy/recompress mode is not offered from an archive (recompressing an already-finished.chdwould be a pointless round trip); Handheld ROM does not accept loose ROMs from inside an archive — its.7z/.zipare the packed product, so to unpack one select the archive file itself and runromz_extract, rather than browsing into it for a member; and PS3 ISO takes a folder, not a file, so it is never an archive input (a zippedPS3_GAMEtree can't be converted from inside an archive). Each tool's full mode list (e.g. CHDMAN'screatecd/extractcd, CSO'scso2_compress, the ROM packer'sromz_7z/romz_zip/romz_extract, the PS3 packer'sfolder_to_iso, and NKit'snkit_restore/nkit_to_rvz) is in Supported Operations.
Archive inputs: most input formats above can be converted straight from inside a ZIP, 7z, or RAR archive, including 3DS ROMs, Dolphin game images, Switch dumps, and NKit images. Browse into the archive, pick a member, and convert. This even covers CHDMAN's extract modes pulling a
.chdout of an archive and decompressing it back to a game image. A few exceptions: CHDMAN's copy/recompress mode is not offered from an archive (recompressing an already-finished.chdwould be a pointless round trip); Handheld ROM does not accept loose ROMs from inside an archive — its.7z/.zipare the packed product, so to unpack one select the archive file itself and runromz_extract, rather than browsing into it for a member; and PS3 ISO takes a folder, not a file, so it is never an archive input (a zippedPS3_GAMEtree can't be converted from inside an archive).
Compressatorium can sync MAME Redump DAT files (Logiqx XML) in one click and check your compressed files against known-good Redump hashes. The same hashes let tools like Hasheous and RomM match your library.
MAMEREDUMP_AUTO_SYNC=true to sync DATs on container startup when none are loadeddolphin-tool verify — the same hash MAME Redump records for GameCube/Wii discs — so compressed Dolphin outputs match without the container bytes having to be identical.iso/.bin): Matched via file-level SHA1.iso, and the .bin data track from CHDMAN extract), not just CHDs, so non-CHD libraries get cached match results too. A single PS3-packed .iso is matched like any other .iso; a 4 GB split set is not, since its .iso.0/.iso.1 parts aren't scanned extensions. Heavy Dolphin disc-hashing during the scan honors MATCH_MAX_FILE_SIZE and stops promptly if you cancel the scan.The Docker image is available from two registries:
docker pull pacnpal/compressatorium
docker pull ghcr.io/pacnpal/compressatorium
Both registries provide identical images with multi-architecture support (linux/amd64 and linux/arm64).
Note: Use either registry: replace
pacnpal/compressatoriumwithghcr.io/pacnpal/compressatoriumfor the same image.
| Tag | Description |
|---|---|
latest | Latest stable release |
beta | Latest pre-release build (see warning below) |
X.Y.Z | Specific stable version (e.g., 3.7.0) |
X.Y.Z-beta-N | Specific pre-release build (e.g., 3.7.0-beta-3) |
sha-xxxxxxx | Specific commit build |
To track pre-release builds, pull the :beta tag instead of :latest:
docker pull pacnpal/compressatorium:beta
Or pin to a specific pre-release (recommended if you want to control when you upgrade):
docker pull pacnpal/compressatorium:3.7.0-beta-3
Warning: beta builds can cause data loss. Pre-releases may carry unfinished migrations, experimental conversion logic, or breaking changes to the job database. Running a beta against a database that a stable release created can corrupt it or migrate it past the point of return, and downgrading back to
:latestafterwards is not supported. Before you pull:beta:
- Back up your SQLite database (
compressatorium.dbin your data volume) and any in-flight output files.- Prefer a separate data volume for beta testing rather than pointing a beta container at your production volume.
- Do not use beta builds for batches you cannot afford to redo.
When you open the Web UI, you'll see the tool options at the top:
.iso RPCS3 can mount.wux and backChoose the tool that matches your files. The interface then shows only the modes and file types that tool can use.
This is the global guide to the workflow and the features shared by every tool — browsing, modes, compression, verifying/deleting, archives, DAT matching, and troubleshooting. The per-tool sections further down only document what's specific to each tool (its formats, modes, env vars, and quirks). The same material is available in-app under Help.
Your mounted volumes appear in the left panel — click a folder to enter, a
breadcrumb to go back. Search All walks the whole volume and lists every
convertible file at once; the filter dropdown narrows by extension. Both
update automatically as tools are added. System clutter (.DS_Store, AppleDouble
._* files, Thumbs.db, desktop.ini, @eaDir, #recycle, lost+found, …) is
hidden so listings stay clean.
Create makes a compressed file, extract/decompress gives the original back, copy
recompresses in place. Pick the create mode that matches the media — compressing a
PSP/PS2 image with createcd instead of createdvd won't come out right. The
full mode list per tool is in Supported Operations.
Every tool that compresses (CHD, Dolphin, Switch, CSO) shares one compression picker in the convert panel:
zlib,
Dolphin zstd:19, Switch solid:18). See also
Compression Compatibility Tips.By default the output lands next to its source; set a custom output directory instead and it's created for you as long as it's inside a mounted volume. If a matching output already exists the app stops and asks rather than clobbering it: skip keeps the existing file, rename writes under a new name, overwrite replaces it.
Every conversion and verify runs through one FIFO queue — one job at a time by default, which keeps the host responsive during big batches. Progress streams live, and jobs run on the server, so closing the browser (or rebooting your laptop) doesn't stop them; reopen the page and it reconnects. The queue has active / completed / failed tabs, plus Cancel All and Clear Done (both confirm first).
Converting never deletes anything on its own — the safe order is convert, verify,
then delete the source. Verify reads the whole output back and checks it against
the file's own hashes/CRC; with delete-on-verify the source is removed only
after the output passes, and never if it fails. You get a confirmation list of
everything to be deleted first, including the .cue/.gdi track files that ride
with a .bin, and the whole archive if the source came from one. Bulk Verify
checks a whole selection at once across CHD, Dolphin, 3DS, Switch, and CSO;
verification status persists between sessions, and a long verify can be given a
timeout so a stalled one doesn't block the queue.
Click a file to open the inspector — it shows the format/version, compression, size, and hashes, plus the raw tool output. For PS1/PS2/PSP/Dreamcast discs it also digs the game serial out of the sector data and shows a human title when it recognizes one. A background scan caches this so the list badges don't recompute on every folder open.
Sync the MAMERedump DATs from the DAT Library (or import your own .dat/.xml
from No-Intro/Redump) and converted files are checked against known-good hashes —
a blue DAT badge means the file matches. CHDs match on the codec-independent header
SHA1, and Dolphin RVZ/WIA/GCZ match on the game image's content SHA1 reconstructed by
dolphin-tool verify --algorithm sha1 (the same hash Redump records), so any
compression setting still matches for both. A missing badge usually means the DATs
aren't synced, the title isn't in the DAT, or the file is larger than
MATCH_MAX_FILE_SIZE (which skips the expensive full-disc reconstruction) — not that
the file is bad.
Browse straight into a ZIP, 7z, or RAR and convert a file from inside it — no need
to extract first. The member is unpacked to a temp dir for the conversion and
cleaned up afterwards. Any convertible source works this way (CHD create,
Dolphin, 3DS, Switch, and CSO — Switch still needs your own prod.keys), and
CHDMAN's extract modes can even pull a .chd out of an archive and decompress it
back to a game image. CHDMAN's copy/recompress mode is the exception: it acts on a
finished .chd, and recompressing one straight out of an archive is a pointless
round trip, so it's not offered there. Handheld ROM and PS3 ISO also don't take
archive inputs: the ROM packer's .7z/.zip are its product, and PS3 ISO's
input is a folder, not a file.
Browsing into an archive does not list everything it contains. It lists the
file types the app knows — every extension that some tool recognizes as a
convertible source (.iso, .cue/.bin, .gdi, .gcz/.wia/.rvz/.wbfs,
.cci/.cia/.3ds/.cxi/.3dsx, .nsp/.xci, .cso/.zso/.dax, the handheld ROMs
.gb/.gbc/.gba/.nds, …) plus a .chd you can decompress in place. Anything
else is hidden, on purpose:
.nfo/.sfv files, box art,
manuals, save states — none of it is something the app can convert or verify, so
it would only be clutter in the browser. The listing is global, scoped to known
extensions: a member shows up if and only if its extension is one the app
understands, regardless of which tool you currently have selected..zip inside a .zip (or .7z/.rar) is not
listed — there's no point browsing an archive within an archive.__MACOSX/… resource forks, .DS_Store,
Thumbs.db and the like never appear, so a ROM zipped on a Mac or Windows box
still reads as a clean single-file archive.Some members that are shown still can't be converted from inside the archive, and the UI badges them non-convertible:
Game.gba inside Game.gba.7z) is shown
so you can see and verify it, but it isn't offered for re-conversion —
recompressing an already-archived ROM would just be packing a .7z into another
.7z. To unpack it, select the archive file itself and run romz_extract..chd inside an archive can be decompressed in place (chdman's extract
modes), but it can't be recompressed — it's already a finished CHD, so chdman's
copy/recompress mode is deliberately not offered from an archive.In short: if a file you expect isn't in the list, it's almost always because its extension isn't one of the convertible/verifiable types the app handles. Loose files on disk follow the same rule — the file list filters to the types the selected tool understands.
zlib only using copy mode (see Compression Compatibility Tips).The web interface is the easiest way to run Compressatorium:
docker run -d \
-p 127.0.0.1:8080:8080 \
-e PUID=$(id -u) \
-e PGID=$(id -g) \
-v /path/to/config:/config \
-v /path/to/games:/data/games \
pacnpal/compressatorium
Then open http://localhost:8080 in your browser. The Web UI and API are unauthenticated by default. To require a token, set COMPRESSATORIUM_ENABLE_AUTH=true: the Web UI then prompts for HTTP Basic auth (username defaults to admin), using COMPRESSATORIUM_AUTH_TOKEN for the password or the token generated in /config/auth_token on first startup.
Required: The
/configvolume must be mounted for persistent data storage and the generated auth token.
Volume discovery: IfCOMPRESSATORIUM_VOLUMESis unset, the app scans/data/*at startup and auto-registers mounted game volumes (restart after mount changes).
Ownership (optional): SetPUID/PGIDto match your host user/group (for example Unraid99:100). If unset, defaults remain999:999.
Default temp location:/config/temp. To use a different location, setCHD_TEMP_DIRand mount it.
Mount multiple game directories for better organization:
docker run -d \
-p 127.0.0.1:8080:8080 \
-v /path/to/config:/config \
-v /home/user/dreamcast:/data/dreamcast \
-v /home/user/psp:/data/psp \
-v /home/user/ps1:/data/ps1 \
pacnpal/compressatorium
In the Web UI, you can specify a custom output directory for converted CHD, Dolphin, or 3DS outputs instead of placing them alongside the source files. The directory will be created automatically as long as it is within your configured volumes.
The Web UI ships with light and dark themes and is fully responsive from desktop down to phones. Each surface below is shown as a light / dark pair.
These screenshots are generated automatically. The Take screenshots GitHub Actions workflow builds the UI, runs it against a throwaway fixture library, captures each surface with shot-scraper (definitions in
shots.yml), optimises the PNGs with Oxipng, and commits the results back todocs/screenshots/. To refresh them, trigger that workflow (or run it locally — seedocs/SCREENSHOTS.md).
A three-pane layout: navigation and tool picker on the left, the volume and file browser in the middle, and a live convert panel with the job queue on the right. Selecting a tool refilters the file list and the convert options to match.
| Light | Dark |
|---|---|
![]() | ![]() |
Batch selection. Tick multiple files and the convert panel arms itself, showing how many sources are queued and a one-click Start conversion.
| Light | Dark |
|---|---|
![]() | ![]() |
Dolphin (GameCube / Wii). Compress discs to RVZ, WIA, or GCZ, with a codec and compression-level picker.
| Light | Dark |
|---|---|
![]() | ![]() |
3DS. Compress .cci, .cia, and .3ds ROMs with z3ds_compressor.
| Light | Dark |
|---|---|
![]() | ![]() |
Wii U. Compress .wud disc images to .wux with JWUDTool, and back again.
| Lig
Content type
Image
Digest
sha256:db22c66a5…
Size
423.3 MB
Last updated
about 2 months ago
docker pull pacnpal/compressatorium