Skip to content

autorip Service

autorip is a rip service: insert a disc, and it rips automatically to MKV. A browser-based UI shows live progress, settings, and history, with nothing to type. This page covers deploying autorip and tuning it; for the manual command-line workflow, see the CLI reference.

On disc insert, autorip runs the full pipeline automatically: a tolerant sweep, targeted patch retries on bad ranges, decrypt, and mux to MKV. Multiple drives rip in parallel, each with independent state.

autorip runs on Windows, macOS, or Linux, on a host with an optical drive (a home server or NAS works well). Run it as a single binary, or (on Linux) via Docker. The configuration and API reference below apply to every platform. The container and udev rip-on-insert trigger are Linux-only; on macOS and Windows the daemon polls for inserted discs.

autorip ripping a disc, showing the matched title, poster, and live per-pass progress

The autorip dashboard during an active rip: matched title and metadata up top, with live per-pass progress, ETA, and throughput below.

Get the autorip binary from the Download page, then run the service:

Terminal window
# rename to `autorip`, make it executable, and start the service
mv autorip-* autorip && chmod +x autorip
./autorip serve # then open http://localhost:8080

One static binary, no container, no runtime. Drive access uses the cdrom group or a udev rule (no --privileged); point AUTORIP_DIR at a local path. The output and staging paths are set afterwards in the web UI’s Settings page (stored in settings.json); OUTPUT_DIR / STAGING_DIR environment variables are ignored.

DVDs work out of the box. Blu-ray and 4K UHD need decryption keys.

On macOS, autorip ships for Apple Silicon only. The Intel target was dropped from the release matrix over a linker issue in a C dependency, so there is no autorip-x86_64-macos asset. On an Intel Mac, build from source or run the Docker image. A macOS binary downloaded in a browser is also blocked on first run — see the macOS page.

Published to GHCR as ghcr.io/freemkv/autorip (:latest and :vX.Y.Z). Drop this compose file on a host with an optical drive and bring it up:

docker-compose.yml
services:
autorip:
image: ghcr.io/freemkv/autorip:latest
container_name: autorip
restart: unless-stopped
privileged: true # REQUIRED for optical SCSI drive access
stop_grace_period: 75s # let a rip drain on stop (default 10s is too short)
environment:
- AUTORIP_DIR=/config # where settings.json + logs live
- PORT=8080 # web bind port (set at start, not at runtime)
- AUTORIP_LOG_LEVEL=autorip=info,libfreemkv=warn,freemkv=warn # tracing filter
volumes:
- /dev:/dev # live host /dev (handles USB re-enumeration)
- ./config:/config # settings.json + logs
- /mnt/media:/output # final MKV / M2TS destination
- /tmp/autorip:/staging # intermediate ISO + mapfile
- /sys:/sys:ro # read-only sysfs
ports:
- 8080:8080
healthcheck:
test: ["CMD", "/usr/local/bin/autorip", "--healthcheck"]
interval: 30s
timeout: 5s
start_period: 20s
retries: 3
Terminal window
docker compose up -d

Then open http://<host>:8080.

stop_grace_period: 75s gives a rip time to cancel and drain on a restart or redeploy; Docker’s default 10 seconds is too short for a drive mid-recovery, which can take up to about a minute.

Mount Purpose
/dev:/dev Live host device tree; lets autorip enumerate optical drives and survive USB re-enumeration.
/config Persistent home for settings.json, per-device logs, and (by default) the keys directory.
/output Where finished MKV/M2TS files land.
/staging Intermediate ISO + mapfile during a multipass rip.
/sys:ro Read-only sysfs.

DVDs need none; Blu-ray and 4K UHD need keys. See Decryption Keys for the options (a local file or an online service). autorip’s key settings live in Configuration → Keys below.

For Docker, bind-mount a host directory to /root/.config/freemkv so keys persist across restarts:

volumes:
- ./config/keys:/root/.config/freemkv

These are read at container start and cannot be changed at runtime:

Variable Default Meaning
PORT 8080 Web UI / API bind port.
AUTORIP_DIR /config Where settings.json and logs are stored.
AUTORIP_LOG_LEVEL autorip=info,libfreemkv=warn,freemkv=warn tracing filter for log verbosity.
RIP_USER autorip Unix user the container creates and runs the daemon as.
NFS_HOST (unset) If set with the two below, autorip mounts an NFS share inside the container at startup.
NFS_EXPORT (unset) Export path on the NFS server (e.g. /mnt/pool/media).
NFS_MOUNTPOINT (unset) Where to mount the share inside the container; point output_dir here.
NFS_OPTS (sensible default) Optional override for NFS mount options.

