Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Auto dvd ripping
#1
I is not displayed in real-time Progress of the dvd. Progress bar move to fast.

What I need it do is rip the dvd the Eject it win done and wait dvd the rip. use all dvd drive in the pc.

import os
import time
import subprocess
import threading
import tkinter as tk
from tkinter import ttk
import win32api
import win32com.client

# Paths
OUTPUT_FOLDER = r"C:\Users\crock\Videos"
MAKEMKV_PATH = r"C:\Program Files (x86)\MakeMKV\makemkvcon64.exe"
HANDBRAKE_PATH = r"C:\Program Files\HandBrake\HandBrakeCLI.exe"
HANDBRAKE_PRESET = "Fast 1080p30"
CHECK_INTERVAL = 10

# Ensure output folder exists
os.makedirs(OUTPUT_FOLDER, exist_ok=True)

# GUI Setup
root = tk.Tk()
root.title("Auto DVD/Blu-ray Ripper")
root.geometry("650x500")
root.config(bg="#F2F2F2")
font = ("Segoe UI", 10)

# Button frame
button_frame = tk.Frame(root, bg="#F2F2F2")
button_frame.pack(pady=10)

def start_auto_rip():
    global auto_rip
    auto_rip = True
    log_message("Auto Rip Started")
    threading.Thread(target=process_disc, daemon=True).start()

def stop_auto_rip():
    global auto_rip
    auto_rip = False
    log_message("Auto Rip Stopped")

# Buttons
start_button = tk.Button(button_frame, text="Start Auto Rip", command=start_auto_rip, bg="#4CAF50", fg="white", font=font, relief="flat", padx=15, pady=5)
start_button.pack(side=tk.LEFT, padx=10)

stop_button = tk.Button(button_frame, text="Stop Auto Rip", command=stop_auto_rip, bg="#F44336", fg="white", font=font, relief="flat", padx=15, pady=5)
stop_button.pack(side=tk.LEFT, padx=10)

exit_button = tk.Button(button_frame, text="Exit", command=root.quit, bg="#9E9E9E", fg="white", font=font, relief="flat", padx=15, pady=5)
exit_button.pack(side=tk.LEFT, padx=10)

# Status label & Progress bar
progress_var = tk.IntVar()
progress_bar = ttk.Progressbar(root, length=400, mode="determinate", variable=progress_var)
progress_bar.pack(pady=10)

progress_label = tk.Label(root, text="0%", font=("Segoe UI", 12, "bold"), bg="#F2F2F2")
progress_label.pack()

# Output window
log_window = tk.Text(root, height=15, width=80, wrap=tk.WORD, state=tk.DISABLED, font=("Segoe UI", 9))
log_window.pack(pady=10)

auto_rip = False

def log_message(msg):
    log_window.config(state=tk.NORMAL)
    log_window.insert(tk.END, msg + "\n")
    log_window.see(tk.END)
    log_window.config(state=tk.DISABLED)
    root.update()

def find_disc_drive():
    drives = ["D:\\", "E:\\", "F:\\", "G:\\"]
    for drive in drives:
        try:
            volume_info = win32api.GetVolumeInformation(drive)
            if volume_info[0]:
                return drive, volume_info[0]
        except Exception:
            pass
    return None, None

def rip_disc(drive, label):
    log_message(f"Ripping {label} from {drive}...")
    output_folder = os.path.join(OUTPUT_FOLDER, label)
    os.makedirs(output_folder, exist_ok=True)
    command = f'"{MAKEMKV_PATH}" mkv disc:0 all "{output_folder}"'
    process = subprocess.Popen(command, shell=True)
    while process.poll() is None:
        progress_var.set(min(progress_var.get() + 2, 50))
        progress_label.config(text=f"{progress_var.get()}%")
        root.update()
        time.sleep(5)
    log_message("Rip Complete!")

