hi there,
i have a lot of script ready for wks-keys tool but now not compatible with new pywidevine. so the only way is make a venv environment
but venv apart, we have a solution to simply adapt old scripts to the new pywidevine ?
Try StreamFab Downloader and download from Netflix, Amazon, Youtube! Or Try DVDFab and copy Blu-rays!
Try StreamFab Downloader and download streaming video from Youtube, Netflix, Amazon! Download free trial.
+ Reply to Thread
Results 1 to 15 of 15
Thread
-
Last edited by whs912km; 27th Aug 2024 at 07:07.
-
Angela has posted a thread on this subject: https://forum.videohelp.com/threads/411862-Beyond-WKS-KEYS
But if you don't understand how your scripts work now with the old wks-tools don't even try to port them to pywidevine.
It's easy, yes - but needs a basic understanding of writing python scripts. There no such thing as a convert-my-script-from-wks-to-pywidevine tool (albeit: maybe an AI can do it for you?) -
yes, i know venv and at the moment it's my easiest solution
about AI help: I don't think AI help me on similar conversion, even if in fact it is a machine and unlike a human who would make a distinction ...
maybe it could help solve the problem. I will try. thanks -
Easiest way to rename pywidevine ==> pywidevine_old
from pywidevine_old *import *discord chuliaohaibaipiao -
Novia, thanks for your reply, but not sure to understood well, it seems too simple ...
one my script start with:
Code:import base64, requests, json, xmltodict from base64 import b64encode from pywidevine.decrypt.wvdecrypt import WvDecrypt from pywidevine.cdm import cdm, deviceconfig
Code:import base64, requests, json, xmltodict from base64 import b64encode from pywidevine_old.decrypt.wvdecrypt import WvDecrypt from pywidevine_old.cdm import cdm, deviceconfig
-
really don't think a simple edit pywidevine ==> pywidevine_old is enough to make a script work on the new pywidevine, so i can share here one my script (obviously edited) as a test to convert into new pywidevine standard, just to see what are the differences
Code:import base64, requests, json, xmltodict from base64 import b64encode from pywidevine.decrypt.wvdecrypt import WvDecrypt from pywidevine.cdm import cdm, deviceconfig title_url = input('\nURL: ') lic_url = 'https://lic/' token = input('Token: ') clip_id = title_url.split('-c_')[1] def get_pssh(mpd_url): r = requests.get(url=mpd_url) r.raise_for_status() xml = xmltodict.parse(r.text) mpd = json.loads(json.dumps(xml)) tracks = mpd['MPD']['Period']['AdaptationSet'] for video_tracks in tracks: if video_tracks['@contentType'] == 'video': for rep in video_tracks['Representation']: for t in rep['ContentProtection']: if t['@schemeIdUri'].lower() == 'urn:uuid:edef8ba9-79d6-4ahg-a3c8-99dcd51d21ed': pssh = t['cenc:pssh'] return pssh def get_mpd(token, clip_id): res = requests.get( url=f"https://layout/video/clip_{clip_id}/layout", headers={ "authorization": token, "referer": "https://uu.com/", "origin": "https://uu.com" } ).json() for block in res["blocks"]: if block["featureId"] == "videos_for_player": for item in block["content"]["items"]: if item["itemType"] == "video": for asset in item["itemContent"]["video"]["assets"]: if asset["quality"] == "sd" and asset["format"] == "dashcenc": sd_mpd_url = asset["path"] uid = asset["drm"]["config"]["uid"] content_id = asset["drm"]["config"]["contentId"] elif asset["quality"] == "hd" and asset["format"] == "dashcenc": hd_mpd_url = asset["path"] if not sd_mpd_url or not uid or not content_id: print(' - Error: mpd not found') exit() print(f"\nMPD URL: {hd_mpd_url}") pssh = get_pssh(sd_mpd_url) upfront = requests.get( url=f"https://dcc.asa.com/v1/customers/rtlnl/platforms/m6group_web/services/users/{uid}/videos/{content_id}/upfront-token", headers={ "authorization": token, "referer": "https://ee.com/", "origin": "https://ee.com" } ).json() if upfront.get("token") is not None: upfront_token = upfront["token"] else: print(f' - Error {upfront["message"]}') exit() return upfront_token, pssh def WV_Function(pssh, lic_url, cert_b64=None): headers = { "x-dt-auth-token": upfront_token, } wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64=cert_b64, device=deviceconfig.device_android_generic) widevine_license = requests.post(url=lic_url, data=wvdecrypt.get_challenge(), headers=headers) if not widevine_license.ok: print("license request failed: \n", widevine_license.content) exit() license_b64 = json.loads(widevine_license.text)["license"] wvdecrypt.update_license(license_b64) Correct, keyswvdecrypt = wvdecrypt.start_process() if Correct: return Correct, keyswvdecrypt upfront_token, pssh = get_mpd(token, clip_id) correct, keys = WV_Function(pssh, lic_url) print() for key in keys: print('--key ' + key)
-
This version should work :
HTML Code:import base64, requests, json, xmltodict from pywidevine.cdm import Cdm from pywidevine.device import Device from pywidevine.pssh import PSSH DEVICEPATH = r"device.wvd" title_url = input('\nURL: ') lic_url = 'https://lic/' token = input('Token: ') clip_id = title_url.split('-c_')[1] def get_pssh(mpd_url): r = requests.get(url=mpd_url) r.raise_for_status() xml = xmltodict.parse(r.text) mpd = json.loads(json.dumps(xml)) tracks = mpd['MPD']['Period']['AdaptationSet'] for video_tracks in tracks: if video_tracks['@contentType'] == 'video': for rep in video_tracks['Representation']: for t in rep['ContentProtection']: if t['@schemeIdUri'].lower() == 'urn:uuid:edef8ba9-79d6-4ahg-a3c8-99dcd51d21ed': pssh = t['cenc:pssh'] return pssh def get_mpd(token, clip_id): res = requests.get( url=f"https://layout/video/clip_{clip_id}/layout", headers={ "authorization": token, "referer": "https://uu.com/", "origin": "https://uu.com" } ).json() for block in res["blocks"]: if block["featureId"] == "videos_for_player": for item in block["content"]["items"]: if item["itemType"] == "video": for asset in item["itemContent"]["video"]["assets"]: if asset["quality"] == "sd" and asset["format"] == "dashcenc": sd_mpd_url = asset["path"] uid = asset["drm"]["config"]["uid"] content_id = asset["drm"]["config"]["contentId"] elif asset["quality"] == "hd" and asset["format"] == "dashcenc": hd_mpd_url = asset["path"] if not sd_mpd_url or not uid or not content_id: print(' - Error: mpd not found') exit() print(f"\nMPD URL: {hd_mpd_url}") pssh = get_pssh(sd_mpd_url) upfront = requests.get( url=f"https://dcc.asa.com/v1/customers/rtlnl/platforms/m6group_web/services/users/{uid}/videos/{content_id}/upfront-token", headers={ "authorization": token, "referer": "https://ee.com/", "origin": "https://ee.com" } ).json() if upfront.get("token") is not None: upfront_token = upfront["token"] else: print(f' - Error {upfront["message"]}') exit() return upfront_token, pssh def get_keys(pssh, lic_url): headers = {"x-dt-auth-token": upfront_token,} pssh = PSSH(pssh) device = Device.load(DEVICEPATH) cdm = Cdm.from_device(device) session_id = cdm.open() challenge = cdm.get_license_challenge(session_id, pssh) licence = requests.post(lic_url, data=challenge, headers=headers) licence.raise_for_status() cdm.parse_license(session_id, licence.json()['license']) keys = [f"{key.kid.hex}:{key.key.hex()}" for key in cdm.get_keys(session_id) if key.type != 'SIGNING'] cdm.close(session_id) return keys upfront_token, pssh = get_mpd(token, clip_id) correct, keys = get_keys(pssh, lic_url) print() for key in keys: print('--key ' + key)
-
thank you @aqzs for your editing. script work fine
also i've tried with duckAI but the new script does not work -
hi guys,
here another script that i need to convert: https://files.videohelp.com/u/301058/92766.py
already read Angela thread Beyond WKS-KEYS, but no luck with this script
also tried with AI help, but without share the full script the help isn't full and clear. and i don't want share my script with AI ...
hope someone here can help me. thanks guys -
little note for those who downloaded my script (6 downloads at the moment): this script is intended as technical purpose only.
The script in question does not work, it was edited on purpose, mine is just a technical question of how to switch from wks to new pywidevne -
Mine is just a technical answer. You were given an exemplar in Beyond WKS-KEYS
Is is up to you to extrapolate from the example to whatever script you are trying to use. Or are you just free-loading and anticipating someone will do the work you cannot? (Again)
Take it slowly and consider the calls your WKS script makes and see if there is a replacement line in the example code for L3.py in Beyond WKS-KEYS.Noob Starter Pack. Just download every Widevine mpd! Not kidding!.
https://files.videohelp.com/u/301890/hellyes6.zip -
This what you want?
Code:import json import re from base64 import b64encode import requests import xmltodict # from pywidevine.cdm import cdm, deviceconfig # from pywidevine.decrypt.wvdecrypt import WvDecrypt from pywidevine import Cdm, Device def get_pssh(mpd_url): pssh = '' try: r = requests.get(url=mpd_url) r.raise_for_status() xml = xmltodict.parse(r.text) mpd = json.loads(json.dumps(xml)) periods = mpd['MPD']['Period'] except Exception as e: pssh = input( f"\nUnable to find PSSH or 'skip': ") return pssh try: regex_dscp = re.search('2013">(.{132})<cenc:pssh', mpd) pssh = regex_dscp.group(1) except: try: if isinstance(periods, list): for idx, period in enumerate(periods): if isinstance(period['AdaptationSet'], list): for ad_set in period['AdaptationSet']: if ad_set['@mimeType'] == 'video/mp4': try: for t in ad_set['ContentProtection']: if t['@schemeIdUri'].lower() == "urn:uuid:edeeeeeeeee4ace-a3c8-129acd51d21ed": pssh = t["cenc:pssh"] except Exception: pass else: if period['AdaptationSet']['@mimeType'] == 'video/mp4': try: for t in period['AdaptationSet']['ContentProtection']: if t['@schemeIdUri'].lower() == "urn:uuid:edefhhhhhhhe-a3c8-129acd51d21ed": pssh = t["cenc:pssh"] except Exception: pass else: for ad_set in periods['AdaptationSet']: if ad_set['@mimeType'] == 'video/mp4': try: for t in ad_set['ContentProtection']: if t['@schemeIdUri'].lower() == "urn:uuid:edef8ggggg-4ace-a3c8-129acd51d21ed": pssh = t["cenc:pssh"] except Exception: pass except Exception: try: # for IW for ad_set in periods['AdaptationSet']: if ad_set['@contentType'] == 'video': try: for t in ad_set['ContentProtection']: if t['@schemeIdUri'].lower() == "urn:uuid:xxxx-79d6-4ace-a3c8-129acd51d21ed": pssh = t["cenc:pssh"] except Exception: pass except Exception: pass if pssh == '': pssh = input( f"\nUnable to find PSSH ") return pssh else: return pssh def main(): video_id = input('\nEnter video_id: ') mpd_resp = requests.get(f'https://ot33333ttv/contents/{video_id}/details') cas_id = mpd_resp.json()['VodItems'][0]['CasId'] mpd_link = mpd_resp.json()['VodItems'][0]['UrlVideo'] print(f'\nMPD_LINK: {mpd_link}') pssh = get_pssh(mpd_link) print(f'\nPSSH: {pssh}') # wvdecrypt = WvDecrypt(pssh, cert_data_b64=None) # raw_challenge = wvdecrypt.get_challenge() device = Device.load("device_wvd_file.wvd") cdm = Cdm.from_device(device) session_id = cdm.open() raw_challenge = cdm.get_license_challenge(session_id, pssh) challenge_b64 = b64encode(raw_challenge).decode() headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 9; sdk_google_atv_x86 Build/PSR1.180720.121; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36', 'x-movi-app': '2.9.1', 'x-mov-deviceid': 'xxxxxxxxxxx', 'x-mov-ui': '4.0.99', 'X-Requested-With': 'com.mov.elpepe' } payload = { "accountNumber": "89549xxxx-TEF", "UserProfile": "0", "deviceType": "REDTTV_OTT", "streamFormat": "DASH", "streamDRM": "Widevine", "streamMiscellanea": "HTTPS", "deviceManufacturerProduct": "unknown" } resp = requests.post('https://clientservices/=ssp&version=8&status=default', headers=headers, json=payload) token = resp.json()['token'] ssp_token = resp.json()['sspToken'] access_token = resp.json()['accessToken'] headers1 = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 9; sdk_google_atv_x86 Build/PSR1.180720.121; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36', 'X-HZId': token, 'X-Requested-With': 'com.moeeeetv' } payload1 = { 'contentID': video_id, 'streamType': 'QAST', 'drmMediaID': cas_id } resp = requests.post('https://hzmoiajshhd/02542b4af5b60/Session', headers=headers1, json=payload1) ctoken = resp.json()['resultData']['cToken'] headers2 = { 'nv-authorizations': ctoken, 'User-Agent': 'MI5_TV/2.3.1 (Linux;Android 9) ExoPlayerLib/2.11.8' } resp2 = requests.post('https://wv-otuwhshhk/venseservice/v1/licenses', data=raw_challenge, headers=headers2) license_b64 = b64encode(resp2.content).decode() print(f'\n{license_b64}') # wvdecrypt.update_license(license_b64) # keys = wvdecrypt.start_process() # if keys: # for key in keys: # print(f'\n--key {key}') cdm.parse_license(session_id, license_b64) for key in cdm.get_keys(session_id): print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}") cdm.close(session_id) if __name__ == '__main__': main()
--[----->+<]>.++++++++++++.---.--------.
[*drm mass downloader: widefrog*]~~~[*how to make your own mass downloader: guide*] -
@ Angela
i've tried to edit this script, but when it seems to work in the first part then in the second part i get an error which instead in the original wks script works fine
the error is requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: ht*ps://xxxxx/licenses
@ 2nHxWW6GkN1l91
thanks for your effort, really appreciated. I will try it soon and then i will let you know if it works. thanks
about compare i use np++ with compare plug-inLast edited by whs912km; 6th Sep 2024 at 10:58.
Similar Threads
-
edit old l3.py for new pywidevine
By whs912km in forum Video Streaming DownloadingReplies: 12Last Post: 28th Jul 2024, 12:16 -
pywidevine key
By aletaladro in forum Video Streaming DownloadingReplies: 6Last Post: 16th Jul 2024, 16:44 -
pywidevine wks-key
By aletaladro in forum Video Streaming DownloadingReplies: 1Last Post: 11th Jul 2024, 14:32 -
Download tool which supports WKS-Keys/pywidevine or cloud
By pimboli in forum Video Streaming DownloadingReplies: 7Last Post: 27th Nov 2023, 09:17 -
help with pywidevine
By killua in forum Video Streaming DownloadingReplies: 1Last Post: 12th Jul 2023, 01:56