VideoHelp Forum



Support our site by donate $5 directly to us Thanks!!!

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



+ Reply to Thread
Results 1 to 26 of 26
  1. Banned
    Join Date
    Apr 2022
    Location
    Hong Kong
    Search Comp PM
    Guys, I met an HTTP 416 error when trying to get a key from GlobalTV,
    it's a Canadian platform and it's free to watch, you need to have a Canadian IP to stream:
    https://watch.globaltv.com/series/7a8be44c-9f6b-11ee-9a7f-0242ac110004/episode/GLOB005...0/?action=play
    It seems that the data I sent out were right, however, the server returned a "eyJzdGF0dXMiOiI0MTYifQ==" (status: 416) error even if I have modified the script.
    Would anyone give me a hand? Thank you in advance!

    PSSH (Generated from Key ID):
    Code:
    AAAAMnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABISEBUVSmIdxnd6DjqgSZqNv34=
    License URL:
    Code:
    https://global.corusappservices.com/authorization/widevine/getresourcekey
    Headers:
    Code:
    headers = {
        'authority': 'global.corusappservices.com',
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'cache-control': 'no-cache',
        'content-type': 'application/json',
        'dnt': '1',
        'origin': 'https://watch.globaltv.com',
        'pragma': 'no-cache',
        'referer': 'https://watch.globaltv.com/series/7a8be44c-9f6b-11ee-9a7f-0242ac110004/episode/GLOB0057108600000000/?action=play',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'cross-site',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    }
    The data (payload) format:
    Image
    [Attachment 76399 - Click to enlarge]

    (Some info related to my own CDM pixelated)

    License Response:
    Code:
    [+] License Response: eyJzdGF0dXMiOiI0MTYifQ==
    The key (Got from an extension) is:
    Code:
    15154a621dc6777a0e3aa0499a8dbf7e:1b42f778d54ea2e8b9a548a0da0dd13e
    P.S. Private messages are also appreciated!
    Last edited by CrymanChen; 24th Jan 2024 at 08:53.
    Quote Quote  
  2. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Try this PSSH from eme logger:
    Code:
    AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG
    Edit: I tested the PSSH with the script and it returns the key. So that's the right PSSH.

    Code:
    import json
    
    import requests
    from pywidevine.cdm import Cdm
    from pywidevine.device import Device
    from pywidevine.pssh import PSSH
    
    
    def str_to_dict(str_value):
        return json.loads(str_value)
    
    
    def dict_to_str(dict_value):
        return json.dumps(dict_value)
    
    
    LICENSE_URL = "https://global.corusappservices.com/authorization/widevine/getresourcekey"
    PSSH_VALUE = "AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG"
    WVD_FILE = "./device_wvd_file.wvd"
    LICENSE_HEADERS = {
        'content-type': 'application/json'
    }
    
    JSON_PAYLOAD = '<INSERT_RAW_JSON_PAYLOAD>'
    
    pssh = PSSH(PSSH_VALUE)
    device = Device.load(WVD_FILE)
    cdm = Cdm.from_device(device)
    session_id = cdm.open()
    challenge = cdm.get_license_challenge(session_id, pssh)
    
    custom_payload = str_to_dict(JSON_PAYLOAD)
    custom_payload["license_request_data"] = list(challenge)
    
    licence = requests.post(LICENSE_URL, data=dict_to_str(custom_payload), headers=LICENSE_HEADERS)
    licence.raise_for_status()
    cdm.parse_license(session_id, licence.content)
    
    for key in cdm.get_keys(session_id):
        print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}")
    cdm.close(session_id)
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 24th Jan 2024 at 09:16.
    Quote Quote  
  3. yes, incorrect pssh will return error 416, dont calculate pssh from KID, at least in globaltv.
    Quote Quote  
  4. Banned
    Join Date
    Apr 2022
    Location
    Hong Kong
    Search Comp PM
    Cool! Thanks @2nHxWW6GkN1l916N3ayz8HQoi and @shellcmd
    I didn't use the PSSH from EME logger because that one is too long to be a so-called "Widevine PSSH".
    Image
    [Attachment 76404 - Click to enlarge]
    Quote Quote  
  5. long pssh is PR+wdvne. need to be convert

    share here your long pssh
    Quote Quote  
  6. Originally Posted by CrymanChen View Post
    Cool! Thanks @2nHxWW6GkN1l916N3ayz8HQoi and @shellcmd
    I didn't use the PSSH from EME logger because that one is too long to be a so-called "Widevine PSSH".
    Image
    [Attachment 76404 - Click to enlarge]
    If you look closely, you'll notice the final part (in bold) looks exactly like a WideVine PSSH:

    Code:
    AAACvnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAp6eAgAAAQABAJQCPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBZAGsAbwBWAEYAYwBZAGQAZQBuAGMATwBPAHEAQgBKAG0AbwAyAC8AZgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AE0ANABxAHMAbABmAEIAegBtAGsAUQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC0AbABpAGMAZQBuAHMAZQAuAGQAcgBtAC4AdABlAGMAaABuAG8AbABvAGcAeQAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4AAAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG
    In facts, pssh-box.py gives:

    Code:
    PSSH Box v0
      System ID: PlayReady 9a04f079-9840-4286-ab92-e65be0885f95
      PSSH Data (size: 670):
        PlayReady Data:
          Record (size 660):
            Record Type: Rights Management Header (1)
            Record XML:
              <WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0"><DATA><PROTECTINFO><KEYLEN>16</KEYLEN><ALGID>AESCTR</ALGID></PROTECTINFO><KID>YkoVFcYdencOOqBJmo2/fg==</KID><CHECKSUM>M4qslfBzmkQ=</CHECKSUM><LA_URL>https://playready-license.drm.technology/rightsmanager.asmx</LA_URL></DATA></WRMHEADER>
    PSSH Box v0
      System ID: Widevine edef8ba9-79d6-4ace-a3c8-27dcd51d21ed
      PSSH Data (size: 28):
        Widevine Data:
          Content ID: 474C4F4230303537313038363030303030303030
          Protection Scheme: b'cenc'
    Quote Quote  
  7. Member
    Join Date
    Jan 2024
    Location
    Canada
    Search PM
    Hi,

    I'm very much a neophyte when it comes to all this, but I'm also looking to download a show from GlobalTV.

    This is the show: https://watch.globaltv.com/series/f791dee6-c510-11ed-9ff0-0242ac110005/episode/FOOD005...0/?action=play

    I've managed to find the PSSH by using the EME logger. Like the poster above noted, I was able to gather it's the 80-character tail end that begins with the strand "AAAA." In this case:

    Code:
    AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEZPT0QwMDUzNDQ2OTEwMDAwMDAwSOPclZsG
    I have the licence (which is the same as OP's):

    Code:
    https://global.corusappservices.com/authorization/widevine/getresourcekey
    But when I use CDRM-Project, I get Error 415. I'm not entering any information in "Headers" box and I don't know who to input it. Any help, via PM or here, would be more than appreciated.

    Code:
    :authority:global.corusappservices.com
    :method:POST
    :path:/authorization/widevine/getresourcekey
    :scheme:https
    Accept:*/*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8
    Content-Length:348
    Content-Type:application/json
    Origin:https://watch.globaltv.com
    Referer:https://watch.globaltv.com/
    Sec-Ch-Ua:"Not_A Brand";v="8", "Chromium";v="120", "Brave";v="120"
    Sec-Ch-Ua-Mobile:?0
    Sec-Ch-Ua-Platform:"Windows"
    Sec-Fetch-Dest:empty
    Sec-Fetch-Mode:cors
    Sec-Fetch-Site:cross-site
    Sec-Gpc:1
    User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
    Quote Quote  
  8. Banned
    Join Date
    Apr 2022
    Location
    Hong Kong
    Search Comp PM
    @lomero OK, here you are.
    Code:
    AAACvnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAp6eAgAAAQABAJQCPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBZAGsAbwBWAEYAYwBZAGQAZQBuAGMATwBPAHEAQgBKAG0AbwAyAC8AZgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AE0ANABxAHMAbABmAEIAegBtAGsAUQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC0AbABpAGMAZQBuAHMAZQAuAGQAcgBtAC4AdABlAGMAaABuAG8AbABvAGcAeQAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4AAAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG
    @white_snake Thanks, I'll check it later by myself.
    Quote Quote  
  9. Originally Posted by McEwan View Post
    Hi,

    I'm very much a neophyte when it comes to all this, but I'm also looking to download a show from GlobalTV.

    This is the show: https://watch.globaltv.com/series/f791dee6-c510-11ed-9ff0-0242ac110005/episode/FOOD005...0/?action=play

    I've managed to find the PSSH by using the EME logger. Like the poster above noted, I was able to gather it's the 80-character tail end that begins with the strand "AAAA." In this case:

    Code:
    AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEZPT0QwMDUzNDQ2OTEwMDAwMDAwSOPclZsG
    I have the licence (which is the same as OP's):

    Code:
    https://global.corusappservices.com/authorization/widevine/getresourcekey
    But when I use CDRM-Project, I get Error 415. I'm not entering any information in "Headers" box and I don't know who to input it. Any help, via PM or here, would be more than appreciated.

    Code:
    :authority:global.corusappservices.com
    :method:POST
    :path:/authorization/widevine/getresourcekey
    :scheme:https
    Accept:*/*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8
    Content-Length:348
    Content-Type:application/json
    Origin:https://watch.globaltv.com
    Referer:https://watch.globaltv.com/
    Sec-Ch-Ua:"Not_A Brand";v="8", "Chromium";v="120", "Brave";v="120"
    Sec-Ch-Ua-Mobile:?0
    Sec-Ch-Ua-Platform:"Windows"
    Sec-Fetch-Dest:empty
    Sec-Fetch-Mode:cors
    Sec-Fetch-Site:cross-site
    Sec-Gpc:1
    User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36


    your key(540p, maybe 1080p or higher, but i dont know the android tv api):
    Code:
    --key 6597c506c407d531738857ebe52c0a9e:c778d92d1dceffa4374b95fc49543753
    and you need read this thread carefully, in second floor @2nHxWW6GkN1l916N3ayz8HQoi had public the script, everyone can use it locally.

    because json payload in the request body, and no online sites(getwv/cdrm/keysdb) can handle json payload, so you expect online sites give you key, it is almost impossible.
    Quote Quote  
  10. Originally Posted by CrymanChen View Post
    @lomero OK, here you are.
    Code:
    AAACvnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAp6eAgAAAQABAJQCPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBZAGsAbwBWAEYAYwBZAGQAZQBuAGMATwBPAHEAQgBKAG0AbwAyAC8AZgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AE0ANABxAHMAbABmAEIAegBtAGsAUQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC0AbABpAGMAZQBuAHMAZQAuAGQAcgBtAC4AdABlAGMAaABuAG8AbABvAGcAeQAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4AAAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG
    white_snake already reply to your question, anyway here your pssh:

    Code:
    AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG
    Image
    [Attachment 76420 - Click to enlarge]
    Quote Quote  
  11. Originally Posted by 2nHxWW6GkN1l916N3ayz8HQoi View Post
    Code:
    import json
    import requests
    from pywidevine.cdm import Cdm
    from pywidevine.device import Device
    from pywidevine.pssh import PSSH
    
    
    def str_to_dict(str_value):
        return json.loads(str_value)
    
    
    def dict_to_str(dict_value):
        return json.dumps(dict_value)
    
    
    LICENSE_URL = "https://global.corusappservices.com/authorization/widevine/getresourcekey"
    PSSH_VALUE = "AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEdMT0IwMDU3MTA4NjAwMDAwMDAwSOPclZsG"
    WVD_FILE = "./device_wvd_file.wvd"
    LICENSE_HEADERS = {
        'content-type': 'application/json'
    }
    
    JSON_PAYLOAD = '<INSERT_RAW_JSON_PAYLOAD>'
    
    pssh = PSSH(PSSH_VALUE)
    device = Device.load(WVD_FILE)
    cdm = Cdm.from_device(device)
    session_id = cdm.open()
    challenge = cdm.get_license_challenge(session_id, pssh)
    
    custom_payload = str_to_dict(JSON_PAYLOAD)
    custom_payload["license_request_data"] = list(challenge)
    
    licence = requests.post(LICENSE_URL, data=dict_to_str(custom_payload), headers=LICENSE_HEADERS)
    licence.raise_for_status()
    cdm.parse_license(session_id, licence.content)
    
    for key in cdm.get_keys(session_id):
        print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}")
    cdm.close(session_id)
    someone can edit for WKS-KEYS tool ? i've tried to run but the first error is about pywidevine.cdm
    so, i've edit from pywidevine.L3.cdm import cdm
    but now i have another error: ModuleNotFoundError: No module named 'pywidevine.device'
    import Device is like on l3.py from pywidevine.L3.cdm import cdm, deviceconfig ?
    Quote Quote  
  12. right, and i suggest use new version of pywidevine. wks-keys is classic but a bit outdated. you just need pip install pywidevine and then you can run the script anywhere in your pc. if you still insist wks-keys, better use it with python venv.
    Last edited by shellcmd; 25th Jan 2024 at 06:08.
    Quote Quote  
  13. no understand: i've used pip install pywidevine
    download all modules, but when i can run the script above i have the same error because i can use wks-keys tool only ...
    Last edited by whs912km; 6th Feb 2024 at 02:44.
    Quote Quote  
  14. Originally Posted by whs912km View Post
    anyway no understand: i've used pip install pywidevine
    download all modules, but when i can run the script above i have the same error because i can use wks-keys tool only ...
    You also need a generic L3 pywidevine script and a .wvd file. You can find everything you need here: https://forum.videohelp.com/threads/411862-Beyond-WKS-KEYS
    Quote Quote  
  15. Originally Posted by shellcmd View Post
    right, and i suggest use new version of pywidevine. wks-keys is classic but a bit outdated. you just need pip install pywidevine and then you can run the script anywhere in your pc. if you still insist wks-keys, better use it with python venv
    after pip install pywidevine my wks-keys tool stop to work ...

    Code:
    ModuleNotFoundError: No module named 'pywidevine.L3'
    how to solve ?
    Quote Quote  
  16. Originally Posted by whs912km View Post
    Originally Posted by shellcmd View Post
    right, and i suggest use new version of pywidevine. wks-keys is classic but a bit outdated. you just need pip install pywidevine and then you can run the script anywhere in your pc. if you still insist wks-keys, better use it with python venv
    after pip install pywidevine my wks-keys tool stop to work ...

    Code:
    ModuleNotFoundError: No module named 'pywidevine.L3'
    how to solve ?
    two choice:
    1: if you decide to use new pywidevine, then you just delete wks-keys forever or use it in python venv
    2: if you decide to use old pywidevine(wks-keys), then you give up new pywidevine, you can pip uninstall pywidevine, or use new pywidevine version in python venv.

    i think you had give up new pywidevine, so just pip uninstall pywidevine
    Quote Quote  
  17. Originally Posted by McEwan View Post
    Hi,

    I'm very much a neophyte when it comes to all this, but I'm also looking to download a show from GlobalTV.

    This is the show: https://watch.globaltv.com/series/f791dee6-c510-11ed-9ff0-0242ac110005/episode/FOOD005...0/?action=play

    I've managed to find the PSSH by using the EME logger. Like the poster above noted, I was able to gather it's the 80-character tail end that begins with the strand "AAAA." In this case:

    Code:
    AAAAPHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABwiFEZPT0QwMDUzNDQ2OTEwMDAwMDAwSOPclZsG
    I have the licence (which is the same as OP's):

    Code:
    https://global.corusappservices.com/authorization/widevine/getresourcekey
    But when I use CDRM-Project, I get Error 415. I'm not entering any information in "Headers" box and I don't know who to input it. Any help, via PM or here, would be more than appreciated.

    Code:
    :authority:global.corusappservices.com
    :method:POST
    :path:/authorization/widevine/getresourcekey
    :scheme:https
    Accept:*/*
    Accept-Encoding:gzip, deflate, br
    Accept-Language:en-US,en;q=0.8
    Content-Length:348
    Content-Type:application/json
    Origin:https://watch.globaltv.com
    Referer:https://watch.globaltv.com/
    Sec-Ch-Ua:"Not_A Brand";v="8", "Chromium";v="120", "Brave";v="120"
    Sec-Ch-Ua-Mobile:?0
    Sec-Ch-Ua-Platform:"Windows"
    Sec-Fetch-Dest:empty
    Sec-Fetch-Mode:cors
    Sec-Fetch-Site:cross-site
    Sec-Gpc:1
    User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
    as always TubeDigger FTW

    https://gofile.io/d/W2Ep6J
    Quote Quote  
  18. GlobalTV still 720p max? or is there a 1080p available.
    Quote Quote  
  19. Originally Posted by shellcmd View Post
    1: if you decide to use new pywidevine, then you just delete wks-keys forever or use it in python venv
    2: if you decide to use old pywidevine(wks-keys), then you give up new pywidevine, you can pip uninstall pywidevine, or use new pywidevine version in python venv.

    i think you had give up new pywidevine, so just pip uninstall pywidevine
    no mate, already done. i'm not interested to new pywidevine, wks is enough for me
    but with pip uninstall pywidevine (already done) i have this on run l3.py:
    Code:
    D:\WKS-KEYS\l3.py
    Traceback (most recent call last):
      File "D:\WKS-KEYS\l3.py", line 3, in <module>
        from pywidevine.L3.cdm import cdm, deviceconfig
      File "D:\WKS-KEYS\pywidevine\L3\cdm\cdm.py", line 10, in <module>
        from pywidevine.L3.cdm.formats import wv_proto2_pb2 as wv_proto2
      File "D:\WKS-KEYS\pywidevine\L3\cdm\formats\wv_proto2_pb2.py", line 33, in <module>
        _descriptor.EnumValueDescriptor(
      File "C:\Program Files\Python38\lib\site-packages\google\protobuf\descriptor.py", line 789, in __new__
        _message.Message._CheckCalledFromGeneratedFile()
    TypeError: Descriptors cannot be created directly.
    If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
    If you cannot immediately regenerate your protos, some other possible workarounds are:
     1. Downgrade the protobuf package to 3.20.x or lower.
     2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
    
    More information: https://developers.google.com/protocol-buffers/docs/news/2022-05-06#python-updates
    Quote Quote  
  20. Banned
    Join Date
    Apr 2022
    Location
    Hong Kong
    Search Comp PM
    Originally Posted by whs912km View Post
    no mate, already done. i'm not interested to new pywidevine, wks is enough for me
    but with pip uninstall pywidevine (already done) i have this on run l3.py:
    Code:
    D:\WKS-KEYS\l3.py
    Traceback (most recent call last):
      File "D:\WKS-KEYS\l3.py", line 3, in <module>
        from pywidevine.L3.cdm import cdm, deviceconfig
      File "D:\WKS-KEYS\pywidevine\L3\cdm\cdm.py", line 10, in <module>
        from pywidevine.L3.cdm.formats import wv_proto2_pb2 as wv_proto2
      File "D:\WKS-KEYS\pywidevine\L3\cdm\formats\wv_proto2_pb2.py", line 33, in <module>
        _descriptor.EnumValueDescriptor(
      File "C:\Program Files\Python38\lib\site-packages\google\protobuf\descriptor.py", line 789, in __new__
        _message.Message._CheckCalledFromGeneratedFile()
    TypeError: Descriptors cannot be created directly.
    If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
    If you cannot immediately regenerate your protos, some other possible workarounds are:
     1. Downgrade the protobuf package to 3.20.x or lower.
     2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
    
    More information: https://developers.google.com/protocol-buffers/docs/news/2022-05-06#python-updates
    Check your protobuf version (3.20.x or lower).
    Code:
    pip install protobuf==3.19.5
    And why not start another thread? You're talking about python script installations from the beginning...
    It has nothing to do with my question
    Quote Quote  
  21. Banned
    Join Date
    Apr 2022
    Location
    Hong Kong
    Search Comp PM
    Originally Posted by pauli3 View Post
    GlobalTV still 720p max? or is there a 1080p available.
    Original .mpd file gives utmost 720p
    Image
    [Attachment 76489 - Click to enlarge]


    But I'm interested in how to get 1080p manifest just like those 9c9media videos.
    Quote Quote  
  22. Originally Posted by CrymanChen View Post

    Check your protobuf version (3.20.x or lower).
    Code:
    pip install protobuf==3.19.5
    And why not start another thread? You're talking about python script installations from the beginning...
    It has nothing to do with my question
    yep, it work. thanks. and sorry for "your" thread
    Quote Quote  
  23. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Here is the downloader for https://watch.globaltv.com . It works only on free videos. Canadian IP and local cdm needed.

    Code:
    import base64
    import json
    import re
    
    import fake_useragent
    import requests
    import xmltodict
    from pywidevine.cdm import Cdm
    from pywidevine.device import Device
    from pywidevine.pssh import PSSH
    
    WVD_FILE = "device_wvd_file.wvd"
    
    SIGN_URL = 'https://global.corusappservices.com/authorization/untrusted/sign'
    AUTHENTICATE_URL = 'https://global.corusappservices.com/authentication/authenticate'
    AUTHORIZE_RESOURCE_URL = 'https://global.corusappservices.com/authorization/authorizeresource'
    GET_STREAM_URL = 'https://global.corusappservices.com/media/getstream'
    LICENSE_URL = "https://global.corusappservices.com/authorization/widevine/getresourcekey"
    
    USER_AGENT = fake_useragent.UserAgent(os="windows").chrome
    
    
    def get_session_data():
        response = requests.post(
            SIGN_URL, headers={'User-Agent': USER_AGENT},
            json={
                'path': '/authentication/authenticate',
                'data': {
                    'transaction_type': 'authenticate',
                    'authenticator_id': 'anonymous',
                    'application_id': 'application_id',
                    'platform_id': 'web_widevine'
                }
            }
        )
        response = json.loads(response.content.decode())["data"]["session_data"]
    
        response = json.loads(base64.b64decode(json.loads(requests.post(
            AUTHENTICATE_URL, headers={'User-Agent': USER_AGENT},
            json={'session_data': response}
        ).content.decode())["session_data"].split(".")[1] + "==").decode())
        return response
    
    
    SESSION_DATA = get_session_data()
    
    
    def get_pssh_from_init(init_url):
        content = requests.get(init_url).content
        offsets = []
        offset = 0
    
        while True:
            offset = content.find(b'pssh', offset)
            if offset == -1:
                break
    
            size = int.from_bytes(content[offset - 4:offset], byteorder='big')
            pssh_offset = offset - 4
    
            offsets.append(content[pssh_offset:pssh_offset + size])
            offset += size
    
        pssh_list = [base64.b64encode(wv_offset).decode() for wv_offset in offsets]
        for pssh in pssh_list:
            if 70 < len(pssh) < 190:
                return pssh
        return None
    
    
    def get_init_from_mpd(mpd_url):
        mpd_content = requests.get(mpd_url).content.decode()
        mpd_content = xmltodict.parse(mpd_content)["MPD"]["Period"]
        base_url = mpd_content["BaseURL"]
        if type(mpd_content["AdaptationSet"]) is not list:
            mpd_content["AdaptationSet"] = [mpd_content["AdaptationSet"]]
    
        best_content = None
        for content in mpd_content["AdaptationSet"]:
            if content["@contentType"] != "video":
                continue
    
            if best_content is None:
                best_content = content
                continue
            if int(content["@maxHeight"]) > int(best_content["@maxHeight"]):
                best_content = content
                continue
            elif int(content["@maxHeight"]) == int(best_content["@maxHeight"]):
                if int(content["@maxBandwidth"]) > int(best_content["@maxBandwidth"]):
                    best_content = content
                    continue
    
        mpd_content = best_content
        init_url = mpd_content["SegmentTemplate"]["@initialization"]
        if type(mpd_content["Representation"]) is not list:
            mpd_content["Representation"] = [mpd_content["Representation"]]
    
        best_content = None
        for content in mpd_content["Representation"]:
            if best_content is None:
                best_content = content
                continue
            if int(content["@height"]) > int(best_content["@height"]):
                best_content = content
                continue
            elif int(content["@height"]) == int(best_content["@height"]):
                if int(content["@bandwidth"]) > int(best_content["@bandwidth"]):
                    best_content = content
                    continue
    
        init_url = init_url.replace("$RepresentationID$", best_content["@id"])
        init_url = '/'.join(mpd_url.split('/')[:-1]) + "/" + base_url + init_url
        return init_url
    
    
    def get_manifest(content_id):
        response = json.loads(requests.post(
            SIGN_URL, headers={'User-Agent': USER_AGENT},
            json={
                'path': '/authorization/authorizeresource',
                'data': {
                    'duid': SESSION_DATA['duid'], 'puid': SESSION_DATA['puid'],
                    'resource_id': content_id
                }
            }
        ).content.decode())["data"]["session_data"]
    
        response = json.loads(base64.b64decode(json.loads(requests.post(
            AUTHORIZE_RESOURCE_URL, headers={'User-Agent': USER_AGENT},
            json={'session_data': response}
        ).content.decode())["session_data"].split(".")[1] + "==").decode())
        if response["status"] == '401':
            print("VPN Failure. Need Canadian IP.")
            exit(0)
        response = response["data"]["authorization_token"]
    
        auth_token = response
        response = json.loads(base64.b64decode(json.loads(requests.post(
            GET_STREAM_URL, json={
                'authorization_token': response,
                'platform': 'web_widevine'
            }
        ).content.decode())["session_data"].split(".")[1] + "==").decode())
        return response["resources"]["streaming_url"], auth_token
    
    
    def get_pssh_from_manifest(manifest):
        return get_pssh_from_init(get_init_from_mpd(manifest))
    
    
    def get_video_data(source_url):
        if "/episode/" in source_url:
            content_id = re.search(r"/episode/([^/]+)", source_url).group(1)
        elif "/channel/" in source_url:
            content_id = re.search(r"/channel/([^/]+)", source_url).group(1)
        else:
            print(f"Unknown URL format for: {source_url}")
            exit(0)
    
        manifest, auth_token = get_manifest(content_id)
        pssh_value = get_pssh_from_manifest(manifest)
        return manifest, pssh_value, auth_token
    
    
    def get_keys(pssh_value, auth_token):
        if pssh_value is None:
            return []
        try:
            device = Device.load(WVD_FILE)
        except:
            return []
    
        pssh_value = PSSH(pssh_value)
        cdm = Cdm.from_device(device)
        cdm_session_id = cdm.open()
    
        challenge = cdm.get_license_challenge(cdm_session_id, pssh_value)
        licence = requests.post(
            LICENSE_URL, json={
                'license_request_data': list(challenge),
                'authorization_token': auth_token
            }
    
        )
        licence.raise_for_status()
        cdm.parse_license(cdm_session_id, licence.content)
    
        keys = []
        for key in cdm.get_keys(cdm_session_id):
            if "CONTENT" in key.type:
                keys += [f"{key.kid.hex}:{key.key.hex()}"]
        cdm.close(cdm_session_id)
        return keys
    
    
    def get_download_command(source_url):
        manifest, pssh, auth_token = get_video_data(source_url)
        keys = get_keys(pssh, auth_token)
    
        if len(keys) == 0:
            if pssh is not None:
                return f"Need local CDM (in WVD format) for {source_url}"
            return f'N_m3u8DL-RE.exe "{manifest}" -M format=mkv'
        return f'N_m3u8DL-RE.exe "{manifest}" {" ".join([f"--key {k}" for k in keys])} -M format=mkv'
    
    
    SOURCE_URLS = [
        "https://watch.globaltv.com/series/32666562/episode/GLOB0053686160000000",
        "https://watch.globaltv.com/series/0572b6bc-e7a0-11ea-9dc3-0242ac110003/episode/GLOB0057056220000000",
        "https://watch.globaltv.com/series/1304382019507/episode/GLOB0056989290000000",
        "https://watch.globaltv.com/series/852506179691/episode/HGTV0054879080000000",
        "https://watch.globaltv.com/series/759427139648/episode/HGTV0055596150000100",
        "https://watch.globaltv.com/channel/215422c9-d1b9-4009-aaca-32e403f22b01",
        "https://watch.globaltv.com/channel/6bfb7f13-9d9d-4211-9c50-fb56330e4ccd",
    ]
    
    for s in SOURCE_URLS:
        print(get_download_command(s))
    Output:
    Code:
    N_m3u8DL-RE.exe "https://globaltvvideo.corusdigitaldev.com/globaltv/content/vod/vms/GlobalTV/GLOB0053686160000000/1664985317_drm_462c4e9c-b653-4969-aeed-9c6ca8d07303.ism/.mpd" --key ceee734173ebd7bd5f76c2eea87bf1a2:e1e44971defc2cdbea6ed9c3d50776bc -M format=mkv
    N_m3u8DL-RE.exe "https://globaltvvideo.corusdigitaldev.com/globaltv/content/vod/vms/GlobalTV/GLOB0057056220000000/1712361153_drm_80e7b1f3-ebb1-4c53-a758-7b15f4b1a395.ism/.mpd" --key b9d202ed2e5652ca1e4955049be0a6de:9ea57fdc678ebbd7520aaa121e576f24 -M format=mkv
    N_m3u8DL-RE.exe "https://globaltvvideo.corusdigitaldev.com/globaltv/content/vod/vms/GlobalTV/GLOB0056989290000000/1712019648_drm_dff1b883-4752-4e54-9183-57051c24e24e.ism/.mpd" --key 565fa4c9fb39b2934cb245dcfddf364f:2f0e36f80d9b4e67103aaaedce8aba98 -M format=mkv
    N_m3u8DL-RE.exe "https://hgtvvideo.corusdigitaldev.com/hgtv/content/vod/vms/HGTV/HGTV0054879080000000/1711156085_drm_75fe17de-51ba-4046-bfc7-e677bc8627ca.ism/.mpd" --key 2ce670ad4055e1a22c3b4cf186a80d92:e4f842d39da9f0c09399bb670410dc60 -M format=mkv
    N_m3u8DL-RE.exe "https://hgtvvideo.corusdigitaldev.com/hgtv/content/vod/vms/HGTV/HGTV0055596150000100/1711576098_drm_930261df-2a38-447d-a8fb-06a66a1cd366.ism/.mpd" --key e0d1db3698d2dd54b5cd4abbafd59ed5:6eb72bc134a63449e6eaa98f9d605ece -M format=mkv
    N_m3u8DL-RE.exe "https://live.corusdigitaldev.com/groupb/live/215422c9-d1b9-4009-aaca-32e403f22b01/live.isml/.mpd" -M format=mkv
    N_m3u8DL-RE.exe "https://live.corusdigitaldev.com/groupa/live/6bfb7f13-9d9d-4211-9c50-fb56330e4ccd/live.isml/.mpd" -M format=mkv
    Videos can get deleted from their site so the demo URLs may not work in the future. Make sure you can actually watch what you want to download. The download command doesn't need a VPN so don't forget to turn it off to avoid wasting data. The livestream channels don't even have DRM and for those download commands you should add other parameters according to what you wanna do with that livestream.

    I didn't manage to find some hidden mpd for 1080p using their web api unfortunately.

    Edit: This script has been added and extended in the widefrog tool so I won't maintain it here. Any relevant updates will take place in the support thread.
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 21st May 2024 at 04:28.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  
  24. Is anyone archiving pepe's amazing automation scripts?
    click click2
    If I/my posts ever helped you, and you want to give back, send me a private message!
    Quote Quote  
  25. i think they should be on Github so others can contribute.
    discord=notaghost9997
    Quote Quote  
  26. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Originally Posted by [ss]vegeta View Post
    Is anyone archiving pepe's amazing automation scripts?
    Originally Posted by notaghost View Post
    i think they should be on Github so others can contribute.
    I actually like it more when they're spread on random (but relevant) forum posts. I think it's more rewarding for users that do actually bother to search the forum. That's why I didn't bother with Github/Bitbucket/etc nor am I advertising/mentioning them. Just posted them once and that's it. But anyone else is free to do whatever they want with those scripts. I don't consider them to be mine from the moment I posted them publicly. It's for the community and to help others start writing their own scripts. It's not rocket science since they're all just data scrapers.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  



Similar Threads

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