Aller au contenu

Extraction DVD et BlueRay

Pour extraire efficacement les films, séries et autres, le workflow suivant est le plus efficace :

  1. Extraction des pistes de durée supérieure à 1h pour les films (pour série, adapter selon épisode le plus court).
  2. Conversion avec HandBrake en sélectionnant les sous-titres forcés (ou par défaut si pas de piste forcée, parfois les forcés dans la piste par défaut...).
Automatiser le workflow

Le code suivant réalise les étapes décrites précédemment.

Dépendances du script

L'installation de makemkvcon et de HandBrakeCLI est nécessaire au foncitonnement du script.

Pour installer makemkvcon, suivre ce guide.

Pour installer HandBrakeCLI, voir le site officiel.

HandBrakeCLI pour Linux

L'outil est displonible dans les dépôts apt de base :

sudo apt-get update
sudo apt-get install HandBrakeCLI

Astuces

  • La constante DRIVE indique l'emplacement standard du cdrom dans la machine. En cas de problème, contacter l'administrateur pour obtenir de l'aide.
  • La constante OUT_DIR définit l'emplacement dans lequel des fichiers sont créés. Elle peut être ajustée librement.
  • La constante MKV_MINLEN indique le nombre minimal de secondes dans une piste du disque pour qu'elle soit considérée. Réglée à 40min (=2400s), peut être ajustée.
#!/bin/bash
# Copyright (c) 2026 Ludovic Peyter
# SPDX-License-Identifier: MIT