Everything else is configured through the web UI and persisted to settings.json. The NFS mount is best-effort: if the server is unreachable the container still starts and logs the failure.

All settings are editable in the Settings page of the web UI and stored in settings.json under AUTORIP_DIR.

Setting Default Meaning
staging_dir /staging Where intermediate ISO + mapfile live during a rip.
output_dir /output Final MKV / M2TS destination.
movie_dir (empty) Optional subdirectory under output for movies.
tv_dir (empty) Optional subdirectory under output for TV.
output_format mkv Output container: mkv, m2ts, iso, or network (stream to network_target).
network_target (empty) Network output target host:port (for streaming output).
keep_iso false Keep the intermediate ISO in the library after muxing.
iso_dir (empty) Where a kept ISO (or a whole-disc output_format = "iso" rip) is filed. A relative path resolves under output_dir; an absolute path targets another disk. Empty files the ISO beside the muxed title.
Setting Default Meaning
on_insert scan What to do on disc insert: nothing, scan, rip, or resume (prefer resuming an existing partial rip).
auto_eject true Eject the disc automatically after a rip completes.
main_feature true Rip only the longest (main feature) title.
tv_auto true On a detected TV disc, rip every episode and file it as Show (Year)/Season NN/ with no operator step. false holds TV discs for review instead.
min_length_secs 600 Ignore titles shorter than this many seconds.
Setting Default Meaning
max_retries 1 0 = single-pass (no retries); 1-10 = multipass with that many patch passes.
on_read_error stop On a read error during the sweep: stop or skip (skip-ahead).
abort_on_lost_secs 0 Tolerated main-movie loss in seconds after retries; 0 = require a perfect rip.
capture_without_keys false Capture to ISO even when AACS keys are missing, deferring the mux.
max_rip_duration_secs 28800 (8 h) Hard ceiling on total rip time across all passes.
min_pass_budget_secs 5400 (90 m) Minimum wall-clock budget allotted to each pass.
transport_recovery_delay_secs 5 Delay after a USB transport re-enumeration before retrying the drive.
decrypt_threads 0 Decryption worker threads; 0 = auto-detect CPU cores.
Setting Default Meaning
key_source local local (use a local key database) or online (use a key service).
keydb_path (unset) Explicit path to a local key database file.
keydb_url (empty) URL to download a key database from (used by the update action and daily refresh).
keyserver_url (empty) Base URL of an external key service (when key_source = online).
keyserver_secret (empty) Optional bearer token for the key service.
Setting Default Meaning
tmdb_api_key (empty) TMDB API key for title lookup / matching.
webhook_urls (empty) Webhooks that receive a JSON POST on pipeline events. Each entry has a url and post_rip / post_mux / post_move flags (all true by default) choosing which stages it fires on.
log_retention_days 30 How long to keep per-device .log files.

autorip wraps the same recovery engine as the freemkv CLI; see How recovery works for the full sweep-and-patch model. The max_retries setting selects between two modes.

  • Single-pass (max_retries = 0) streams the disc directly to the output container. No intermediate ISO, no retries. Fastest path; appropriate for healthy discs.
  • Multipass (max_retries ≥ 1) runs the full recovery pipeline:
    1. Sweep reads the whole disc to an intermediate ISO, recording good and bad ranges in a mapfile and skipping ahead over damage.
    2. Patch re-reads the bad ranges from the disc, up to max_retries times.
    3. Mux decrypts the ISO and writes the final container.

Multipass exits the retry loop early as soon as there are no unreadable bytes left.

After retries are exhausted, autorip evaluates abort_on_lost_secs against main-movie loss only (menus and trailers are excluded):

  • abort_on_lost_secs = 0: perfect rip required; abort if any main-movie data is still unreadable.
  • abort_on_lost_secs = N: finish the MKV as long as no more than N seconds of main-movie video are missing.

With output_format = "iso" (a whole-disc image), abort_on_lost_secs is ignored and treated as 0: a whole-disc backup always requires a perfect rip. The tolerance applies only to muxed MKV / M2TS output.

When a rip aborts on loss, the staging directory is preserved so you can review or retry.

max_rip_duration_secs caps total wall-clock time across all passes. min_pass_budget_secs guarantees each pass a minimum amount of time. Together they keep a badly damaged disc from running indefinitely while still giving each recovery pass a fair shot.

The dashboard at http://<host>:8080 shows each drive’s current state and live progress (status, percentage, ETA, bad ranges). From it you can:

  • Scan, rip, stop, and eject per drive.
  • Edit any configuration value in Settings.
  • Review held rips (when title matching needs confirmation) and pick the correct title, optionally via a TMDB search.
  • Inspect per-device logs and the system debug log.

