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
Page 1 of 2
1 2 LastLast
Results 1 to 30 of 33
  1. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Hi
    I have a type link,

    https://iframe.mediadelivery.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/1280x720/video.drm?contextId=8c8d29d8-f9c5-4fe9-971b-6344fedbd324

    For the first time I see links like this, I would like to know if there is any way to download them

    Image
    [Attachment 74754 - Click to enlarge]


    the video does not show even an mpd or m3u8 link

    hand with this, will you?
    Quote Quote  
  2. HTTP ERROR 401

    need original video link

    or link like this one:
    Code:
    https://iframe.mediadelivery.net/embed/7xxx2/e3xxxx27f-xxx-xxxxx-xxxxx
    Quote Quote  
  3. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by lomero View Post
    HTTP ERROR 401

    need original video link

    or link like this one:
    Code:
    https://iframe.mediadelivery.net/embed/7xxx2/e3xxxx27f-xxx-xxxxx-xxxxx

    in agre
    https://turkgunesi.com/yazgi-02/
    Quote Quote  
  4. Image
    [Attachment 74759 - Click to enlarge]


    i think this is the right video link

    https://iframe.mediadelivery.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video.dr...0-15df7cf6f241
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:5
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-KEY:METHOD=AES-128,URI="https://video-1223.mediadelivery.net/.drm/58ea6a9c-cc22-477d-bbb0-15df7cf6f241/640x360.drmkey?v=0",IV=0x3230386236373936636331332 d346433
    #EXTINF:4.800000,
    https://vz-735d06b5-ce8.b-cdn.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video0....0-15df7cf6f241
    #EXTINF:4.800000,
    https://vz-735d06b5-ce8.b-cdn.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video1....0-15df7cf6f241
    #EXTINF:2.400000,
    https://vz-735d06b5-ce8.b-cdn.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video2....0-15df7cf6f241
    #EXT-X-KEY:METHOD=AES-128,URI="https://video-1223.mediadelivery.net/.drm/58ea6a9c-cc22-477d-bbb0-15df7cf6f241/640x360.drmkey?v=1",IV=0x3230386236373936636331332 d346433
    #EXTINF:4.800000,
    https://vz-735d06b5-ce8.b-cdn.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video3....0-15df7cf6f241
    #EXTINF:4.800000,
    https://vz-735d06b5-ce8.b-cdn.net/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f/640x360/video4....0-15df7cf6f241
    but AES-128 Encrypted
    Quote Quote  
  5. search embed url in referer
    HTML Code:
    https://iframe.mediadelivery.net/embed/64132/dc7000xxxxxxxxxxxxxe928f?autoplay=true
    delete last useless part '?autoplay=true'

    and use py script to download with yt-dlp

    Image
    [Attachment 74760 - Click to enlarge]
    Quote Quote  
  6. Member
    Join Date
    Dec 2021
    Location
    england
    Search Comp PM
    Code:
    #!/usr/bin/env python3
    
    import re
    import sys
    from hashlib import md5
    from html import unescape
    from random import random
    from urllib.parse import urlparse
    
    import requests
    import yt_dlp
    
    
    class iframeVideoDownloader:
        # user agent and platform related headers
        user_agent = {
            'sec-ch-ua':
                '"Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"',
            'sec-ch-ua-mobile':
                '?0',
            'sec-ch-ua-platform':
                '"Linux"',
            'user-agent':
                'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
        }
        session = requests.session()
        session.headers.update(user_agent)
    
        def __init__(self,
                     referer='https://127.0.0.1/',
                     embed_url='',
                     name='',
                     path=''):
            self.referer = referer if referer else sys.exit(1)
            self.embed_url = embed_url if embed_url else sys.exit(1)
            self.guid = urlparse(embed_url).path.split('/')[-1]
            self.headers = {
                'embed': {
                    'authority': 'iframe.mediadelivery.net',
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'pragma': 'no-cache',
                    'referer': referer,
                    'sec-fetch-dest': 'iframe',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'cross-site',
                    'upgrade-insecure-requests': '1',
                },
                'ping|activate': {
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'origin': 'https://iframe.mediadelivery.net',
                    'pragma': 'no-cache',
                    'referer': 'https://iframe.mediadelivery.net/',
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-site',
                },
                'playlist': {
                    'authority': 'iframe.mediadelivery.net',
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'pragma': 'no-cache',
                    'referer': embed_url,
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-origin',
                }
            }
            embed_response = self.session.get(embed_url,
                                              headers=self.headers['embed'])
            embed_page = embed_response.text
            try:
                self.server_id = re.search(
                    r'https://video-(.*?)\.mediadelivery\.net', embed_page).group(1)
            except AttributeError:
                sys.exit(1)
            self.headers['ping|activate'].update(
                {'authority': f'video-{self.server_id}.mediadelivery.net'})
            search = re.search(r'contextId=(.*?)&secret=(.*?)"', embed_page)
            self.context_id, self.secret = search.group(1), search.group(2)
            if name:
                self.file_name = f'{name}.mp4'
            else:
                file_name_unescaped = re.search(r'og:title" content="(.*?)"',
                                                embed_page).group(1)
                file_name_escaped = unescape(file_name_unescaped)
                self.file_name = re.sub(r'\.[^.]*$.*', '.mp4', file_name_escaped)
            self.path = path if path else '~/Videos/'
    
        def prepare_dl(self) -> str:
    
            def ping(time: int, paused: str, res: str):
                md5_hash = md5(
                    f'{self.secret}_{self.context_id}_{time}_{paused}_{res}'.encode(
                        'utf8')).hexdigest()
                params = {
                    'hash': md5_hash,
                    'time': time,
                    'paused': paused,
                    'chosen_res': res
                }
                self.session.get(
                    f'https://video-{self.server_id}.mediadelivery.net/.drm/{self.context_id}/ping',
                    params=params,
                    headers=self.headers['ping|activate'])
    
            def activate():
                self.session.get(
                    f'https://video-{self.server_id}.mediadelivery.net/.drm/{self.context_id}/activate',
                    headers=self.headers['ping|activate'])
    
            def main_playlist():
                params = {'contextId': self.context_id, 'secret': self.secret}
                response = self.session.get(
                    f'https://iframe.mediadelivery.net/{self.guid}/playlist.drm',
                    params=params,
                    headers=self.headers['playlist'])
                resolutions = re.findall(r'RESOLUTION=(.*)', response.text)[::-1]
                if not resolutions:
                    sys.exit(2)
                else:
                    return resolutions[0]  # highest resolution, -1 for lowest
    
            def video_playlist():
                params = {'contextId': self.context_id}
                self.session.get(
                    f'https://iframe.mediadelivery.net/{self.guid}/{resolution}/video.drm',
                    params=params,
                    headers=self.headers['playlist'])
    
            ping(time=0, paused='true', res='0')
            activate()
            resolution = main_playlist()
            video_playlist()
            for i in range(0, 29, 4):  # first 28 seconds, arbitrary
                ping(time=i + round(random(), 6),
                     paused='false',
                     res=resolution.split('x')[-1])
            self.session.close()
            return resolution
    
        def download(self):
            resolution = self.prepare_dl()
            url = [
                f'https://iframe.mediadelivery.net/{self.guid}/{resolution}/video.drm?contextId={self.context_id}'
            ]
            ydl_opts = {
                'http_headers': {
                    'Referer': self.embed_url,
                    'User-Agent': self.user_agent['user-agent']
                },
                'concurrent_fragment_downloads': 10,
                # 'external_downloader': 'aria2c'
                'nocheckcertificate': True,
                'outtmpl': self.file_name,
                'restrictfilenames': True,
                'windowsfilenames': True,
                'nopart': True,
                'paths': {
                    'home': self.path,
                    'temp': f'.{self.file_name}/',
                },
                'retries': float('inf'),
                'extractor_retries': float('inf'),
                'fragment_retries': float('inf'),
                'skip_unavailable_fragments': False,
                'no_warnings': True,
            }
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download(url)
    
    
    if __name__ == '__main__':
        video = iframeVideoDownloader(
            # insert the referer between the quotes below (address of your webpage)
            referer='https://iframe.mediadelivery.net/',
            # paste your embed link
            embed_url='https://iframe.mediadelivery.net/embed/64132/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f',
            # you can override file name, no extension
            name="video",
            # you can override download path
            path=r"")
        # video.session.close()
        video.download()
    download other video so change embed link in line 182
    Quote Quote  
  7. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by lomero View Post
    search embed url in referer
    HTML Code:
    https://iframe.mediadelivery.net/embed/64132/dc7000xxxxxxxxxxxxxe928f?autoplay=true
    delete last useless part '?autoplay=true'

    and use py script to download with yt-dlp

    Image
    [Attachment 74760 - Click to enlarge]

    I use the code yt-dlp python yt_dlp -F -v https://iframe.mediadelivery.net/embed/64132/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f
    have this error

    Code:
    yt_dlp.networking.exceptions.CertificateVerifyError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002)
    grateful for your help
    Quote Quote  
  8. Use "yt-dlp --no-check-certificates".

    Tip: "yt-dlp --help" tells you about all available options; it's really useful to at least once skim through.
    Quote Quote  
  9. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by Obo View Post
    Use "yt-dlp --no-check-certificates".

    Tip: "yt-dlp --help" tells you about all available options; it's really useful to at least once skim through.
    It tells me that the url is not supported


    Code:
    ERROR: Unsupported URL: https://iframe.mediadelivery.net/embed/64132/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f 
    Traceback (most recent call last): 
      File "C:\Users\jorge\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\YoutubeDL.py", line 1567, in 
    wrapper
        return func(self, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\jorge\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\YoutubeDL.py", line 1702, in 
    __extract_info
        ie_result = ie.extract(url)
                    ^^^^^^^^^^^^^^^
      File "C:\Users\jorge\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 715, in extract
        ie_result = self._real_extract(url)
                    ^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\jorge\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\generic.py", line 2575, in _real_extract
        raise UnsupportedError(url)
    yt_dlp.utils.UnsupportedError: Unsupported URL: https://iframe.mediadelivery.net/embed/64132/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f
    
    PS C:\jorge\yt-dlp-master\yt-dlp-master>
    Quote Quote  
  10. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by iamghost View Post
    Code:
    #!/usr/bin/env python3
    
    import re
    import sys
    from hashlib import md5
    from html import unescape
    from random import random
    from urllib.parse import urlparse
    
    
            # you can override download path
            path=r"")
        # video.session.close()
        video.download()
    download other video so change embed link in line 182
    It's the only thing that has helped me, I thank you a world
    Quote Quote  
  11. i have yt-dlp installed but getting this error when I run the script. also a error shows in the file about _.
    \b-cdn-drm-vod-dl.py", line 11, in <module>
    import yt_dlp
    ModuleNotFoundError: No module named 'yt_dlp'
    Quote Quote  
  12. Member
    Join Date
    Dec 2021
    Location
    england
    Search Comp PM
    Pip install yt-dlp
    Quote Quote  
  13. already do this getting the same error. how to run the script properly
    C:\yt-dlp>Pip install yt-dlp
    WARNING: Ignoring invalid distribution -ip (c:\python310\lib\site-packages)
    Requirement already satisfied: yt-dlp in c:\python310\lib\site-packages (2023.10.13)
    Requirement already satisfied: mutagen in c:\python310\lib\site-packages (from yt-dlp) (1.47.0)
    Requirement already satisfied: pycryptodomex in c:\python310\lib\site-packages (from yt-dlp) (3.19.0)
    Requirement already satisfied: websockets in c:\python310\lib\site-packages (from yt-dlp) (12.0)
    Requirement already satisfied: certifi in c:\python310\lib\site-packages (from yt-dlp) (2023.7.22)
    Requirement already satisfied: brotli in c:\python310\lib\site-packages (from yt-dlp) (1.1.0)
    WARNING: Ignoring invalid distribution -ip (c:\python310\lib\site-packages)
    Quote Quote  
  14. can someone check if the link is working or not? is it possible to download from the link?
    https://iframe.mediadelivery.net/play/104942/68702c7b-dad2-4dea-a85a-e36a185d2a01
    Quote Quote  
  15. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    what kind of codder its thad of thsi site ahaha its realy crayz man

    i have just try to download samthing bud imposible for me to

    https://turkgunesi.com/destan-2/
    Quote Quote  
  16. Member
    Join Date
    Dec 2021
    Location
    england
    Search Comp PM
    just done download with script (above)
    Image
    [Attachment 74816 - Click to enlarge]
    Quote Quote  
  17. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    Originally Posted by iamghost View Post
    Code:
    #!/usr/bin/env python3
    
    import re
    import sys
    from hashlib import md5
    from html import unescape
    from random import random
    from urllib.parse import urlparse
    
    import requests
    import yt_dlp
    
    
    class iframeVideoDownloader:
        # user agent and platform related headers
        user_agent = {
            'sec-ch-ua':
                '"Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"',
            'sec-ch-ua-mobile':
                '?0',
            'sec-ch-ua-platform':
                '"Linux"',
            'user-agent':
                'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
        }
        session = requests.session()
        session.headers.update(user_agent)
    
        def __init__(self,
                     referer='https://127.0.0.1/',
                     embed_url='',
                     name='',
                     path=''):
            self.referer = referer if referer else sys.exit(1)
            self.embed_url = embed_url if embed_url else sys.exit(1)
            self.guid = urlparse(embed_url).path.split('/')[-1]
            self.headers = {
                'embed': {
                    'authority': 'iframe.mediadelivery.net',
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'pragma': 'no-cache',
                    'referer': referer,
                    'sec-fetch-dest': 'iframe',
                    'sec-fetch-mode': 'navigate',
                    'sec-fetch-site': 'cross-site',
                    'upgrade-insecure-requests': '1',
                },
                'ping|activate': {
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'origin': 'https://iframe.mediadelivery.net',
                    'pragma': 'no-cache',
                    'referer': 'https://iframe.mediadelivery.net/',
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-site',
                },
                'playlist': {
                    'authority': 'iframe.mediadelivery.net',
                    'accept': '*/*',
                    'accept-language': 'en-US,en;q=0.9',
                    'cache-control': 'no-cache',
                    'pragma': 'no-cache',
                    'referer': embed_url,
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-origin',
                }
            }
            embed_response = self.session.get(embed_url,
                                              headers=self.headers['embed'])
            embed_page = embed_response.text
            try:
                self.server_id = re.search(
                    r'https://video-(.*?)\.mediadelivery\.net', embed_page).group(1)
            except AttributeError:
                sys.exit(1)
            self.headers['ping|activate'].update(
                {'authority': f'video-{self.server_id}.mediadelivery.net'})
            search = re.search(r'contextId=(.*?)&secret=(.*?)"', embed_page)
            self.context_id, self.secret = search.group(1), search.group(2)
            if name:
                self.file_name = f'{name}.mp4'
            else:
                file_name_unescaped = re.search(r'og:title" content="(.*?)"',
                                                embed_page).group(1)
                file_name_escaped = unescape(file_name_unescaped)
                self.file_name = re.sub(r'\.[^.]*$.*', '.mp4', file_name_escaped)
            self.path = path if path else '~/Videos/'
    
        def prepare_dl(self) -> str:
    
            def ping(time: int, paused: str, res: str):
                md5_hash = md5(
                    f'{self.secret}_{self.context_id}_{time}_{paused}_{res}'.encode(
                        'utf8')).hexdigest()
                params = {
                    'hash': md5_hash,
                    'time': time,
                    'paused': paused,
                    'chosen_res': res
                }
                self.session.get(
                    f'https://video-{self.server_id}.mediadelivery.net/.drm/{self.context_id}/ping',
                    params=params,
                    headers=self.headers['ping|activate'])
    
            def activate():
                self.session.get(
                    f'https://video-{self.server_id}.mediadelivery.net/.drm/{self.context_id}/activate',
                    headers=self.headers['ping|activate'])
    
            def main_playlist():
                params = {'contextId': self.context_id, 'secret': self.secret}
                response = self.session.get(
                    f'https://iframe.mediadelivery.net/{self.guid}/playlist.drm',
                    params=params,
                    headers=self.headers['playlist'])
                resolutions = re.findall(r'RESOLUTION=(.*)', response.text)[::-1]
                if not resolutions:
                    sys.exit(2)
                else:
                    return resolutions[0]  # highest resolution, -1 for lowest
    
            def video_playlist():
                params = {'contextId': self.context_id}
                self.session.get(
                    f'https://iframe.mediadelivery.net/{self.guid}/{resolution}/video.drm',
                    params=params,
                    headers=self.headers['playlist'])
    
            ping(time=0, paused='true', res='0')
            activate()
            resolution = main_playlist()
            video_playlist()
            for i in range(0, 29, 4):  # first 28 seconds, arbitrary
                ping(time=i + round(random(), 6),
                     paused='false',
                     res=resolution.split('x')[-1])
            self.session.close()
            return resolution
    
        def download(self):
            resolution = self.prepare_dl()
            url = [
                f'https://iframe.mediadelivery.net/{self.guid}/{resolution}/video.drm?contextId={self.context_id}'
            ]
            ydl_opts = {
                'http_headers': {
                    'Referer': self.embed_url,
                    'User-Agent': self.user_agent['user-agent']
                },
                'concurrent_fragment_downloads': 10,
                # 'external_downloader': 'aria2c'
                'nocheckcertificate': True,
                'outtmpl': self.file_name,
                'restrictfilenames': True,
                'windowsfilenames': True,
                'nopart': True,
                'paths': {
                    'home': self.path,
                    'temp': f'.{self.file_name}/',
                },
                'retries': float('inf'),
                'extractor_retries': float('inf'),
                'fragment_retries': float('inf'),
                'skip_unavailable_fragments': False,
                'no_warnings': True,
            }
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download(url)
    
    
    if __name__ == '__main__':
        video = iframeVideoDownloader(
            # insert the referer between the quotes below (address of your webpage)
            referer='https://iframe.mediadelivery.net/',
            # paste your embed link
            embed_url='https://iframe.mediadelivery.net/embed/64132/dc70003f-3dc9-4ea0-851b-6a8e0a8e928f',
            # you can override file name, no extension
            name="video",
            # you can override download path
            path=r"")
        # video.session.close()
        video.download()
    download other video so change embed link in line 182


    wawww its works 100% big thanks

    just the python version must last
    Quote Quote  
  18. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    Originally Posted by iamghost View Post


    i get it work with your script,
    very great work..
    big thanks its fantastik ..
    Quote Quote  
  19. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    When trying to download it shows me this message

    yt_dlp.utils.DownloadError: ERROR: ffmpeg exited with code 3419392776

    I downloaded the previous videos without problems, with the script mentioned above
    Quote Quote  
  20. Member
    Join Date
    Dec 2021
    Location
    england
    Search Comp PM
    Url?
    Quote Quote  
  21. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by iamghost View Post
    Url?
    https://turkgunesi.com/yazgi-40/
    Quote Quote  
  22. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Originally Posted by Zabon View Post
    The GitHub script needs to be changed for hls aes I think. If you want a easy solution without caring at all about their joke of pinging mechanism, you can download this using Tubedigger or you can code your own tubedigger mini script for that page (so you won't pay a cent for that software if you aren't a fan of paid software). I checked for the first few fragments and they can be decrypted. Each fragment has a unique key though.
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 28th Feb 2024 at 10:43.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  
  23. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Yep. Seems I was right. I really have no idea if there are other resolutions hidden but from what I see at first glance 720p is the highest. They really went hardcore on that pinging mechanism there.

    Luckily you can throw their ping to the trash by injecting some JS code. If you have no idea what I'm talking about just skip the entire post and just get the download link at the end. First of all, find the function of interest that you can use to download each fragment (use Chrome to make it easier to edit stuff, I dunno how to get Firefox to auto-format page source code ). It is found in hls.min.js

    Code:
    onSuccess: function(e, i, n, a) {
    Outside of that function, you need to add some "global" declarations for the following variables. You'll have to figure out where to add them exactly.

    Code:
    var keyMap = new Map();
    var COUNT_KEYS = 213;
    The COUNT_KEYS variable can be found at the end of the m3u8 stream found in the network requests (in this case 720p).

    Code:
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video638.ts?v=212&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXT-X-KEY:METHOD=AES-128,URI="https://video-1366.mediadelivery.net/.drm/d64d2107-43dd-42c1-8379-eabfc69a8e4c/720p.drmkey?v=213",IV=0x3230386236373936636331332d346433
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video639.ts?v=213&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video640.ts?v=213&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:1.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video641.ts?v=213&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXT-X-ENDLIST
    720p.drmkey?v=213 is the last one.

    Moving on, the detected function (the onSucess one) contains some existing code which we're going to ignore completely. The code we're gonna add focuses on 2 parts: getting the video fragments and getting the keys. For some reason apparently at each refresh of the page that function receives different encrypted fragments with different keys (why though, I have no idea). Anyway, in theory, if you get those fragments with their respective keys, you can decrypt locally the m3u8 stream.

    The part that deals with getting the video fragments is put at the beginning of their function.

    Code:
    let videoNumber = e.url.match(/video(\d+)\.ts/i)[1];
    const fragmentBlob = new Blob([new Uint8Array(e.data)], {
    	type: 'application/octet-stream'
    });
    const downloadLink = document.createElement('a');
    downloadLink.href = URL.createObjectURL(fragmentBlob);
    downloadLink.download = "video" + videoNumber + ".ts";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
    So then the video can be played at 4x, 6x, 8x, whatever, and you're going to download the fragments very fast. Be careful, there is a limit so not too fast. I tried to find a clever way that can force it to the max but the arraybuffers used by them are detached. So manipulating them is a major headache to figure out (at least for me so I dunno).

    Then the getting the keys part is added at the end of the function.

    Code:
    let keyIndex = parseInt(t.decryptdata.uri.match(/\?v=(\d+)/i)[1]);
    keyMap[keyIndex] = t.decryptdata.key;
    
    if (keyIndex === COUNT_KEYS) {
    	let concatenatedArray = new Uint8Array();
    
    	for (let i = 0; i <= COUNT_KEYS; i++) {
    		concatenatedArray = new Uint8Array([...concatenatedArray, ...keyMap[i]]);
    	}
    
    	let batchBlob = new Blob([concatenatedArray], {
    		type: 'application/octet-stream'
    	});
    
    	let downloadLink = document.createElement('a');
    	downloadLink.href = URL.createObjectURL(batchBlob);
    	downloadLink.download = "keys.txt";
    	document.body.appendChild(downloadLink);
    	downloadLink.click();
    	document.body.removeChild(downloadLink);
    }
    Start the video. Raise the speed very high (5x-8x I think, you may use an addon for that speed). And at the end, you're gonna have all the fragments and all the keys into one single keys.txt file. Then use a script to split that keys.txt file into separated 16-byte keyINDEX.txt files.

    Code:
    import os
    
    
    def split_into_chunks(file_path, chunk_size):
        with open(file_path, 'rb') as file:
            index = 0
            while True:
                chunk = file.read(chunk_size)
                if not chunk:
                    break
                yield chunk, index
                index += 1
    
    
    def write_chunk_to_file(chunk, index, output_dir):
        file_path = os.path.join(output_dir, f'key{index}.txt')
        with open(file_path, 'wb') as file:
            file.write(chunk)
    
    
    def split_file_into_chunks(input_file, output_dir, chunk_size=16):
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
    
        for chunk, index in split_into_chunks(input_file, chunk_size):
            write_chunk_to_file(chunk, index, output_dir)
    
    
    input_file = 'keys.txt'
    output_directory = 'output_keys'
    split_file_into_chunks(input_file, output_directory)
    Then you're gonna have to obtain a sample m3u8 file from the network requests. Just copy and paste the output. In this case, it is a 720p m3u8 stream.

    Code:
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:4
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-KEY:METHOD=AES-128,URI="https://video-1366.mediadelivery.net/.drm/d64d2107-43dd-42c1-8379-eabfc69a8e4c/720p.drmkey?v=0",IV=0x3230386236373936636331332d346433
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video0.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video1.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video2.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXT-X-KEY:METHOD=AES-128,URI="https://video-1366.mediadelivery.net/.drm/d64d2107-43dd-42c1-8379-eabfc69a8e4c/720p.drmkey?v=1",IV=0x3230386236373936636331332d346433
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video3.ts?v=1&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    https://vz-735d06b5-ce8.b-cdn.net/050528f1-19b8-4c8a-8a69-f865339c1e4c/720p/video4.ts?v=1&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    .... etc etc
    You're gonna have to replace all http links related to keys looking like "drmkey?v=INDEX" with "keyINDEX.txt". So it becomes a local resource.

    Code:
    import re
    
    
    def replace_links(input_file, output_file):
        with open(input_file, 'r') as fin, open(output_file, 'w') as fout:
            for line in fin:
                matches = re.findall(r'(https://[^"\']+drmkey\?v=(\d+)[^"\']*)', line)
                for link, number in matches:
                    line = line.replace(link, f'key{number}.txt')
                fout.write(line)
    
    
    input_file = 'input.m3u8'
    output_file = 'output.m3u8'
    replace_links(input_file, output_file)
    Then using a simple find all + replace in a text editor, remove the base URL of all videoINDEX.ts fragments. So they become all local resources. Doesn't matter if you keep the query parameter, just get rid of the URL.
    Code:
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:4
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXT-X-KEY:METHOD=AES-128,URI="key0.txt",IV=0x3230386236373936636331332d346433
    #EXTINF:4.000000,
    video0.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    video1.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    video2.ts?v=0&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXT-X-KEY:METHOD=AES-128,URI="key1.txt",IV=0x3230386236373936636331332d346433
    #EXTINF:4.000000,
    video3.ts?v=1&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    video4.ts?v=1&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    #EXTINF:4.000000,
    video5.ts?v=1&resolution=720p&server=1366&contextId=d64d2107-43dd-42c1-8379-eabfc69a8e4c
    etc.etc...
    Image
    [Attachment 77325 - Click to enlarge]


    And finally in the end.

    Code:
    N_m3u8DL-RE.exe output.m3u8
    And you successfully downloaded your video. The download link: https://www.transfernow.net/dl/20240228283v6Q9Z

    I really don't know if there is an easier way. I guess you could do this with tubedigger if you bought it. By using this approach you could totally ignore whatever modifications they could introduce in the future to the existing ping mechanism.
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  
  24. Marvelous job pepe! I applaud you.
    click click2
    If I/my posts ever helped you, and you want to give back, send me a private message!
    Quote Quote  
  25. Originally Posted by [ss]vegeta View Post
    Marvelous job pepe! I applaud you.
    Agreed! That was one hell of a ride!
    Quote Quote  
  26. Search, Learn, Download! Karoolus's Avatar
    Join Date
    Oct 2022
    Location
    Belgium
    Search Comp PM
    I've read it three times and I'm still scratching my head.
    Quote Quote  
  27. Member
    Join Date
    Jul 2022
    Location
    Freezer Planet
    Search PM
    Originally Posted by 2nHxWW6GkN1l916N3ayz8HQoi View Post

    Code:
    N_m3u8DL-RE.exe output.m3u8
    And you successfully downloaded your video. The download link: https://www.transfernow.net/dl/20240228283v6Q9Z

    I really don't know if there is an easier way. I guess you could do this with tubedigger if you bought it. By using this approach you could totally ignore whatever modifications they could introduce in the future to the existing ping mechanism.
    some things I don't understand, but I'll try
    thank you
    Quote Quote  
  28. @2nHxWW6GkN1l916N3ayz8HQoiGreat write up. Thanks for sharing


    You have so far demonstrated a proficiency in python, bash shell, powershell, curl, sed ,awk, grep, xargs, tr and now javascript. You continue to amaze.


    Have a questiion.


    You wrote


    You're gonna have to replace all http links related to keys looking like "drmkey?v=INDEX" with "keyINDEX.txt".

    Can you post the contents of the "keyINDEX.txt"


    Thanks
    Quote Quote  
  29. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Originally Posted by [ss]vegeta View Post
    Marvelous job pepe! I applaud you.
    Originally Posted by white_snake View Post
    Agreed! That was one hell of a ride!
    Thank you both @vegeta and @white_snake for the kind words! To be fair, I don't think of this as something groundbreaking and I'll try to explain in a few words why (short answer, it is boring and cheap). Across the years I've seen many sites that use tricky convoluted ways like this to hide the video, I've seen the usual flow that happens when a solution is found.

    The site uses a dubious method/protocol etc. to protect the video against trivial tools (yt-dlp, N_m3u8, etc.) -> someone reverse-engineers that mechanism and posts it somewhere for the end-user to utilize -> the tool/script, etc. gets popular -> the site makes the dubious method even more dubious and convoluted -> .... -> cat/mouse never-ending game

    And I thought why would someone put themselves through that hell haha. Without any paid software, one could do this with minimal programming knowledge (obviously it is different from site to site, I just provide the general flow).

    The site uses the dubious method -> debug the code and look for relevant information -> know what to look for and find some magic function that deals with the video fragments -> inject js code -> refresh the page and max up the playback speed -> download all video fragments and other relevant data (depends on the case, this is just general) -> process the downloaded data -> final video done.

    So you just skip over whatever they're doing to protect that video. Of course, this line of thinking can be stopped and I've seen sites where it doesn't work. Some sites thought of this from the start, and some didn't. And to fix your site to defend the video from this strategy, would mean some serious restructuring of the code and rethinking of how the video is sent. And that is not trivial at all. There are ways to defend against this and ways that I'm not even aware of.

    Would that mean that iframe mediadelivery is going to start changing the code to avoid that? Well, I have a personal unproved theory of mine. If a method for downloading can't be widely used by the general public, then they probably won't bother at all. However, that is unproved and only time will tell. Looking forward to what they come up with since I like seeing new stuff. And if they fix it for good, it is what it is. Then only the reverse-engineering strategy remains and keeping it as private as possible.

    The nice thing is that this approach works on a good part of tricky sites. Kinda off topic but if someone is interested in seeing it applied in some other context, you could read:
    https://forum.videohelp.com/threads/412993-How-to-download-a-video-of-higher-quality-f...x)#post2719620

    I personally call it a funny name, the caveman approach, since you actually deal at almost the lowest level with that site. By digging into that messy obfuscated source code. There is a lower level than that and that involves WASM. But that's another topic and one I don't have a lot of experience in, unfortunately.

    Is it cheap? Oh, for sure, definitely haha, and quite boring. Is it effective? Yes. I think that Tubedigger uses the same line of thinking but I don't know for sure. I still think the proper solution to this problem is to fix the pinging script. That being said, my bad if I went on quite a ramble there.

    Originally Posted by Karoolus View Post
    I've read it three times and I'm still scratching my head.
    I'm sure you will figure it out eventually

    Originally Posted by Zabon View Post
    some things I don't understand, but I'll try
    thank you
    You're welcome. I personally advise you to wait for the ping script to be updated. Maybe someone (or even the author himself) can look into it. Very cool of MaZED-UP to provide this script that can be found here (I dunno if there are other solutions/pages):
    https://github.com/MaZED-UP/bunny-cdn-drm-video-dl

    I posted the solution more for people who do have an idea of what is going on with the source code. If you do try what I posted without some background knowledge, then I'm afraid I won't assist you. I really don't mean to sound rude but I honestly don't have the patience to deal with every little thing and explain from scratch everything (I kinda suck as a proper teacher). Kudos to the users that do have the patience! Hats off to them.

    Maybe someone can actually incorporate this into a browser addon or something else that semi-automates the task at least. However, I don't have the expertise necessary, nor the interest to do it.

    Originally Posted by jack_666 View Post
    Thanks for sharing


    You have so far demonstrated a proficiency in python, bash shell, powershell, curl, sed ,awk, grep, xargs, tr and now javascript. You continue to amaze.
    You're welcome, and again, thanks for the kind words @jack! I have to thank my former college professors for that knowledge. Much respect for teachers!

    Originally Posted by jack_666 View Post
    Have a questiion.


    Can you post the contents of the "keyINDEX.txt"


    Thanks
    Sure. I'll post the original m3u8 file, the final processed m3u8 file (both as txt so I can send them), and the full keys.txt file that contains all the keys appended. The size of keys.txt is 3424 bytes. 3424 / 16 = 214 (don't forget it starts from zero index). So you need to split into chunks the keys.txt file with the script I gave previously. 16-byte chunks because obviously, a key for hls aes 128 is 16 in size.

    keys.txt

    original_input.txt

    processed_output.txt

    I'll also post the encrypted video fragments in a zip if you wanna play with the encrypted stuff. I've seen that at every refresh of the page, you get a different videoINDEX.ts encrypted file and also a different keyINDEX for that ts file. I guess that they use some form of key rotation mechanism (I could be wrong though, needs some research).

    https://www.transfernow.net/dl/20240229VLPdAci4
    Last edited by 2nHxWW6GkN1l916N3ayz8HQoi; 29th Feb 2024 at 13:47.
    --[----->+<]>.++++++++++++.---.--------.
    [*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!