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 :
A more professional version, to simplify the creation of WVD files, also allows for the export of WVD files.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)
+ Reply to Thread
Results 1 to 2 of 2
Similar Threads
-
how get .wvd
By mr.root in forum Video Streaming DownloadingReplies: 15Last Post: 21st Sep 2025, 03:01 -
Widevine cdm in .wvd format
By stevepen1974 in forum Video Streaming DownloadingReplies: 4Last Post: 23rd Mar 2025, 07:47 -
pywidevine key
By aletaladro in forum Video Streaming DownloadingReplies: 6Last Post: 16th Jul 2024, 16:44 -
help with pywidevine
By killua in forum Video Streaming DownloadingReplies: 1Last Post: 12th Jul 2023, 01:56 -
pywidevine + L3 Problem with new CDM Server [build date 5 AUG 2022]
By Balooshy in forum Video Streaming DownloadingReplies: 7Last Post: 25th Aug 2022, 07:55


Quote