def convert_to_mp4(label):
    log_message(f"Converting {label} to MP4...")
    files = [f for f in os.listdir(OUTPUT_FOLDER) if f.startswith(label) and f.endswith(".mkv")]
    total_files = len(files)
    if total_files == 0:
        log_message("No MKV files found.")
        return
    for i, file in enumerate(files):
        mkv_path = os.path.join(OUTPUT_FOLDER, file)
        mp4_path = mkv_path.replace(".mkv", ".mp4")
        command = f'"{HANDBRAKE_PATH}" -i "{mkv_path}" -o "{mp4_path}" --preset "{HANDBRAKE_PRESET}"'
        subprocess.run(command, shell=True)
        os.remove(mkv_path)
        progress_var.set(50 + int(((i + 1) / total_files) * 50))
        progress_label.config(text=f"{progress_var.get()}%")
        log_message(f"Converting {file} to MP4 ({i + 1}/{total_files})")
        root.update()
    log_message("Conversion Complete!")
    progress_var.set(100)
    progress_label.config(text="100%")

def eject_disc(drive):
    log_message(f"Ejecting {drive}...")
    shell = win32com.client.Dispatch("Shell.Application")
    drives = shell.Namespace(17)
    drive_obj = drives.ParseName(drive)
    drive_obj.InvokeVerb("Eject")
    log_message("Eject Complete!")

def process_disc():
    global auto_rip
    while auto_rip:
        drive, label = find_disc_drive()
        if drive:
            log_message(f"Detected: {label} in {drive}")
            rip_disc(drive, label)
            convert_to_mp4(label)
            eject_disc(drive)
        else:
            log_message("No disc detected. Checking again in 10 seconds...")
        time.sleep(CHECK_INTERVAL)

root.mainloop()
Reply
#2
Your problem with the progress bar is that it doesn't show progress. You should capture output when you run the rip command and use the output to determine progress. I don't have mkv installed on my laptop, so I wrote a short python program that produces output. I run this as a subprocess and pipe the output into my program.

This is the program I used to mimic the mkv program from the commandline. It spits out words and numbers, the numbers representing progress.
mkv.py
import time

for (
    progress
) in "This is 10 a program 20 30 to generate output 40 50 60 to 70 pipe 80 back to 90 a parent process 100".split():
    print(progress)
    time.sleep(0.5)
And this is a program that runs mkv.py as a subprocess, capturing and displaying the progress output in real time.
import subprocess
import threading
import tkinter as tk
from tkinter import ttk


def rip_task():
    progress_var.set(0)
    start_button["state"] = "disabled"
    with subprocess.Popen(["python", "mkv.py"], stdout=subprocess.PIPE) as process:
        while process.poll() is None:
            line = process.stdout.read1().decode("utf-8").strip()
            if line.isnumeric():
                progress_var.set(int(line))
    start_button["state"] = "normal"


def start_rip():
    threading.Thread(target=rip_task, daemon=True).start()


root = tk.Tk()
progress_var = tk.IntVar(root, 0)
start_button = tk.Button(root, text="Start", command=start_rip)
start_button.pack(side="left", padx=10, pady=10)
ttk.Progressbar(root, length=100, variable=progress_var).pack(side="left", padx=(0, 10), pady=10)
root.mainloop()
For piping to work, the mkv program must output something that you can parse to determine progress. Remember that programs might output the information you need as stderr.

You should look for python packages to for ripping DVD's. They would be easier to use with a Tkinter GUI than running a subprocess and parsing output.
Reply
#3
can some one help me with the code add fixes to my and upload new code with the fixes. i'm not good a coding?
Reply
#4
If you aren't good at coding, where did you get your code? It is messy, but not bad.

You don't need to be a great programmer to write good code. Mostly you need to understand the problem and design a solution. Coding is usually easy once the solution is defined.

Start by running this command in a CMD or powershell, replacing MAKEMV_PATH and output_folder with approprate values.

"{MAKEMKV_PATH}" mkv disc:0 all "{output_folder}"

What information is printed while the disk is ripped? Does any of the output indicate the ripping progress? Write down what output is useful an see if there is a pattern you can use to identify progress information and ignore other information. Play around with different command line options to find which produce the information you need. Do the experiment and post what you find.

Once you know what output you need to get progress information, you need to capture that the output and parse it to find the info. My example shows very few changes are required for your code to capture output whine the subprocess is running. The difficult part is parsing the output to get the progress info. How easy/hard that is will depend on what the program prints while it is run.
Reply
#5
chat gpt it maked the code for me.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020