Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to deal with m3u8 without links in uri #311

Closed
RevealedSoulEven opened this issue Jan 25, 2023 · 13 comments
Closed

How to deal with m3u8 without links in uri #311

RevealedSoulEven opened this issue Jan 25, 2023 · 13 comments

Comments

@RevealedSoulEven
Copy link

RevealedSoulEven commented Jan 25, 2023

#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=187909,RESOLUTION=640x360
hls/360/main.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=158770,RESOLUTION=426x240
hls/240/main.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=310500,RESOLUTION=1280x720
hls/720/main.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=201372,RESOLUTION=854x480
hls/480/main.m3u8

as seen in this m3u8 file the uri can't be specified as a link.
How to download this type of file? Even it's possible to download using 1dm app in android

@RevealedSoulEven
Copy link
Author

{'media_sequence': None, 'is_variant': True, 'is_endlist': False, 'is_i_frames_only': False, 'is_independent_segments': False, 'playlist_type': None, 'playlists': [{'uri': 'hls/360/main.m3u8', 'stream_info': {'bandwidth': 187909, 'resolution': '640x360'}}, {'uri': 'hls/240/main.m3u8', 'stream_info': {'bandwidth': 158770, 'resolution': '426x240'}}, {'uri': 'hls/720/main.m3u8', 'stream_info': {'bandwidth': 310500, 'resolution': '1280x720'}}, {'uri': 'hls/480/main.m3u8', 'stream_info': {'bandwidth': 201372, 'resolution': '854x480'}}], 'segments': [], 'iframe_playlists': [], 'media': [], 'keys': [], 'rendition_reports': [], 'skip': {}, 'part_inf': {}, 'session_data': [], 'session_keys': [], 'segment_map': [], 'version': 3}

This is the data I get

@bbayles
Copy link
Contributor

bbayles commented Jan 25, 2023

Use the absolute_uri attribute.

>>> import m3u8
>>> playlist = m3u8.load('http://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8')
>>> playlist.playlists[0].absolute_uri
http://cph-p2p-msl.akamaized.net/hls/live/2000341/test/level_0.m3u8

If you loaded the multivariant playlist from text rather than a URL, use urljoin.

>>> from urllib.parse import urljoin
>>> urljoin('https://example.org', 'hls/360/main.m3u8')
https://example.org/hls/360/main.m3u8

@RevealedSoulEven
Copy link
Author

RevealedSoulEven commented Jan 25, 2023

Alright, the absolute_uri doesn't worked for me

But getting to the second point I added /hls/720/main.m3u8 at last of the url and I got this

[link removed]

But I have no idea how to deal with it

@bbayles
Copy link
Contributor

bbayles commented Jan 25, 2023

Use the same trick with urljoin to turn those .ts items into URLs.

@RevealedSoulEven
Copy link
Author

Yes but I think that this .ts file is encrypted

@bbayles
Copy link
Contributor

bbayles commented Jan 25, 2023

You'll have to download the key and decrypt the .ts files.

Something like this:

import m3u8
import requests
from urllib.parse import urljoin
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

base_url = '...'  # Your URL here
playlist_text = '...'  # Your text here

parsed_playlist = m3u8.loads(playlist_text)
seq_no = parsed_playlist.media_sequence or 0

key_data = {}

for n, segment in enumerate(parsed_playlist.segments, seq_no):
    # Save the key for this segment if we don't have it already
    key_url = segment.key.uri
    if key_url not in key_data:
        key_data[key_url] = requests.get(key_url).content

    # Download the encrypted segment
    segment_url = urljoin(base_url, segment.uri)
    segment_data = requests.get(segment.key.uri).content

    # The initialization vector is either given in the playlist or is the sequence number
    iv = segment.key.iv or n.to_bytes(16, 'big')

    # Decrypt with the key and IV
    cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
    decryptor = cipher.decryptor()
    decrypted_data = decryptor.update(segment_data) + decryptor.finalize()

    # Do something with the decrypted data

That's probably not going to work verbatim, but those are the right steps.

@RevealedSoulEven
Copy link
Author

RevealedSoulEven commented Jan 25, 2023 via email

@RevealedSoulEven
Copy link
Author

Thanks for your support, I've managed to key the key and will try decrypting it soon.

thanks a lot

@RevealedSoulEven
Copy link
Author

but the code that you sent is using key as string
and the cipher module is giving error that it needs bytes

@bbayles
Copy link
Contributor

bbayles commented Jan 25, 2023

Try: iv = segment.key.iv or n.to_bytes(16, 'big') instead of what was there before.

@RevealedSoulEven
Copy link
Author

NameError                                 Traceback (most recent call last)
Input In [5], in <cell line: 30>()
     45 cipher = Cipher(algorithms.AES(key_data[key_url]), modes.CBC(iv))
     46 decryptor = cipher.decryptor()
---> 47 decrypted_data = decryptor.update(ts) + decryptor.finalize()
     49 # Do something with the decrypted data
     50 print(decrypted_data)

NameError: name 'ts' is not defined

@RevealedSoulEven
Copy link
Author

@bbayles

@RevealedSoulEven
Copy link
Author

II managed to do this and got the decrypted .ts file and it's playable. Thanks for your support sir

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants