# Movie Ripping Workflow (HandBrakeCLI + MakeMKV → Jellyfin) ## Tools | Tool | Purpose | |------|---------| | `HandBrakeCLI` | Rip + encode DVDs to H.265 MKV directly from disc | | `libdvd-pkg` | Builds libdvdcss to decrypt commercial DVDs | | `makemkv-bin` / `makemkv-oss` | Decrypt Blu-rays to lossless MKV (required before HandBrake) | | `disc-scan.py` | Helper script to identify the main feature title number | ## Install (one-time) ### DVD support ```bash sudo apt install -y handbrake-cli libdvd-pkg sudo dpkg-reconfigure libdvd-pkg # builds libdvdcss from source — follow the prompt ``` ### Blu-ray support ```bash sudo add-apt-repository ppa:heyarje/makemkv-beta sudo apt update sudo apt install -y makemkv-bin makemkv-oss ``` ## Encode Settings (used for both DVD and Blu-ray) ``` Preset: H.265 MKV 1080p30 Audio: German + English, all matching tracks, AC3/DTS passed through unchanged Subs: ALL tracks (captures forced/foreign-language subs — see Subtitle Strategy below) ``` --- ## DVD Workflow ### One command ```bash python3 ~/smithpc/disc-scan.py ``` The script handles everything interactively: 1. Scans the disc (~20-30 s) and prints a title table with duration, video, audio tracks, and subtitle languages 2. Prompts for title number (default: longest title), movie name (default: from disc label), year (default: from disc filesystem timestamp), audio languages, output directory 3. Shows a full confirmation including the exact HandBrakeCLI command that will run 4. Asks "Begin ripping? [Y/n]" before starting Takes ~30-90 min depending on disc. Output is typically 4–8 GB. ### Manual command (reference / fallback) ```bash HandBrakeCLI \ -i /dev/sr0 \ -t TITLE \ -o "/mnt/media/jellyfin/movies/Movie Name (Year)/Movie Name (Year).mkv" \ --preset="H.265 MKV 1080p30" \ --audio-lang-list deu,eng --all-audio --aencoder copy --audio-fallback aac \ --all-subtitles ``` --- ## Blu-ray Workflow Blu-rays use AACS encryption that HandBrakeCLI cannot decrypt directly. MakeMKV handles the decryption; HandBrakeCLI handles the encoding. ### Step 1 — Create temp dir and scan ```bash mkdir -p ~/makemkv-tmp makemkvcon info disc:0 ``` Look for the longest title by duration. Note its title number (zero-indexed in MakeMKV). ### Step 2 — Decrypt to lossless MKV Replace `TITLE` with the title number from Step 1 (MakeMKV uses 0-based indexing): ```bash TITLE=0 makemkvcon mkv disc:0 "$TITLE" ~/makemkv-tmp/ ``` Outputs a file like `~/makemkv-tmp/Title_t00.mkv`. No re-encoding, so this is fast (~10-20 min). ### Step 3 — Encode with HandBrakeCLI ```bash MOVIE="Movie Name (Year)" OUTDIR="/mnt/media/jellyfin/movies/$MOVIE" INPUT=$(ls ~/makemkv-tmp/*.mkv | head -1) mkdir -p "$OUTDIR" HandBrakeCLI \ -i "$INPUT" \ -o "$OUTDIR/$MOVIE.mkv" \ --preset="H.265 MKV 1080p30" \ --audio-lang-list deu,eng --all-audio --aencoder copy \ --all-subtitles ``` ### Step 4 — Clean up temp files ```bash rm -rf ~/makemkv-tmp/ ``` --- ## Jellyfin Naming Convention Jellyfin expects: ``` /mnt/media/jellyfin/movies/ Movie Name (Year)/ Movie Name (Year).mkv ``` The `mkdir -p "$OUTDIR"` and output path in the commands above follow this convention automatically. --- ## Subtitle Strategy `--all-subtitles` copies every subtitle track from the disc as soft subs (not burned in). This is critical for films with characters speaking constructed or foreign languages (e.g., Dothraki in Game of Thrones, Elvish in LotR, alien dialogue). Those subtitles often live on a separate "forced" track that `--subtitle-lang-list` would miss unless explicitly included. `--all-subtitles` captures them all; Jellyfin lets you toggle which track to display at playback time. --- ## Trigger Jellyfin Rescan Jellyfin dashboard → Libraries → Movies → "Scan Library Files" --- ## Troubleshooting - **`[warning] decavsub: track 0, invalid PTS` during encode:** Normal and harmless. VOBSUB subtitle packets on DVDs frequently have malformed presentation timestamps. HandBrake logs them but still copies the subtitle tracks correctly. - **HandBrakeCLI: "CSS error" or no video:** libdvdcss isn't built yet — run `sudo dpkg-reconfigure libdvd-pkg` again and confirm at the prompt. - **disc-scan.py shows no titles:** Check disc is inserted and spun up (`lsblk`). Try `lsdvd /dev/sr0` to confirm the drive sees it. - **MakeMKV expired trial:** MakeMKV shows a nag but still works during the trial. For long-term use, purchase a license or build from source. - **HandBrakeCLI audio: "copy not supported":** The preset or container rejected a codec. Add `--audio-fallback aac` to fall back to AAC instead of failing silently. - **Wrong title ripped (bonus feature, trailer):** Re-run `disc-scan.py` and compare durations. Main feature is almost always the longest. - **Blu-ray: MakeMKV "AACS error":** The disc uses a newer AACS version not yet in MakeMKV's key database — update MakeMKV to the latest beta via the PPA.