VideoHelp Forum





Try StreamFab Downloader and download streaming video from Netflix, Amazon!



+ Reply to Thread
Results 1 to 2 of 2
  1. Hello everyone, I am creating a menu to convert the files: private_key.pem, client_id.bin, device_private_key, device_client_id_blob into device.wvd format.

    Give the program a name in Python, such as Convert_CDM.py.
    how it works:
    • The program will check if PyWideVine is installed on your PC.
    • If it is not installed there, it will be installed in your place, you will need to add (Y = YES).
    • Once you have installed pywidevine you will have a menu.
    • A folder has been created: device_android.
    • The following files were added to the device_android folder: private_key.pem, client_id.bin, device_private_key, device_client_id_blob, your *.wvd file
    • Choose two modes: create-device device or export-device.

    my code :
    Code:
    import os
    import subprocess
    import sys
    import time
    import glob
    
    # ============================
    # ANSI Styles
    # ============================
    GREEN = "\033[92m"
    RED = "\033[91m"
    YELLOW = "\033[93m"
    CYAN = "\033[96m"
    BLUE = "\033[94m"
    END = "\033[0m"
    
    def success(text):
        print(f"{GREEN}✔  {text}{END}")
    
    def error(text):
        print(f"{RED}❌ {text}{END}")
    
    def info(text):
        print(f"{CYAN}ℹ  {text}{END}")
    
    def clear_screen():
        os.system("cls" if os.name=="nt" else "clear")
    
    # ============================
    # Check pywidevine
    # ============================
    def check_pywidevine():
        try:
            subprocess.run(["pywidevine", "--version"], capture_output=True, text=True, check=True)
        except (subprocess.CalledProcessError, FileNotFoundError):
            error("pywidevine is not installed or not found.")
            choice = input(f"{YELLOW}Do you want to install it now? (y/n) : {END}").strip().lower()
            if choice == "y":
                try:
                    subprocess.run([sys.executable, "-m", "pip", "install", "pywidevine"], check=True)
                    success("pywidevine installed successfully ✅")
                    time.sleep(1)
                    clear_screen()
                except subprocess.CalledProcessError:
                    error("Failed to install pywidevine.")
                    time.sleep(2)
                    sys.exit()
            else:
                info("Installation cancelled, exiting program.")
                time.sleep(1)
                sys.exit()
    
    check_pywidevine()
    
    # ============================
    # Configuration
    # ============================
    folder = "device_android"
    os.makedirs(folder, exist_ok=True)
    pair_1 = ("private_key.pem", "client_id.bin")
    pair_2 = ("device_private_key", "device_client_id_blob")
    
    def check_pair(pair):
        return all(os.path.isfile(os.path.join(folder, f)) for f in pair)
    
    def get_single_wvd():
        wvd_files = glob.glob(os.path.join(folder, "*.wvd"))
        if not wvd_files:
            error("No .wvd file found.")
            time.sleep(2)
            return None
    
        if len(wvd_files) > 1:
            error("Multiple .wvd files found, leave only one:")
            for f in wvd_files:
                error(f" - {os.path.basename(f)}")
            time.sleep(2)
            return None
    
        return wvd_files[0]
    
    # ============================
    # Main menu loop
    # ============================
    while True:
        clear_screen()
        print(f"""
    {CYAN}====================================
      {BLUE}PyWidevine Universal Device Tool{CYAN}
    ====================================
    {YELLOW}1) {GREEN}Create device.wvd
    {YELLOW}2) {GREEN}Export device.wvd
    {YELLOW}0) {RED}Exit{CYAN}
    ===================================={END}
    """)
        choice = input(f"{YELLOW}Choice: {END}").strip()
    
        # ============================
        # OPTION 1 : CREATE
        # ============================
        if choice == "1":
            if check_pair(pair_1):
                key_file, client_file = pair_1
                success("Pair detected: private_key.pem + client_id.bin")
            elif check_pair(pair_2):
                key_file, client_file = pair_2
                success("Pair detected: device_private_key + device_client_id_blob")
            else:
                error("No valid key/client pair found in the device_android folder.")
                time.sleep(2)
                continue
    
            print()
            info("Select device type to create:")
            info("1) ANDROID")
            info("2) CHROME")
            info("3) OEM")
            info("4) CDM")
            dtype = input(f"{YELLOW}Choice [1-4]: {END}").strip()
            device_map = {"1": "ANDROID", "2": "CHROME", "3": "OEM", "4": "CDM"}
            device_type = device_map.get(dtype)
            if not device_type:
                error("Invalid device type.")
                time.sleep(2)
                continue
    
            level = input(f"{YELLOW}Widevine level (1 or 3): {END}").strip()
            if level not in ("1", "3"):
                error("Invalid level.")
                time.sleep(2)
                continue
    
            info("Creating device.wvd...")
            wvd_output = os.path.join(folder, "device.wvd")
            cmd = ["pywidevine", "create-device", "-k", os.path.join(folder, key_file), "-c", os.path.join(folder, client_file), "-t", device_type, "-l", level, "-o", wvd_output]
            try:
                subprocess.run(cmd, check=True)
                success("device.wvd created successfully ✅")
                info(f"Path: {wvd_output}")
    
                # Remove source files
                try:
                    os.remove(os.path.join(folder, key_file))
                    os.remove(os.path.join(folder, client_file))
                    info("Source files removed ✅")
                    input(f"{YELLOW}Press Enter to continue...{END}")
                except OSError as e:
                    error(f"Error removing source files: {e}")
    
            except subprocess.CalledProcessError:
                error("Error while creating device.wvd.")
                time.sleep(2)
                continue
    
        # ============================
        # OPTION 2 : EXPORT
        # ============================
        elif choice == "2":
            wvd_path = get_single_wvd()
            if not wvd_path:
                continue
            wvd_name = os.path.basename(wvd_path)
            export_folder = os.path.join(folder, os.path.splitext(wvd_name)[0])
            info(f"Exporting {wvd_name}...")
            try:
                subprocess.run(["pywidevine", "export-device", wvd_name], cwd=folder, check=True)
    
                # Rename files to expected format
                client_src = os.path.join(export_folder, "client_id.bin")
                key_src = os.path.join(export_folder, "private_key.pem")
                client_dest = os.path.join(folder, "device_client_id_blob")
                key_dest = os.path.join(folder, "device_private_key")
    
                if os.path.isfile(client_src):
                    os.replace(client_src, client_dest)
                if os.path.isfile(key_src):
                    os.replace(key_src, key_dest)
    
                # Remove remaining export folder
                for f in os.listdir(export_folder):
                    path = os.path.join(export_folder, f)
                    try:
                        os.remove(path)
                    except Exception:
                        pass
                try:
                    os.rmdir(export_folder)
                except Exception:
                    pass
    
                success("Export completed ✅")
                success(f" - {key_dest}")
                success(f" - {client_dest}")
    
                # Remove original .wvd file
                try:
                    os.remove(wvd_path)
                    info(f"Source file removed: {wvd_name} ✅")
                    input(f"{YELLOW}Press Enter to continue...{END}")
                except OSError as e:
                    error(f"Error removing source file: {e}")
            except subprocess.CalledProcessError:
                error("Error during export.")
                time.sleep(2)
                continue
    
        # ============================
        # EXIT
        # ============================
        elif choice == "0":
            info("Exiting...")
            time.sleep(1)
            break
    
        else:
            error("Invalid choice.")
            time.sleep(1)
    A more professional version, to simplify the creation of WVD files, also allows for the export of WVD files.
    Quote Quote  
  2. works great
    thanks
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!