VideoHelp Forum




Closed Thread
Results 1 to 11 of 11
  1. Hi guys,

    I tried different methods to download a video from RTL Play, with no success so far...

    The link to the video (site requires login) is:
    https://www.rtlplay.be/rtl-info-19h-p_8553/rtl-info-19-heures-17-03-24-c_13060570

    Any suggestion to solve this issue is very welcome. Thanks!

  2. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Code:
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/7/3/3/733fa22e3084dcfe5041b9a7676f3f6ff33cd8d2/static/13060570_45ac1622cd59e0850d31e366f7e72f10_web_dash_upTo540p_540p_vbr_cae_drm_software.mpd" --key fe1a9855ba37381ba7c2f70b6eba1238:554d1b2b12bb01659a32341284d402f6 -M format=mkv
    I dunno if there are other hidden resolutions. 540p seems kinda low.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]

  3. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Here is the downloader for https://www.rtlplay.be . It works only for free videos that don't have geographic restrictions. In theory, it should work for those as well if you have a good IP, but I don't know for sure because I couldn't test it (even with a free VPN). The script requires a mail/password.

    Code:
    import json
    import re
    import urllib.parse
    
    import requests
    from pywidevine.cdm import Cdm
    from pywidevine.device import Device
    from pywidevine.pssh import PSSH
    
    EMAIL = 'YOUR_EMAIL'
    PASSWORD = 'YOUR_PASSWORD'
    
    COOKIE_URL = 'https://cdn.cookielaw.org/consent/{consent_id}/{resource}'
    LAYOUT_URL = "https://layout.6cloud.fr/front/v1/rtlbe/m6group_web/main/token-web-3/video/{video_id}/layout"
    JWT_URL = 'https://front-auth.6cloud.fr/v2/platforms/m6group_web/getJwt'
    LOGIN_URL = 'https://accounts.eu1.gigya.com/accounts.login'
    TOKEN_URL = "https://drm.6cloud.fr/v1/customers/rtlbe/platforms/m6group_web/services/rtlbe_rtl_info/users/{user_id}/videos/{video_id}/upfront-token"
    
    
    def get_api_key():
        consent_id = re.search(
            r'data-domain-script="([^"]*)"',
            requests.get("https://www.rtlplay.be").content.decode()
        ).group(1)
    
        response = json.loads(requests.get(
            COOKIE_URL.format(consent_id=consent_id, resource=f'{consent_id}.json')
        ).content.decode())
    
        consent_ids = [rule["Id"] for rule in response["RuleSet"]]
        response = json.loads(requests.get(
            COOKIE_URL.format(consent_id=consent_id, resource=f'{consent_ids[0]}/fr.json')
        ).content.decode())
    
        api_keys = []
        for group in response["DomainData"]["Groups"]:
            for cookie in group["FirstPartyCookies"]:
                if "gigya" not in cookie["Host"]:
                    continue
                api_keys.append(cookie["Name"])
    
        api_key = api_keys[0]
        return api_key[api_key.index("_") + 1:]
    
    
    API_KEY = get_api_key()
    RES_PRIORITY = {"sd": 0, "hd": 1}
    LICENSE_URL = "https://lic.drmtoday.com/license-proxy-widevine/cenc/"
    WVD_FILE = "./device_wvd_file.wvd"
    
    
    def get_auth_info():
        response = json.loads(requests.post(
            LOGIN_URL,
            headers={'Content-Type': 'application/x-www-form-urlencoded'},
            data=f'loginID={urllib.parse.quote(EMAIL)}&password={PASSWORD}&sessionExpiration=-2&APIKey={API_KEY}&format=json'
        ).content.decode())
        user_id = response["UID"]
    
        jwt_token = json.loads(requests.get(JWT_URL, headers={
            'X-Customer-Name': 'rtlbe',
            'x-auth-device-id': 'x-auth-device-id',
            'X-Auth-gigya-uid': user_id,
            'X-Auth-gigya-signature': response["UIDSignature"],
            'X-Auth-gigya-signature-timestamp': response["signatureTimestamp"]
        }).content.decode())["token"]
        return user_id, jwt_token
    
    
    USER_ID, JWT_TOKEN = get_auth_info()
    
    
    def format_manifest(manifest):
        split_path = "/rtl.be/"
        base_url, path_url = manifest.split("?")[0].split(split_path)
        base_url = base_url.split("/resource/")[0]
        base_url = "https://rtlbe.vod" + base_url[base_url.index("."):]
        return f"{base_url}{split_path}{path_url}"
    
    
    def get_video_data(source_url, format_mpd=False):
        video_id = re.search(
            r"(c_[^_]+)$", source_url
        ).group(1).replace("c_", "clip_")
    
        video_token = json.loads(requests.get(
            TOKEN_URL.format(user_id=USER_ID, video_id=video_id),
            headers={'Authorization': f'Bearer {JWT_TOKEN}'}
        ).content.decode())["token"]
    
        response = json.loads(requests.get(
            LAYOUT_URL.format(video_id=video_id),
            headers={'Authorization': f'Bearer {JWT_TOKEN}'}
        ).content.decode())
    
        if "geoBlocked" in str(response):
            print("VPN Failure")
            exit(0)
    
        manifests = []
        for block in response["blocks"]:
            if ".mpd" not in str(block):
                continue
    
            try:
                for item in block["content"]["items"]:
                    item_content = item["itemContent"]
                    if "video" not in item_content.keys():
                        continue
    
                    video_content = item_content["video"]
                    if video_content["id"] != video_id:
                        continue
    
                    for asset in video_content["assets"]:
                        if asset["video_container"] != "mpd" or asset["format"] != "dashcenc":
                            continue
    
                        manifest = (asset["quality"].lower(), asset["path"])
                        if manifest not in manifests:
                            manifests.append(manifest)
            except:
                pass
    
        if len(manifests) == 0:
            print("No MPD found for: ", source_url)
            exit(0)
        manifest = sorted(manifests, key=lambda m: RES_PRIORITY[m[0]], reverse=True)[0][1]
    
        if format_mpd:
            manifest = format_manifest(manifest)
        try:
            pssh_value = str(min(re.findall(
                r'<cenc:pssh\b[^>]*>(.*?)</cenc:pssh>',
                requests.get(manifest).content.decode()
            ), key=len))
        except:
            return manifest, None, None
        return manifest, pssh_value, video_token
    
    
    def get_keys(pssh_value, video_token):
        if pssh_value is None:
            return []
    
        pssh = PSSH(pssh_value)
        device = Device.load(WVD_FILE)
        cdm = Cdm.from_device(device)
        cdm_session_id = cdm.open()
    
        challenge = cdm.get_license_challenge(cdm_session_id, pssh)
        licence = requests.post(
            LICENSE_URL, data=challenge,
            headers={'x-dt-auth-token': video_token}
        )
        licence.raise_for_status()
        licence = json.loads(licence.content.decode())["license"]
    
        keys = []
        cdm.parse_license(cdm_session_id, licence)
        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, format_mpd=False):
        manifest, pssh_value, video_token = get_video_data(source_url, format_mpd)
        keys = get_keys(pssh_value, video_token)
    
        if len(keys) == 0:
            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://www.rtlplay.be/rtl-info-19h-p_8553/rtl-info-19-heures-19-03-24-c_13060945",
        "https://www.rtlplay.be/francois-lembrouille-le-best-ouf-p_9043/embrouilles-dinterieures-c_11932445",
        "https://www.rtlplay.be/linvite-de-7h50-p_8655/georges-louis-bouchez-20-03-c_13060982",
        "https://www.rtlplay.be/le-good-morning-p_8661/emission-du-19-03-c_13060858",
        "https://www.rtlplay.be/francois-pirette-p_11851/francois-pirette-les-annees-vhs-du-06-03-c_13058955"
    ]
    for s in SOURCE_URLS:
        print(get_download_command(s, format_mpd=True))
    Output:
    Code:
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/5/b/1/5b113d633a6658b8ddf74843405061f47bbf0d01/static/13060945_b836123e75b7e4c7f80e7990b3892f87_web_dash_upTo1080p_720p_vbr_cae_drm_hardware.mpd" --key d480f359451b601d8d6b6e5657b364dc:c6567ab778d6588896d15c4eb4cd5b45 -M format=mkv
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/d/a/f/daf8a3aa75e55ebcb9a30abe06e4f856d197269bd85118b33bc12caa6520ff6a/daf8a3aa75e55ebcb9a30abe06e4f856d197269bd85118b33bc12caa6520ff6a_web_drm_hd_dash_v2.ism/Manifest.mpd" --key 921dc2f5ff4ff9feb16e199cfe35ec4c:52d25bcf90d6be5ffe3691e9b7b37781 -M format=mkv
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/2/6/f/26feb0b27c2a297682feba4a695ec6aeefe31814/static/13060982_15b7a6898a124a1c43a7ccc53b82f56a_web_dash_upTo1080p_720p_vbr_cae_drm_hardware.mpd" --key 98fdd687785249e6e4b2eb6fc933674e:880c0129475246322cb4ea2dfa09cf7e -M format=mkv
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/2/0/c/20c20ec63c57a9bd33d8ed5e7aa2bcb7eca496f8/static/13060858_3a33d1f042d9942bd26ab265f8a587fe_web_dash_upTo1080p_720p_vbr_cae_drm_hardware.mpd" --key 6013c17f099ecec0fd70a92c6f8b6420:2959a43e8be2a249b1db4bc91db07a81 -M format=mkv
    N_m3u8DL-RE.exe "https://rtlbe.vod.6cloud.fr/rtl.be/output/6/a/b/6ab387bd809d394897b0a54bfca8585249f95096/static/13058955_93d98bf4647aea2475e3f6b3f086b62b_web_dash_upTo1080p_720p_vbr_cae_drm_hardware.mpd" --key 3a3213735e0aaf481b4859af232915d1:85ab638cd08f5aaa87315632983e0a6d -M format=mkv
    I managed to find the manifest for the highest resolution by using their API but it's kinda useless if you can't decrypt the content. The key you get works for resolutions lower than 720p (in some cases it works even for 720p but rarely). I don't know if I'm doing something wrong with the license call or after a certain date, they added L1 for newer videos at higher resolutions. Maybe someone can shed some light on this issue.

    If it fails for a specific video, try changing "format_mpd=True" to False. I added a way in which the manifest URL can be changed to get rid of its original query parameters that can expire so you could share the download command without being restricted to a timeframe. But if you're using the script just for yourself, you can set it to be always False.

    Edit: I noticed that the manifest file has multiple pssh values for different resolutions. However, even if you use the pssh corresponding to the highest resolution, you still get the same key that doesn't work.
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 22nd Mar 2024 at 03:59.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]

  4. Thanks for your reply! But I have to say I'm totally lost. I've zero expertise with code

  5. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Originally Posted by Kiwaki View Post
    But I have to say I'm totally lost. I've zero expertise with code
    Then stick to the manual way. You can find more info on the sticky threads (all of them).

    Here's your 540p requested video. https://www.transfernow.net/dl/20240322fsjmZdwg
    Maybe someone else can get 720p for you. I tested the key and it doesn't work.
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 22nd Mar 2024 at 07:53.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]

  6. Hi,

    Thanx for your script 2nHxWW6GkN1l916N3ayz8HQoi. I just tried it and got this error. All the other scripts found here (ITV, C4, boltgeneric) work correctly. Any idea what the problem is?

    C:\Users\Me\WKS-KEYS\rtlplay.py", line 6, in <module>
    from pywidevine.cdm import Cdm
    ModuleNotFoundError: No module named 'pywidevine.cdm'

    Maybe it's related to the wvd file which is not in the right place? (I saw in your script a line WVD_FILE = "./device_wvd_file.wvd") I never needed it until now, everything worked with the 2 files device client id blob and device private key. I added the wvd file with the 2 mentioned above (here: C:\Users\Me\WKS-KEYS\pywidevine\L3\cdm\devices\android_generic)

    If it helps, here's my pywidevine version: pywidevine version 1.8.0

  7. Originally Posted by pouki2 View Post
    Hi,

    Thanx for your script 2nHxWW6GkN1l916N3ayz8HQoi. I just tried it and got this error. All the other scripts found here (ITV, C4, boltgeneric) work correctly. Any idea what the problem is?

    C:\Users\Me\WKS-KEYS\rtlplay.py", line 6, in <module>
    from pywidevine.cdm import Cdm
    ModuleNotFoundError: No module named 'pywidevine.cdm'

    Maybe it's related to the wvd file which is not in the right place? (I saw in your script a line WVD_FILE = "./device_wvd_file.wvd") I never needed it until now, everything worked with the 2 files device client id blob and device private key. I added the wvd file with the 2 mentioned above (here: C:\Users\Me\WKS-KEYS\pywidevine\L3\cdm\devices\android_generic)

    If it helps, here's my pywidevine version: pywidevine version 1.8.0
    Move rtlplay.py to another directory and run it again. You unfortunately placed it in WKS-KEYS directory, which has its own pywidevine folder, so your rtlplay.py is mistakenly using that local (and old) pywidevine library instead.

  8. It works, thank you white_snake.

    I tried to adapt it for 6play (it's the same company as RTL) which uses the same license by modifying the script but without success. I'll keep looking for what's wrong

  9. Originally Posted by 2nHxWW6GkN1l916N3ayz8HQoi View Post
    Originally Posted by Kiwaki View Post
    But I have to say I'm totally lost. I've zero expertise with code
    Then stick to the manual way. You can find more info on the sticky threads (all of them).

    Here's your 540p requested video. https://www.transfernow.net/dl/20240322fsjmZdwg
    Maybe someone else can get 720p for you. I tested the key and it doesn't work.
    Thanks so much! Very kind from you.

  10. Thanks a lot for the 720p version! Very kind from you.




Similar Threads

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