The process of digitizing a media library is fairly straightforward. The first step is to move your media from the disc to your computer. MakeMKV is the preferred program for this process. This created an exact copy of the files from the disc, which means large files. A tool like handbrake is used as a next step compress the files for media storage and streaming playback. Because the compression process is the lengthiest part, it’s easy to accumulate a backlog of movies and shows that are waiting to be compressed. While there’s not much we can do about the time it takes to compress media, we can automate the lengthiest parts of the process so it’ll just run in the background.
Install CLI Tools
Install the necessary tools, the following works on Debian/Ubuntu-based systems
sudo apt install makemkv-bin makemkv-oss handbrake-cli udev inotify-tools eject
Encoding Queue
If there’s one thing you should automate, it’s the encoding queue. The idea is simple: have a designated queue folder where uncompressed files go. While files exist, a process will pick the oldest file, compress it using the handbrake CLI, and remove the original file when complete.
Setup
#!/bin/bash# ~/scripts/encode-worker.shQUEUE_DIR="$HOME/rips/queue" # uncompressed inputENCODED_DIR="$HOME/rips/encoded" # compressed outputPRESET_FILE="$HOME/scripts/SAVED_PRESET_CONFIG.json" # create in handbrake, export to JSONPRESET_NAME="SAVED_PRESET_NAME" # whatever you named your configLOGFILE="$HOME/rips/encode.log"mkdir -p "$QUEUE_DIR" "$ENCODED_DIR"echo "[$(date)] Encode worker started, watching $QUEUE_DIR" >> "$LOGFILE"while true; do # Grab the oldest queued file across all title subfolders, if any FILE=$(find "$QUEUE_DIR" -mindepth 2 -maxdepth 2 -name '*.mkv' -printf '%T+ %p\n' 2>/dev/null | sort | head -n1 | cut -d' ' -f2-) if [ -z "$FILE" ]; then sleep 30 continue fi CLEAN_TITLE=$(basename "$(dirname "$FILE")") base=$(basename "$FILE" .mkv) OUT_DIR="$ENCODED_DIR/$CLEAN_TITLE" mkdir -p "$OUT_DIR" out="$OUT_DIR/${base}.mkv" # Claim the file immediately so a restart mid-run doesn't double-process it mv "$FILE" "$FILE.processing" FILE="$FILE.processing" echo "[$(date)] Encoding: $CLEAN_TITLE/$base" >> "$LOGFILE" HandBrakeCLI -i "$FILE" -o "$out" --preset-import-file "$PRESET_FILE" -Z "$PRESET_NAME" >> "$LOGFILE" 2>&1 if [ $? -eq 0 ]; then ORIGINAL_SIZE=$(stat -c%s "$FILE") ENCODED_SIZE=$(stat -c%s "$out") if [ "$ENCODED_SIZE" -gt "$ORIGINAL_SIZE" ]; then echo "[$(date)] Encoded file larger than original ($ENCODED_SIZE > $ORIGINAL_SIZE bytes) for $CLEAN_TITLE/$base — keeping original" >> "$LOGFILE" rm -f "$out" mv "$FILE" "$out" else rm -f "$FILE" echo "[$(date)] Encode complete: $CLEAN_TITLE/$base" >> "$LOGFILE" fi else echo "[$(date)] ENCODE FAILED: $CLEAN_TITLE/$base — left as $FILE for manual review" >> "$LOGFILE" fi # Clean up empty title subfolder in the queue once drained rmdir "$(dirname "${FILE%.processing}")" 2>/dev/null || truedone
[Unit]Description=HandBrake encode queue workerAfter=network.target[Service]Type=simpleUser=YOUR_USERNAMEEnvironment=HOME=/home/YOUR_USERNAMEExecStart=/home/YOUR_USERNAME/scripts/encode-worker.shRestart=alwaysRestartSec=10[Install]WantedBy=multi-user.target
Creating encode-worker.service requires elevated permissions. One way to do this is by running
sudo nano /etc/systemd/system/encode-worker.service
Once the files are created, run the following commands
chmod +x ~/scripts/encode-worker.shsudo systemctl daemon-reloadsudo systemctl enable --now encode-worker.service
To stop the service, run
sudo systemctl stop --now encode-worker.service
Disc Detection Event Driven Rip
There are three components to automating ripping when a disc in inserted:
- a udev rule to respond to a disc being inserted into the drive
- a service that initiates the ripping process
- a script the service executes
ACTION=="change", SUBSYSTEM=="block", KERNEL=="sr0", ENV{ID_CDROM_MEDIA}=="1", TAG+="systemd", ENV{SYSTEMD_WANTS}="dvd-rip.service"
[Unit]Description=Automated disc rip pipeline[Service]Type=oneshotUser=YOUR_USERNAMEEnvironment=HOME=/home/YOUR_USERNAMEExecStart=/home/YOUR_USERNAME/scripts/rip-trigger.sh
#!/bin/bash# ~/scripts/rip-trigger.shset -eRAW_DIR="$HOME/rips/raw"QUEUE_DIR="$HOME/rips/queue"LOGFILE="$HOME/rips/rip.log"mkdir -p "$RAW_DIR" "$QUEUE_DIR"TIMESTAMP=$(date +%Y%m%d-%H%M%S)RAW_LABEL=$(blkid -o value -s LABEL /dev/sr0 2>/dev/null || echo "UNKNOWN_DISC")CLEAN_TITLE=$(echo "$RAW_LABEL" | sed -E 's/_DISC[0-9]*//I; s/[_\.]+/ /g; s/ +/ /g' | sed -E 's/\b(\w)/\U\1/g')echo "[$TIMESTAMP] Disc detected: '$RAW_LABEL' -> guessed title '$CLEAN_TITLE'" >> "$LOGFILE"DISC_RAW="$RAW_DIR/$TIMESTAMP"mkdir -p "$DISC_RAW"makemkvcon mkv disc:0 all "$DISC_RAW" --minlength=120 >> "$LOGFILE" 2>&1echo "[$TIMESTAMP] Rip complete, ejecting disc..." >> "$LOGFILE"eject /dev/sr0# Move every ripped file into its own titled subfolder in the queueDEST_DIR="$QUEUE_DIR/$CLEAN_TITLE"mkdir -p "$DEST_DIR"for f in "$DISC_RAW"/*.mkv; do [ -e "$f" ] || continue mv "$f" "$DEST_DIR/" echo "[$TIMESTAMP] Queued: $CLEAN_TITLE/$(basename "$f")" >> "$LOGFILE"donermdir "$DISC_RAW" 2>/dev/null || trueecho "[$TIMESTAMP] Disc processing done. Ready for next disc." >> "$LOGFILE"
Once all three files are saved, run the following commands
sudo systemctl daemon-reloadsudo udevadm control --reload-rulessudo udevadm trigger --subsystem-match=block
Once setup, inserting a disc will initiate a rip and then place the file into a queue to be compressed, and digitizing your media library is as simple as inserting a DVD.