Downloading HLS Files on Android

Waqas Younis
Towards Dev
Published in
4 min readSep 6, 2023
Image capture by me, hope you like it :)

HLS is one of the top-used protocols for live and on-demand content. It uses adaptive bitrate, enhancing or reducing video quality depending on your internet speed.

In this tutorial, I will explain the formats of different HLS URLs and how to download them.

I am using sample links from this website: https://ottverse.com/free-hls-m3u8-test-urls/

Let’s take the first URL from the above blog post: https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8
If you visit this URL, the browser will download an M3U file, which when opened in a text editor looks like this:

#EXTM3U
#EXT-X-VERSION:1
## Created with Unified Streaming Platform (version=1.11.20-26889)

# variants
#EXT-X-STREAM-INF:BANDWIDTH=493000,CODECS="mp4a.40.2,avc1.66.30",RESOLUTION=224x100,FRAME-RATE=24
tears-of-steel-audio_eng=64008-video_eng=401000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=932000,CODECS="mp4a.40.2,avc1.66.30",RESOLUTION=448x200,FRAME-RATE=24
tears-of-steel-audio_eng=128002-video_eng=751000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1197000,CODECS="mp4a.40.2,avc1.77.31",RESOLUTION=784x350,FRAME-RATE=24
tears-of-steel-audio_eng=128002-video_eng=1001000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1727000,CODECS="mp4a.40.2,avc1.100.40",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR
tears-of-steel-audio_eng=128002-video_eng=1501000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2468000,CODECS="mp4a.40.2,avc1.100.40",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR
tears-of-steel-audio_eng=128002-video_eng=2200000.m3u8

# variants
#EXT-X-STREAM-INF:BANDWIDTH=68000,CODECS="mp4a.40.2"
tears-of-steel-audio_eng=64008.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=136000,CODECS="mp4a.40.2"
tears-of-steel-audio_eng=128002.m3u8

Anyway, let’s understand this code. It’s pretty straightforward, though.

The first line #EXTM3U tells that this is an M3U file. The second and third line mentions a little meta-data.

The actual story begins from #variants. From this line onward until the next #variants, it says all the different variants available for video and audio, and from the second #variants onwards, it mentions all the variants available for the audio.

You can literally read the #EXT-X-STREAM-INF: and understand what it is trying to explain. The figure following BANDWIDTH= tells, of course, bandwidth, similarly, you can read codecs, resolutions, frame-rate, video-range etc.

Now, once you have decided which variant you want to download, append the line following that line to the actual URL of the file after removing everything after last /.

Let’s say I choose the maximum resolution which is 1680x750 with bandwidth 2468000 . The line following is:

tears-of-steel-audio_eng=128002-video_eng=2200000.m3u8

So I append it to the base URL after removing everything next to last / .

So the new URL would become:

https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/tears-of-steel-audio_eng=128002-video_eng=2200000

Let’s visit this URL, and sorry if you were expecting a video, this is another M3U file, but don’t worry, we have made some progress.

Let’s look at the new file. It looks like:

#EXTM3U
#EXT-X-VERSION:1
## Created with Unified Streaming Platform (version=1.11.20-26889)
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-TARGETDURATION:4
#USP-X-TIMESTAMP-MAP:MPEGTS=900000,LOCAL=1970-01-01T00:00:00Z
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-1.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-2.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-3.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-4.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-5.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-6.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-7.ts
#EXTINF:4, no desc
tears-of-steel-audio_eng=128002-video_eng=2200000-8.ts
#...

Now, this file contains parts of the whole video in separate parts, and names of those parts are mentioned here. As you might have guessed, just append the part names to the base URL, and you will get your final video file, part file, I mean.

Here is what it looks like if I want to download the very first part

https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/tears-of-steel-audio_eng=128002-video_eng=2200000-1.ts

Just download all parts, one by one, to a single file, and you get the final video.

That’s it, most of the HLS.

But, there are cases where the M3U file is slightly different.

Like if you try that exact algo on the second URL from the samples, which is “https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8” you will not be able to download the file.

The second m3u file that we get from this URL does not contain the names of all the parts, but it contains different BYTERANGE for the same file. Have a look:

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-VERSION:7
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MAP:URI="main.mp4",BYTERANGE="720@0"
#EXTINF:6.00000,
#EXT-X-BYTERANGE:3381026@720
main.mp4
#EXTINF:6.00000,
#EXT-X-BYTERANGE:3378764@3381746
main.mp4
#EXTINF:6.00000,
#EXT-X-BYTERANGE:3378834@6760510
main.mp4
#EXTINF:6.00000,
#EXT-X-BYTERANGE:3380162@10139344
main.mp4
#EXTINF:6.00000,
#EXT-X-BYTERANGE:3380365@13519506
main.mp4
#EXTINF:6.00000,
#...

Now, it’s up to you, if you want to download the video in parts by passing the BYTERANGE to the header of the request or you download the whole file at once.

That’s it, most of the HLS.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in Towards Dev

A publication for sharing projects, ideas, codes, and new theories.

No responses yet

What are your thoughts?

Recommended from Medium

Lists

See more recommendations