autorip idle, showing per-drive controls and the device log

Per-drive controls (Resume, Rip, Verify, Eject) with the live device log expanded below.

State updates stream to the browser over Server-Sent Events (/events).

autorip exposes an HTTP API on the same port as the UI. JSON errors use {"ok": false, "error": "..."}; simple successes return {"ok": true}. {device} is a drive identifier from /api/state.

Method Path Description
GET /api/state Snapshot of every drive’s rip state, plus move/verify state.
GET /api/version Running version, e.g. {"version":"1.7.7"}.
GET /api/system System info: mux/move queues and the output file list.
GET /events Server-Sent Events stream of live state pushes.
Method Path Body Description
GET /api/settings - Full configuration (secrets redacted).
POST /api/settings JSON config fields Overlay and persist settings to settings.json.
Method Path Query / Body Description
POST /api/scan/{device} - Scan the disc (no rip).
POST /api/rip/{device} ?resume=yes|no (optional) Start a rip. See Resume below.
POST /api/stop/{device} - Stop the active rip; preserves staging for resume (404 if device unknown).
POST /api/eject/{device} - Eject the disc (409 if a rip/scan is in progress).
POST /api/accept-loss/{device} - Accept the recorded main-movie loss on a rip that aborted on loss, and deliver it as-is. See Accepted loss.
Method Path Description
POST /api/mux-errors/clear?path=... Clear one failed-mux entry.
POST /api/mux-errors/clear-all Clear every failed-mux entry.
POST /api/move-errors/clear?path=... Clear one failed-move entry.
POST /api/move-errors/clear-all Clear every failed-move entry.
Method Path Description
POST /api/update-keydb Download the key database from the configured keydb_url (SSRF-guarded fetch).
Method Path Body Description
GET /api/review - List rips on hold awaiting operator review.
POST /api/review/resolve {dir, action, title, year} Resolve a held rip: proceed, retitle, or cancel.
GET /api/tmdb/search ?q=query Search TMDB for title candidates.
POST /api/title/{device} {title, year, poster_url, overview, media_type} Override the matched title for the active disc (one-shot).
Method Path Query / Body Description
GET /api/logs/{device} - Per-device log, most recent lines first (plain text).
GET /api/debug ?n=&level=&device=&q= (optional) Recent debug events (JSON, filterable).
POST /api/debug {"enabled":true|false} Toggle debug logging at runtime.

Toggle debug logging and watch the mux stage:

Terminal window
# enable debug logging
curl -s -X POST http://<host>:8080/api/debug -d '{"enabled":true}'
# stream mux-stage output from the container
docker logs autorip --tail=500 -f | grep -i mux

autorip’s recovery work survives interruptions.

  • Default (POST /api/rip/{device}, no param): starts a fresh sweep — the mapfile is recreated and the ISO truncated. It does not delete an existing staging directory, but it does not resume one either; a disc already marked .completed is skipped rather than re-ripped.
  • ?resume=yes: require an existing resumable staging directory. If the sweep is incomplete, it continues the partial sweep, re-reading only the not-yet-recovered ranges from the disc; if the mapfile is already fully recovered, it re-muxes the staged ISO without any disc reads. If no resumable state exists, the request still returns 200 and the rip ends in an error state (there is no synchronous 404).
  • ?resume=no: wipe staging and start completely fresh.

Stopping a rip with /api/stop/{device} preserves staging, so a stopped rip resumes on the next disc insert or container restart, with no time lost on a long UHD rip.

Finished files land in output_dir, optionally split into movie_dir / tv_dir. Set webhook_urls to have autorip POST a JSON event to external systems (a media server, a chat webhook) when a rip, mux, or move completes.

When a rip finishes, autorip sends a rip_complete payload:

{
"event": "rip_complete",
"title": "Dune: Part Two",
"year": 2024,
"format": "UHD",
"poster_url": "https://image.tmdb.org/...",
"duration": "2h 46m",
"codecs": "HEVC 4K HDR10 · TrueHD 7.1 · ...",
"size_gb": 78.4,
"speed_mbs": 24.1,
"elapsed_secs": 5460,
"output_path": "/output/Dune Part Two (2024)/Dune Part Two (2024).mkv",
"errors": 0,
"lost_video_secs": 0.0
}

When the MKV has been produced from the staged ISO, a mux_complete payload with the same fields as rip_complete ("event": "mux_complete").

When the file is moved to its final destination, a smaller move_complete payload:

{ "event": "move_complete", "title": "Dune: Part Two", "output_path": "/output/..." }