# --- 0. AUTO-UPDATE MAKEMKV KEY ---
echo "Checking MakeMKV License..."
# Scrapes the official forum for the current beta key
NEW_KEY=$(curl -s https://forum.makemkv.com/forum/viewtopic.php?f=5\&t=1053 | grep -oP '(?<=<code>).*?(?=</code>)' | head -n 1)

if [ -z "$NEW_KEY" ]; then
    echo "Could not fetch key automatically. Check your internet connection."
else
    mkdir -p ~/.MakeMKV
    echo "app_Key = \"$NEW_KEY\"" > ~/.MakeMKV/settings.conf
    echo 'app_UpdateEnable = "0"' >> ~/.MakeMKV/settings.conf
    echo "License updated successfully."
fi

# --- CONFIGURATION ---
# Disc reader location
DRIVE="/dev/sr1"
# Output folder
OUT_DIR="/mnt/hdd1/tmp"
mkdir -p "$OUT_DIR"

# Character for the progress bar
FILL_CHAR="#"
EMPTY_CHAR="-"
BAR_WIDTH=50

MKV_MINLEN=2400

HB_LINE_LEN=140

while true; do
echo "--- 1. SCANNING DISC (ROBOT MODE) ---"
# We fetch the raw info once to save time
RAW_INFO=$(makemkvcon -r info dev:$DRIVE --minlength=$MKV_MINLEN)

echo "--------------------------------------------------------"
echo "ID  |  DURATION  |  SIZE    |  FILE NAME"
echo "--------------------------------------------------------"

# This logic parses the TINFO lines:
# TINFO:X,9  is Duration
# TINFO:X,10 is Size
# TINFO:X,27 is Output Name
paste <(echo "$RAW_INFO" | grep "TINFO:" | grep ",9,0," | cut -d: -f2 | cut -d, -f1) \
      <(echo "$RAW_INFO" | grep "TINFO:" | grep ",9,0," | cut -d'"' -f2) \
      <(echo "$RAW_INFO" | grep "TINFO:" | grep ",10,0," | cut -d'"' -f2) \
      <(echo "$RAW_INFO" | grep "TINFO:" | grep ",27,0," | cut -d'"' -f2) | \
      awk -F'\t' '{printf "%-3s | %-10s | %-8s | %s\n", $1, $2, $3, $4}'

echo "--------------------------------------------------------"

echo ""
echo "--- 2. SELECTION ---"
read -p "Which Title ID to extract? (e.g. 0, or type 'all'): " TITLE_NUM
read -p "Enter filename for final MP4 (e.g. Matrix): " BASE_FILE_NAME
[[ "${BASE_FILE_NAME,,}" == "" ]] && BASE_FILE_NAME="tmp"

DO_ALL=false
[[ "${TITLE_NUM,,}" == "all" ]] && DO_ALL=true

mkdir "$OUT_DIR/$BASE_FILE_NAME"
LOG_FILE="$OUT_DIR/$BASE_FILE_NAME/makemkv_error.log"

echo ""
echo "========================================================"
echo "          EXTRACTING TARGET: $TITLE_NUM"
echo "========================================================"
echo ""
echo "--- 3. EXTRACTING WITH MAKEMKV ---"

set -o pipefail

# This rips the selected title to a temporary MKV
# 'mkv disc:0' targets the first drive, $TITLE_NUM is your choice
makemkvcon -r --minlength=$MKV_MINLEN --messages="$LOG_FILE" --progress=-stdout mkv dev:$DRIVE "$TITLE_NUM" "$OUT_DIR/$BASE_FILE_NAME" | while IFS= read -r line; do
    # Check if the line starts with PRGV:
    if [[ $line == PRGV:* ]]; then
        # Strip "PRGV:" and split by comma
        IFS=',' read -r current total max <<< "${line#PRGV:}"

        # Ensure max is not zero to avoid division errors
        if [[ $max -gt 0 ]]; then
            # Calculate percentage (Bash only does integer math, so we scale by 100)
            percent=$(( 100 * current / max ))

            # Calculate number of filled blocks
            filled=$(( percent * BAR_WIDTH / 100 ))
            empty=$(( BAR_WIDTH - filled ))

            # Build the bar string
            bar=$(printf "%${filled}s" | tr ' ' "$FILL_CHAR")
            empty_bar=$(printf "%${empty}s" | tr ' ' "$EMPTY_CHAR")

            # Print the bar (\r returns to start of line, -n keeps it on one line)
            printf "\rProgress: [%s%s] %d%%   " "$bar" "$empty_bar" "$percent"
        fi
    fi
done

# Capture the exit code immediately
MKV_EXIT_CODE=$?

# Turn pipefail back off so the rest of the script behaves normally
set +o pipefail

echo ""

# Check if MakeMKV actually succeeded
if [ $MKV_EXIT_CODE -ne 0 ]; then
    echo "ERROR: MakeMKV extraction failed (Exit Code: $MKV_EXIT_CODE)!"
    echo "Check the log file for details: $LOG_FILE"

    # Prompt the user on how to proceed
    read -p "Do you want to retry or quit? (r/Q): " answer
    [[ "${answer,,}" != "r" ]] && break
    continue
fi

echo -e "\nExtraction Complete."
echo ""
echo "--- 4. CONVERTING TO H.265 (MP4) ---"

ID=0

for TEMP_MKV in "$OUT_DIR/$BASE_FILE_NAME"/*.mkv; do
    # Check if files actually exist to avoid empty loop errors
    [ -e "$TEMP_MKV" ] || continue

    # If extracting 'all', append MakeMKV's generated filename to the base name 
    # to prevent Handbrake from overwriting the same MP4 file.
    if [ "$DO_ALL" = true ]; then
        FILE_NAME="${BASE_FILE_NAME}_${ID}.mp4"
    else
        FILE_NAME="${BASE_FILE_NAME}.mp4"
    fi

    echo ""
    echo "Converting: $(basename "$TEMP_MKV") -> $FILE_NAME"

    # -e x265: High efficiency codec for <5GB files
    # -q 22: High quality balance
    # --subtitle-forced: Automatically finds the French 'foreign' lines
    # --subtitle-burned: Fixes the 'sticky' bug by baking them into the video
    HandBrakeCLI -i "$TEMP_MKV" \
                 -o "$OUT_DIR/$FILE_NAME" \
                 -e x265 -q 22 \
                 --encoder-preset fast \
                 --audio-lang-list fra,eng \
                 --all-audio \
                 --aencoder av_aac \
                 --ab 128 \
                 --subtitle scan \
                 --subtitle-forced 1 \
                 --subtitle-burned 1 \
                 --native-language fra

    echo -e "\nConversion Complete for $OUT_DIR/$FILE_NAME"

    ID=$((ID + 1))

done # End of convertion loop

echo ""
echo "All processing finished!"

echo ""
echo "--- 5. CLEANUP ---"
echo "Removing MKV file..."
rm -r "$OUT_DIR/$BASE_FILE_NAME"

read -p "Do you want to run again or to quit? (r/Q): " answer
[[ "${answer,,}" != "r" ]] && break

done
A la maison
  1. Ouvrir l'explorateur de fichiers.
  2. Cliquer sur Ce PC.
  3. Naviguer dans Disque Local -> Utilisateurs -> Public (C:\Users\Public).
  4. Double cliquer sur Extracteur film.

    Un terminal s'ouvre et l'analyse du film commence.

  5. Quand la liste des titres s'affiche, sélectionner un ID (première colonne).

    Si plusieurs titres font la même durée (ou semblent pouvoir être le film), il est possible d'entrer all pour tous les transférer.

  6. Pour le nom, chercher le film sur TMDB, y accéder et reporter l'id (e.g. Dune (1984) -> 841).

    L'id du film se trouve dans l'url : https://www.themoviedb.org/movie/841-dune.

  7. Quand le transfert est terminé, entrer r pour relancer l'analyse (une fois que le disque a été changé) ou autre chose pour quitter.