Web UI for converting game disc images (GDI/ISO/CUE) to CHD format
3.3K
Fork Notice: This project is a fork of MarcTV/docker-chd-converter with an added Web UI and additional features. Thanks to MarcTV for the original CLI-based converter!
Compresses GDI, ISO, BIN and CUE files to CHD using CHDMAN from MAME Tools.
.chd filescreatecd (default) or createdvd modesThe Docker image is available from two registries:
docker pull pacnpal/chd-converter
docker pull ghcr.io/pacnpal/docker-chd-converter-webui
Both registries provide identical images with multi-architecture support (linux/amd64 and linux/arm64).
Note: In all examples below, you can substitute
pacnpal/chd-converterwithghcr.io/pacnpal/docker-chd-converter-webuiinterchangeably.
| Tag | Description |
|---|---|
latest | Latest stable release from the main branch |
vX.Y.Z | Specific version (e.g., v1.0.0) |
sha-xxxxxxx | Specific commit build |
The easiest way to use CHD Converter is through the web interface:
docker run -d \
-p 8080:8080 \
-v /path/to/config:/config \
-v /path/to/games:/data/games \
pacnpal/chd-converter
Then open http://localhost:8080 in your browser.
Required: The
/configvolume must be mounted for persistent data storage.
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 8080:8080 \
-v /path/to/config:/config \
-e CHD_VOLUMES="/data/dreamcast,/data/psp,/data/ps1" \
-v /home/user/dreamcast:/data/dreamcast \
-v /home/user/psp:/data/psp \
-v /home/user/ps1:/data/ps1 \
pacnpal/chd-converter
In the Web UI, you can specify a custom output directory for converted CHD files instead of placing them alongside the source files. The directory will be created automatically as long as it is within your configured volumes.
File Browser
Archive Support
.cue/.gdi is present in the same archive folder, .bin entries are suppressed and batch jobs are deduplicated by output path to avoid stalled conversions.Batch Conversion
.cue/.gdi track files)Bulk Operations
CHD Verification
/config/verified_chds.json)CHD Inspector
File Management
Conversion Modes
Compression Options
For automated/headless conversion, use CLI mode:
docker run --rm \
-e CHD_MODE=cli \
-v "$(pwd)/isofiles:/data/games:rw" \
pacnpal/chd-converter
docker run --rm \
-e CHD_MODE=cli \
-e CHDMAN_MODE=createdvd \
-v "$(pwd)/isofiles:/data/games:rw" \
pacnpal/chd-converter
docker run --rm \
-e CHD_MODE=cli \
-e CHDMAN_MODE=createdvd \
-e CHD_VOLUMES="/data/psp,/data/ps2" \
-v /home/user/psp:/data/psp:rw \
-v /home/user/ps2:/data/ps2:rw \
pacnpal/chd-converter
Using the chdman info command directly:
docker run --rm \
-v "/path/to/games:/data/games:ro" \
--entrypoint chdman \
pacnpal/chd-converter \
info -i "/data/games/game.chd"
Or use the Web UI's CHD Inspector feature by clicking on any .chd file.
Some emulators (notably NetherSX2/AetherSX2) only support zlib-compressed CHDs. In the Web UI, choose:
zlibchdman -c)If you see emulator errors like “Failed to initialize cdvd,” re-convert with the zlib-only preset.
Use chdman help createcd or chdman help createdvd to see the expected -c format for your version.
All actions are queued and processed by the job queue (FIFO). The queue is the only execution path.
Create CHD
createraw, createhd, createcd, createdvd, createldExtract from CHD
extractraw, extracthd, extractcd, extractdvd, extractldCopy / Recompress
copy (CHD → CHD, optionally with new compression)Notes:
extractcd produces both .cue and .bin outputs.The Web UI communicates with a REST API that can also be used directly. Interactive API documentation is available at /docs when running the container.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/volumes | List configured volume mount points |
| GET | /api/files | List files in a directory |
| GET | /api/files/search | Recursively search for convertible files |
| GET | /api/files/archive | List contents of an archive file |
| POST | /api/files/rename | Rename a file or directory |
| DELETE | /api/files/delete | Delete a single file or empty directory |
| POST | /api/files/delete-batch | Delete multiple files at once |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/jobs | Create a single conversion job |
| POST | /api/jobs/batch | Create multiple conversion jobs |
| POST | /api/jobs/check-duplicates | Check for existing output files |
| POST | /api/jobs/delete-plan | Build delete-on-verify confirmation list |
| GET | /api/jobs | List all jobs |
| GET | /api/jobs/{id} | Get a specific job |
| DELETE | /api/jobs/{id} | Cancel a job |
| DELETE | /api/jobs/completed | Clear completed/failed/cancelled jobs |
| GET | /api/jobs/events | SSE stream for job progress updates |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/info | Get CHD file metadata |
| GET | /api/verify | Verify a CHD file's integrity |
| GET | /api/verify/events | SSE stream for verification progress |
| POST | /api/verify-batch/events | SSE stream for batch verification |
| GET | /api/verified | List all verified CHD paths |
| Variable | Default | Description |
|---|---|---|
CHD_MODE | webui | Mode: webui (web interface) or cli (batch processing) |
CHD_VOLUMES | /data/games | Comma-separated list of volume mount paths |
CHD_DATA_DIR | /config | Directory for persistent application data |
CHD_TEMP_DIR | /config/temp | Temporary working directory for archive extraction |
CHDMAN_MODE | createcd | Conversion mode: createcd or createdvd (CLI mode only) |
CHDMAN_PATH | /usr/bin/chdman | Path to chdman binary (for custom builds) |
MAX_CONCURRENT_JOBS | 1 | Maximum parallel conversion jobs |
MAX_JOB_HISTORY | 500 | Maximum completed jobs to retain in history |
CHD_CHDMAN_NICE | 10 | Nice level for chdman (0-19, higher = lower priority) |
CHD_CHDMAN_IOPRIO_CLASS | 2 | I/O priority class (1 realtime, 2 best-effort, 3 idle) |
CHD_CHDMAN_IOPRIO_LEVEL | 6 | I/O priority level (0 highest, 7 lowest) |
CHD_ARCHIVE_MAX_ENTRIES | 5000 | Max archive members to list (0 disables limit) |
CHD_ARCHIVE_MAX_MEMBER_SIZE | 0 | Max size in bytes per archive member (0 disables limit) |
CHD_ARCHIVE_MAX_TOTAL_SIZE | 0 | Max total size in bytes for archive listings/extractions (0 disables limit) |
CHD_INFO_TIMEOUT | 60 | Timeout in seconds for chdman info (0 disables) |
CHD_VERIFY_TIMEOUT | 0 | Timeout in seconds for chdman verify (0 disables) |
CHD_VERIFY_PROGRESS_TIMEOUT | 0 | Timeout in seconds without verify output (0 disables) |
CHD_DEBUG | false | Enable debug logging |
CHD_DEBUG_LOG_PATH | (none) | Path to debug log file |
CHD_DEBUG_HEARTBEAT | 30 | Debug heartbeat interval in seconds |
CHD_DEBUG_PROGRESS_INTERVAL | 30 | Debug progress log interval in seconds |
CHD_DEBUG_PROGRESS_TIMEOUT | 300 | Debug progress timeout in seconds |
CHD_PROGRESS_TIMEOUT | 600 | Fail a conversion if progress and output size do not advance for this many seconds (0 disables) |
Defaults are intentionally conservative to reduce host impact during conversion. Increase MAX_CONCURRENT_JOBS or adjust CHD_CHDMAN_* only if your host has ample CPU/RAM and fast storage. By default temp files go to /config/temp; set CHD_TEMP_DIR to use a faster disk and mount it into the container.
The /config volume is required and must be mounted for the application to store persistent data.
-v /path/to/config:/config
| File | Location | Description |
|---|---|---|
verified_chds.json | /config/ | Records of verified CHD files (integrity checks) |
The repository includes ready-to-use Docker Compose configurations:
docker-compose.yml - Single volume setup with subdirectory supportdocker-compose.multi-volume.yml - Multiple separate volume mountsdocker-compose.cli.yml - CLI/batch processing modedocker-compose up -d
The default compose files include conservative CPU/memory limits to help avoid host lockups during large conversions. Adjust those limits to match your system.
How to change settings
docker-compose.yml (or docker-compose.multi-volume.yml) and update MAX_CONCURRENT_JOBS, CHD_CHDMAN_*, and the deploy.resources limits.Recommended starting points
MAX_CONCURRENT_JOBS=1, CHD_CHDMAN_NICE=10, CHD_CHDMAN_IOPRIO_CLASS=2, CHD_CHDMAN_IOPRIO_LEVEL=6. Set a container memory limit (8–12 GB).MAX_CONCURRENT_JOBS=2 and a higher memory limit (16–24 GB). Raise I/O priority only if the host remains responsive.MAX_CONCURRENT_JOBS, increase CHD_CHDMAN_NICE, or set CHD_CHDMAN_IOPRIO_CLASS=3 (idle) with CHD_CHDMAN_IOPRIO_LEVEL=7.Docker host tips
CHD_TEMP_DIR and CHD output to reduce array contention.docker-compose -f docker-compose.multi-volume.yml up -d
docker-compose -f docker-compose.cli.yml up
version: '3.8'
services:
chd-converter:
image: pacnpal/chd-converter
ports:
- "8080:8080"
environment:
- CHD_VOLUMES=/data/dreamcast,/data/psp,/data/ps1
- MAX_CONCURRENT_JOBS=1
- CHD_CHDMAN_NICE=10
- CHD_CHDMAN_IOPRIO_CLASS=2
- CHD_CHDMAN_IOPRIO_LEVEL=6
volumes:
- /home/user/chd-converter-config:/config
- /home/user/games/dreamcast:/data/dreamcast
- /home/user/games/psp:/data/psp
- /home/user/games/ps1:/data/ps1
restart: unless-stopped
For production deployment guidance, see DEPLOYMENT.md.
Input formats:
.gdi - GD-ROM (Dreamcast).iso - ISO 9660 disc images.cue / .bin - CD images with cue sheetsArchive formats (Web UI):
.zip - ZIP archives.7z - 7-Zip archives.rar - RAR archivesOutput format:
.chd - Compressed Hunks of DataThis project is a fork of the original docker-chd-converter by MarcTV. The original project provides a simple CLI-based batch converter, and this fork extends it with a Web UI and additional features.
Original Project:
Thank you MarcTV for creating and sharing the original converter!
Content type
Image
Digest
sha256:d2fdd7890…
Size
310.2 MB
Last updated
8 months ago
docker pull pacnpal/chd-converter