Skip to content

Instantly share code, notes, and snippets.

@devinschumacher
Last active December 1, 2025 02:31
Show Gist options
  • Select an option

  • Save devinschumacher/aad315b92661fdaad316b949c33c94c7 to your computer and use it in GitHub Desktop.

Select an option

Save devinschumacher/aad315b92661fdaad316b949c33c94c7 to your computer and use it in GitHub Desktop.
How to Download m3u8 / HLS stream videos for free

M3U8/HLS Video Download Research: Technical Analysis of Stream Patterns, CDNs, and Download Methods

A comprehensive research document analyzing M3U8/HLS video streaming infrastructure, embed patterns, stream formats, encryption handling, and optimal download strategies using modern tools

Authors: SERP Apps
Date: December 2024
Version: 1.0


Abstract

This research document provides a comprehensive analysis of M3U8/HLS (HTTP Live Streaming) video streaming infrastructure, including URL patterns, content delivery networks (CDNs), stream formats, encryption mechanisms, and optimal download methodologies. We examine the technical architecture behind HLS video delivery systems and provide practical implementation guidance using industry-standard tools like yt-dlp, ffmpeg, N_m3u8DL-RE, and alternative solutions for reliable video extraction and download.

Table of Contents

  1. Introduction
  2. HLS/M3U8 Infrastructure Overview
  3. URL Patterns and Detection
  4. CDN Analysis and Provider Patterns
  5. Stream Formats and Encryption
  6. yt-dlp Implementation Strategies
  7. FFmpeg Processing Techniques
  8. Alternative Tools and Backup Methods
  9. Live Stream Recording
  10. Implementation Recommendations
  11. Troubleshooting and Edge Cases
  12. Conclusion

1. Introduction

HLS (HTTP Live Streaming) has become the dominant protocol for delivering video content across the internet, developed by Apple and now supported across virtually all platforms and devices. M3U8 files serve as the playlist manifests that orchestrate the delivery of video segments, enabling adaptive bitrate streaming that adjusts quality based on network conditions.

1.1 Research Scope

This document covers:

  • Technical analysis of HLS video streaming architecture
  • Comprehensive URL pattern recognition for M3U8 playlists
  • CDN infrastructure and delivery patterns across major providers
  • Stream format analysis including encryption handling
  • Practical implementation using open-source tools
  • Live stream recording techniques
  • Backup strategies for edge cases and failures

1.2 Methodology

Our research methodology includes:

  • Network traffic analysis of HLS video playback across multiple platforms
  • Reverse engineering of stream delivery mechanisms
  • Testing with various quality settings, formats, and encryption types
  • Validation across multiple CDN endpoints and providers

2. HLS/M3U8 Infrastructure Overview

2.1 Protocol Architecture

HLS (HTTP Live Streaming) utilizes a hierarchical playlist structure:

Architecture Components:

[Media Encoder] → [Segmenter] → [Playlist Generator] → [Origin Server/CDN] → [Client Player]
                       |                |
                 [Master .m3u8]   [Variant .m3u8]
                              ↑ (adaptive selection by client)

Key Components:

  • Media Encoder & Segmenter: Transcodes video/audio into multiple bitrates/resolutions, then slices them into small chunks (typically .ts format)
  • Master Playlist (M3U8 file): Top-level manifest listing all variant streams (different quality levels)
  • Variant Playlist (M3U8 files): For each quality/bitrate, points to media segment chunks
  • Segments (.ts files): Short files (2–10 seconds), enabling fast quality switching
  • Client Player: Fetches playlists, selects appropriate variant, requests segments for playback

2.2 Video Processing Pipeline

Typical HLS video processing follows this pipeline:

  1. Upload: Original video uploaded to processing servers
  2. Transcoding: Multiple formats generated at various quality levels
  3. Segmentation: Video split into small chunks (typically 2-10 seconds)
  4. Encryption: Optional AES-128 or SAMPLE-AES encryption applied
  5. Playlist Generation: M3U8 manifests created with segment references
  6. CDN Distribution: Files distributed across global CDN network
  7. Adaptive Streaming: Client dynamically selects quality based on bandwidth

2.3 Quality Variants

Standard quality levels for HLS streams:

Resolution Typical Bitrate Use Case
240p ~400 kbps Mobile/Low bandwidth
360p ~700 kbps Low quality fallback
480p ~1.2 Mbps Standard definition
720p ~2.5 Mbps HD
1080p ~4.5 Mbps Full HD
1440p ~8 Mbps 2K
2160p ~15 Mbps 4K

2.4 Security and Access Control

Common protection mechanisms:

  • Token-based Access: Time-limited signed URLs
  • AES-128 Encryption: Segment-level encryption with key retrieval
  • SAMPLE-AES: Content protection with DRM integration
  • DRM Systems: FairPlay (Apple), Widevine (Google), PlayReady (Microsoft)
  • Geographic Restrictions: Region-based content blocking
  • Referrer Checking: Domain-based access restrictions
  • Rate Limiting: Per-IP download limitations

3. URL Patterns and Detection

3.1 M3U8 Playlist Structure

3.1.1 Master Playlist Example

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360
low/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1600000,RESOLUTION=1280x720
mid/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3200000,RESOLUTION=1920x1080
hi/playlist.m3u8

3.1.2 Variant Playlist Example

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:10.0,
segment1.ts
#EXTINF:10.0,
segment2.ts
#EXTINF:10.0,
segment3.ts
#EXT-X-ENDLIST

3.1.3 Encrypted Playlist Example

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/key.key",IV=0x1234567890abcdef1234567890abcdef
#EXTINF:10.0,
segment1.ts
#EXTINF:10.0,
segment2.ts
#EXT-X-ENDLIST

3.2 Common M3U8 Tags

Tag Purpose
#EXTM3U Required header for all playlists
#EXT-X-VERSION HLS version used
#EXT-X-STREAM-INF Bandwidth and resolution details for variant streams
#EXTINF Duration of each segment
#EXT-X-ENDLIST Marks playlist end (VOD only)
#EXT-X-KEY Encryption key for protected streams
#EXT-X-TARGETDURATION Maximum segment duration
#EXT-X-MEDIA-SEQUENCE Sequence number of first segment

3.3 URL Pattern Detection

3.3.1 Common M3U8 URL Patterns

# Standard patterns
https://cdn.example.com/hls/{channel}/master.m3u8
https://cdn.example.com/hls/{channel}/{quality}/playlist.m3u8
https://cdn.example.com/hls/{channel}/{quality}/segment0001.ts

# Live stream patterns
https://cdn.example.com/live/{channel}/index.m3u8
https://cdn.example.com/stream/{id}/playlist.m3u8

# VOD patterns
https://cdn.example.com/vod/{video_id}/master.m3u8
https://cdn.example.com/content/{video_id}/{quality}/index.m3u8

3.3.2 Regex Patterns for URL Extraction

# Match M3U8 playlist URLs
https?://[^\s"'<>]+\.m3u8[^\s"'<>]*

# Match segment URLs
https?://[^\s"'<>]+\.ts[^\s"'<>]*

# Extract video ID patterns
/(?:hls|vod|stream|video)/([a-zA-Z0-9_-]+)/

3.3.3 Command-line Detection Methods

Using grep for URL pattern extraction:

# Extract M3U8 URLs from HTML files
grep -oE "https?://[^\"'<>]+\.m3u8[^\"'<>]*" input.html

# Extract from multiple files
find . -name "*.html" -exec grep -oE "https?://[^\"']+\.m3u8" {} +

# Extract M3U8 URLs from HAR files
grep -oE "https://[^\"]*\.m3u8" network_export.har

Using curl to test M3U8 accessibility:

# Check if M3U8 is accessible
curl -I "https://example.com/stream/playlist.m3u8"

# Download and inspect M3U8 content
curl -s "https://example.com/stream/playlist.m3u8" | head -20

# Check with custom headers
curl -s -H "User-Agent: Mozilla/5.0" -H "Referer: https://example.com" "https://example.com/stream/playlist.m3u8"

3.4 Browser DevTools Detection

Manual Inspection Steps:

  1. Open DevTools (F12 or Ctrl+Shift+I)
  2. Navigate to the Network tab
  3. Load or play the video on the page
  4. Filter by "m3u8" in the search bar
  5. Right-click → Copy → Copy link address

Browser Extensions for Detection:

  • M3U8 Sniffer TV: Detects and lists M3U8 URLs from network requests
  • The Stream Detector: Detects HLS, DASH, Adobe HDS, and Smooth Streaming
  • Live Stream Downloader: Auto-detects M3U8 streams for download

4. CDN Analysis and Provider Patterns

4.1 Major CDN Providers

4.1.1 AWS CloudFront

# Pattern
https://{distribution-id}.cloudfront.net/{path}/{filename}.m3u8

# Examples
https://d111111abcdef8.cloudfront.net/live/playlist.m3u8
https://12345678901234567890.mediapackage.us-east-1.amazonaws.com/out/v1/abcdefg/hls/playlist.m3u8

Characteristics:

  • Distribution ID is unique per account
  • Often paired with AWS Elemental services
  • Supports signed URLs for access control

4.1.2 Akamai

# Patterns
https://{subdomain}.akamaihd.net/{content-path}/{playlist}.m3u8
https://{subdomain}.akamaized.net/{content-path}/{playlist}.m3u8

# Examples
https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8
https://cph-msl.akamaized.net/hls/live/2000341/test/master.m3u8
https://skynewsau-live.akamaized.net/hls/live/2002689/skynewsau-extra1/master.m3u8

Characteristics:

  • Uses akamaihd.net or akamaized.net domains
  • Commonly used for live broadcasts and news streams
  • Often includes authentication tokens in query strings

4.1.3 Cloudflare

# Pattern (Custom domain)
https://{your-domain}/cdn-cgi/hls/{path}/{name}.m3u8

# Cloudflare Stream
https://videodelivery.net/{video-id}/manifest/video.m3u8

Characteristics:

  • Acts as reverse proxy for custom domains
  • Cloudflare Stream has dedicated videodelivery.net domain
  • Flexible configuration with custom paths

4.1.4 Other Notable Providers

# Fastly
https://{subdomain}.fastly.net/{path}/playlist.m3u8

# BunnyCDN
https://video.cdn77.com/{account-id}/playlist.m3u8

# JWPlayer (Backend varies)
https://content.jwplatform.com/manifests/{video-id}.m3u8

# Mux
https://test-streams.mux.dev/{video-id}/{video-id}.m3u8

4.2 CDN URL Structure Summary

Provider Domain Pattern Example URL Structure
CloudFront .cloudfront.net https://xyz.cloudfront.net/live/video.m3u8
Akamai .akamaized.net https://foo.akamaized.net/hls/live/123/channel.m3u8
Cloudflare Custom / cdn-cgi/hls https://yourdomain.com/cdn-cgi/hls/stream/video.m3u8
Cloudflare Stream .videodelivery.net https://videodelivery.net/abc123/manifest/video.m3u8

4.3 CDN Failover Testing

#!/bin/bash
# Test multiple CDN endpoints for availability

test_cdn_endpoints() {
    local video_id="$1"
    
    local endpoints=(
        "https://cdn.example.com/hls/$video_id/master.m3u8"
        "https://backup.cdn.example.com/hls/$video_id/master.m3u8"
        "https://d123456.cloudfront.net/hls/$video_id/master.m3u8"
    )
    
    for url in "${endpoints[@]}"; do
        echo "Testing: $url"
        local status=$(curl -o /dev/null -s -w "%{http_code}" "$url")
        echo "Status: $status"
        
        if [ "$status" = "200" ] || [ "$status" = "302" ]; then
            echo "✓ Available: $url"
            return 0
        fi
    done
    
    echo "✗ All endpoints failed"
    return 1
}

5. Stream Formats and Encryption

5.1 Container and Codec Formats

5.1.1 Transport Stream (.ts)

  • Container: MPEG-2 Transport Stream
  • Video Codec: H.264 (AVC), H.265 (HEVC)
  • Audio Codec: AAC, AC3
  • Use Case: Standard HLS segments

5.1.2 Fragmented MP4 (fMP4)

  • Container: ISO Base Media File Format
  • Video Codec: H.264, H.265, VP9
  • Audio Codec: AAC, Opus
  • Use Case: CMAF (Common Media Application Format)

5.1.3 Audio-only Streams

  • Formats: AAC, MP3
  • Extension: .aac, .m4a
  • Use Case: Podcasts, music streaming

5.2 Encryption Types

5.2.1 AES-128 Encryption

The most common encryption method for HLS streams:

M3U8 Declaration:

#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/key.key",IV=0x1234567890abcdef1234567890abcdef

Download and Decrypt with FFmpeg:

# FFmpeg automatically handles AES-128 when key is accessible
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "playlist.m3u8" -c copy -bsf:a aac_adtstoasc output.mp4

Manual Key Decryption with OpenSSL:

# Decrypt individual segment
openssl aes-128-cbc -d -in segment1.ts -out segment1.dec.ts -nosalt -iv <IV> -K <key_hex>

# Then concatenate decrypted segments
ffmpeg -i "concat:segment1.dec.ts|segment2.dec.ts" -c copy output.mp4

5.2.2 SAMPLE-AES

Content protection with DRM integration:

M3U8 Declaration:

#EXT-X-KEY:METHOD=SAMPLE-AES,URI="skd://key-server.example.com/key",KEYFORMAT="com.apple.streamingkeydelivery"

Important: SAMPLE-AES typically requires DRM license servers (FairPlay, Widevine, PlayReady) and cannot be decrypted with standard open-source tools without proper authorization.

5.2.3 Encryption Detection Commands

# Check M3U8 for encryption
check_encryption() {
    local url="$1"
    
    echo "Checking encryption for: $url"
    
    local content=$(curl -s "$url")
    
    if echo "$content" | grep -q "EXT-X-KEY:METHOD=AES-128"; then
        echo "Encryption: AES-128 (downloadable with proper tools)"
    elif echo "$content" | grep -q "EXT-X-KEY:METHOD=SAMPLE-AES"; then
        echo "Encryption: SAMPLE-AES (DRM protected - requires license)"
    elif echo "$content" | grep -q "EXT-X-KEY"; then
        echo "Encryption: Other method detected"
        echo "$content" | grep "EXT-X-KEY"
    else
        echo "Encryption: None detected"
    fi
}

6. yt-dlp Implementation Strategies

6.1 Installation

# Using pip
pip install yt-dlp

# Using homebrew (macOS)
brew install yt-dlp

# Direct download
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
chmod a+rx /usr/local/bin/yt-dlp

6.2 Basic Download Commands

# Download best quality
yt-dlp "https://example.com/stream/playlist.m3u8"

# Download with custom filename
yt-dlp -o "%(title)s.%(ext)s" "https://example.com/stream/playlist.m3u8"

# Download specific quality
yt-dlp -f "best[height<=720]" "https://example.com/stream/playlist.m3u8"

# Download best video + best audio
yt-dlp -f "bv+ba/best" "https://example.com/stream/playlist.m3u8"

6.3 Format Selection

# List available formats
yt-dlp -F "https://example.com/stream/playlist.m3u8"

# Download by format ID
yt-dlp -f 22 "https://example.com/stream/playlist.m3u8"

# Download with quality preference and fallback
yt-dlp -f "best[height=1080]/best[height=720]/best" "https://example.com/stream/playlist.m3u8"

# Download HLS streams specifically
yt-dlp -f "bv*[protocol=m3u8][height<=1080]+ba[protocol=m3u8]/b[protocol=m3u8][height<=1080]" "https://example.com/stream/playlist.m3u8"

# Sort by resolution
yt-dlp -S "res:1080" "https://example.com/stream/playlist.m3u8"

6.4 Advanced Options

# Download with ffmpeg as external downloader
yt-dlp --downloader ffmpeg "https://example.com/stream/playlist.m3u8"

# Download with metadata
yt-dlp --write-description --write-info-json --write-thumbnail "https://example.com/stream/playlist.m3u8"

# Download with subtitles
yt-dlp --write-auto-sub --sub-lang en,es,fr "https://example.com/stream/playlist.m3u8"

# Rate limiting and retries
yt-dlp --limit-rate 1M --retries 5 --fragment-retries 5 "https://example.com/stream/playlist.m3u8"

# Custom headers for authentication
yt-dlp --add-header "User-Agent:Mozilla/5.0" --add-header "Referer:https://example.com" "https://example.com/stream/playlist.m3u8"

# Use browser cookies
yt-dlp --cookies-from-browser chrome "https://example.com/stream/playlist.m3u8"

6.5 Batch Processing

# Download from file list
yt-dlp -a urls.txt

# With archive tracking (skip already downloaded)
yt-dlp --download-archive downloaded.txt -a urls.txt

# Parallel downloads with rate limiting
yt-dlp --max-downloads 3 --sleep-interval 2 -a urls.txt

# Ignore errors and continue
yt-dlp --ignore-errors -a urls.txt

6.6 Information Extraction

# Get video metadata only
yt-dlp --dump-json "https://example.com/stream/playlist.m3u8"

# Extract specific fields
yt-dlp --dump-json "https://example.com/stream/playlist.m3u8" | jq '.title, .duration, .uploader'

# Check if video is accessible
yt-dlp --list-formats "https://example.com/stream/playlist.m3u8"

# Verbose output for debugging
yt-dlp --verbose "https://example.com/stream/playlist.m3u8" 2>&1 | tee debug.log

6.7 Configuration File

Create ~/.config/yt-dlp/config:

-o "%(uploader)s/%(title)s.%(ext)s"
--write-description
--write-info-json
--write-thumbnail
--embed-metadata
--format "bv[height<=1080]+ba/best[height<=1080]"
--retries 5
--fragment-retries 5
--rate-limit 2M
--user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

7. FFmpeg Processing Techniques

7.1 Direct HLS Download

# Basic HLS download
ffmpeg -i "https://example.com/stream/playlist.m3u8" -c copy output.mp4

# With protocol whitelist (required for encrypted streams)
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "playlist.m3u8" -c copy output.mp4

# Download with custom headers
ffmpeg -user_agent "Mozilla/5.0" -referer "https://example.com" -i "https://example.com/stream/playlist.m3u8" -c copy output.mp4

# Download specific quality from master playlist
ffmpeg -i "https://example.com/stream/720p/playlist.m3u8" -c copy output_720p.mp4

7.2 Stream Analysis

# Analyze stream details
ffprobe -v quiet -print_format json -show_format -show_streams "https://example.com/stream/playlist.m3u8"

# Get duration
ffprobe -v quiet -show_entries format=duration -of csv="p=0" "input.mp4"

# Check codec information
ffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name,width,height -of csv="s=x:p=0" "input.mp4"

# List streams in HLS
ffprobe -v quiet -show_streams "https://example.com/stream/master.m3u8"

7.3 Encrypted Stream Processing

# AES-128 encrypted stream (key accessible via URI)
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "encrypted_playlist.m3u8" -c copy -bsf:a aac_adtstoasc output.mp4

# With local key file
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "playlist_with_local_key.m3u8" -c copy output.mp4

# Handle broken segments
ffmpeg -err_detect ignore_err -i "playlist.m3u8" -c copy output.mp4

# Download with segment retry
ffmpeg -protocol_whitelist file,http,https,tcp,tls -max_reload 5 -i "master.m3u8" -c copy output.mp4

7.4 Format Conversion

# Convert WebM to MP4
ffmpeg -i input.webm -c:v libx264 -c:a aac output.mp4

# Re-encode for smaller file size
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac -b:a 128k output_compressed.mp4

# Optimize for streaming
ffmpeg -i input.mp4 -c copy -movflags +faststart output_optimized.mp4

# Extract audio only
ffmpeg -i input.mp4 -vn -c:a aac audio_only.m4a

# Extract video only
ffmpeg -i input.mp4 -an -c:v copy video_only.mp4

7.5 Segment Processing

# Concatenate TS segments
ffmpeg -f concat -safe 0 -i segments.txt -c copy output.mp4

# segments.txt format:
# file 'segment1.ts'
# file 'segment2.ts'
# file 'segment3.ts'

# Join segments directly
ffmpeg -i "concat:segment1.ts|segment2.ts|segment3.ts" -c copy output.mp4

# Fix timestamp issues
ffmpeg -i input.mp4 -avoid_negative_ts make_zero -c copy fixed.mp4

# Repair corrupted MP4
ffmpeg -err_detect ignore_err -i corrupted.mp4 -c copy repaired.mp4

7.6 Batch Processing Script

#!/bin/bash
# batch_ffmpeg_download.sh

download_hls_batch() {
    local input_file="$1"
    local output_dir="${2:-./downloads}"
    
    mkdir -p "$output_dir"
    
    while IFS= read -r url; do
        [[ $url =~ ^#.*$ ]] && continue  # Skip comments
        [[ -z "$url" ]] && continue      # Skip empty lines
        
        # Generate filename from URL
        filename=$(echo "$url" | grep -oP '[^/]+\.m3u8' | sed 's/\.m3u8//')
        
        echo "Downloading: $url"
        ffmpeg -i "$url" -c copy "$output_dir/${filename}.mp4"
        
        if [ $? -eq 0 ]; then
            echo "✓ Success: ${filename}.mp4"
        else
            echo "✗ Failed: $url"
        fi
        
        sleep 2  # Rate limiting
    done < "$input_file"
}

8. Alternative Tools and Backup Methods

8.1 N_m3u8DL-RE

A powerful cross-platform HLS/DASH downloader with extensive features.

Installation:

# Download from GitHub releases
# https://github.com/nilaoda/N_m3u8DL-RE/releases

Basic Usage:

# Download best quality
N_m3u8DL-RE "https://example.com/stream/master.m3u8"

# Download specific resolution
N_m3u8DL-RE "https://example.com/stream/master.m3u8" --select-video best

# With custom output
N_m3u8DL-RE "https://example.com/stream/master.m3u8" --save-name "output" --save-dir "./downloads"

# Handle encrypted streams
N_m3u8DL-RE "https://example.com/stream/playlist.m3u8" --custom-hls-key <hex_key>

# Live stream recording
N_m3u8DL-RE "https://example.com/live/stream.m3u8" --live-real-time-merge

Features:

  • Parallel segment downloads
  • Encrypted stream handling (AES-128)
  • Subtitle extraction (WebVTT)
  • Output to MP4/TS with ffmpeg merging
  • Live stream support

8.2 Streamlink

Designed for streaming content to media players, also supports saving to file.

Installation:

pip install streamlink

Usage:

# Stream to VLC
streamlink "https://example.com/stream/playlist.m3u8" best

# Save to file
streamlink "https://example.com/stream/playlist.m3u8" best -o output.mp4

# Specify quality
streamlink "https://example.com/stream/playlist.m3u8" 720p -o output_720p.mp4

# With HLS options
streamlink --hls-duration 01:00:00 "https://example.com/stream/playlist.m3u8" best -o output.mp4

8.3 gallery-dl

While primarily for image galleries, supports some video sources.

Installation:

pip install gallery-dl

Usage:

# Download from supported sites
gallery-dl "https://example.com/video/page"

# With configuration
gallery-dl --config config.json "https://example.com/video/page"

8.4 wget/curl for Direct Downloads

Using wget:

# Download M3U8 playlist
wget -O "playlist.m3u8" "https://example.com/stream/playlist.m3u8"

# Download with custom headers
wget --user-agent="Mozilla/5.0" --referer="https://example.com" -O "video.m3u8" "https://example.com/stream/playlist.m3u8"

# Download all segments listed in playlist
grep -oP 'https?://[^\s]+\.ts' playlist.m3u8 | xargs -I {} wget {}

Using curl:

# Download with headers
curl -H "User-Agent: Mozilla/5.0" -H "Referer: https://example.com" -o "playlist.m3u8" "https://example.com/stream/playlist.m3u8"

# Test accessibility
curl -I "https://example.com/stream/playlist.m3u8"

# Download segment with cookie
curl -b "session=abc123" -o "segment.ts" "https://example.com/stream/segment.ts"

8.5 Tool Comparison Summary

Tool Platform Stream Support Encryption Live Streams Speed
yt-dlp All HLS/DASH/Many sites AES-128 Yes High
FFmpeg All HLS/DASH/Generic AES-128 Yes High
N_m3u8DL-RE Win/Lin/Mac HLS/DASH/MSS AES-128 Yes High
Streamlink All HLS (focus VOD/Live) Some Yes Medium
gallery-dl All Some video sites No No Medium
wget/curl All Direct URLs No Manual Low

9. Live Stream Recording

9.1 Basic Live Stream Recording

Using FFmpeg:

# Record live stream
ffmpeg -i "https://example.com/live/stream.m3u8" -c copy output.mp4

# Record for specific duration (1 hour)
ffmpeg -i "https://example.com/live/stream.m3u8" -c copy -t 3600 output.mp4

# Record with segmentation (10 minute chunks)
ffmpeg -i "https://example.com/live/stream.m3u8" -c copy -f segment -segment_time 600 -reset_timestamps 1 out%03d.mp4

Using yt-dlp:

# Record live stream
yt-dlp --live-from-start "https://example.com/live/stream.m3u8"

# Record with duration limit
yt-dlp --live-from-start --max-downloads 1 "https://example.com/live/stream.m3u8"

9.2 Automated Recording Scripts

Continuous Recording Script:

#!/bin/bash
# continuous_record.sh

STREAM_URL="$1"
OUTPUT_DIR="${2:-./recordings}"
SEGMENT_DURATION="${3:-600}"  # 10 minutes

mkdir -p "$OUTPUT_DIR"

while true; do
    TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
    OUTPUT_FILE="$OUTPUT_DIR/recording_$TIMESTAMP.mp4"
    
    echo "Starting recording: $OUTPUT_FILE"
    
    ffmpeg -i "$STREAM_URL" \
           -c copy \
           -t "$SEGMENT_DURATION" \
           "$OUTPUT_FILE" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        echo "✓ Completed: $OUTPUT_FILE"
    else
        echo "✗ Recording interrupted or failed"
        sleep 10  # Wait before retry
    fi
done

Scheduled Recording with cron:

# Record 1-hour segments every hour
0 * * * * /path/to/record.sh "https://example.com/live/stream.m3u8" "/recordings" 3600

9.3 Segment Recovery

Recover Missing Segments:

#!/bin/bash
# recover_segments.sh

recover_missing_segments() {
    local playlist_url="$1"
    local output_dir="$2"
    
    mkdir -p "$output_dir"
    
    # Download current playlist
    curl -s "$playlist_url" > /tmp/playlist.m3u8
    
    # Extract segment URLs
    grep -E "^https?://" /tmp/playlist.m3u8 > /tmp/segments.txt
    
    # Download missing segments
    while IFS= read -r segment_url; do
        filename=$(basename "$segment_url" | cut -d'?' -f1)
        
        if [ ! -f "$output_dir/$filename" ]; then
            echo "Downloading: $filename"
            curl -s -o "$output_dir/$filename" "$segment_url"
        fi
    done < /tmp/segments.txt
    
    echo "Segment recovery complete"
}

9.4 Graceful Stop and Merge

Recording with Graceful Stop:

#!/bin/bash
# graceful_record.sh

STREAM_URL="$1"
OUTPUT_FILE="${2:-output.mp4}"
PID_FILE="/tmp/stream_record.pid"

# Handle SIGINT gracefully
trap 'kill -SIGINT $FFMPEG_PID; wait $FFMPEG_PID; echo "Recording stopped gracefully"' SIGINT SIGTERM

ffmpeg -i "$STREAM_URL" -c copy "$OUTPUT_FILE" &
FFMPEG_PID=$!
echo $FFMPEG_PID > "$PID_FILE"

wait $FFMPEG_PID
rm -f "$PID_FILE"

10. Implementation Recommendations

10.1 Primary Download Strategy

Hierarchical Download Approach:

#!/bin/bash
# primary_download.sh

download_m3u8() {
    local url="$1"
    local output_dir="${2:-./downloads}"
    local output_name="$3"
    
    mkdir -p "$output_dir"
    
    # Method 1: yt-dlp (primary)
    echo "Attempting yt-dlp..."
    if yt-dlp --ignore-errors -o "$output_dir/%(title)s.%(ext)s" "$url"; then
        echo "✓ Success with yt-dlp"
        return 0
    fi
    
    # Method 2: FFmpeg
    echo "Attempting FFmpeg..."
    if ffmpeg -i "$url" -c copy "$output_dir/${output_name:-output}.mp4"; then
        echo "✓ Success with FFmpeg"
        return 0
    fi
    
    # Method 3: N_m3u8DL-RE
    echo "Attempting N_m3u8DL-RE..."
    if N_m3u8DL-RE "$url" --save-dir "$output_dir"; then
        echo "✓ Success with N_m3u8DL-RE"
        return 0
    fi
    
    # Method 4: Streamlink
    echo "Attempting Streamlink..."
    if streamlink "$url" best -o "$output_dir/${output_name:-output}.mp4"; then
        echo "✓ Success with Streamlink"
        return 0
    fi
    
    echo "✗ All methods failed"
    return 1
}

10.2 Quality Selection Strategy

# Inspect available qualities first
yt-dlp -F "https://example.com/stream/master.m3u8"

# Download with quality preference and fallback
yt-dlp -f "best[height<=1080][ext=mp4]/best[height<=720][ext=mp4]/best" "https://example.com/stream/master.m3u8"

# Quality selection function
select_quality() {
    local url="$1"
    local max_quality="${2:-1080}"
    local max_size_mb="${3:-2000}"
    
    echo "Checking available formats..."
    yt-dlp -F "$url"
    
    echo "Downloading with quality limit: ${max_quality}p"
    yt-dlp -f "best[height<=$max_quality][filesize<${max_size_mb}M]/best[height<=$max_quality]/best" "$url"
}

10.3 Error Handling and Resilience

#!/bin/bash
# resilient_download.sh

download_with_retries() {
    local url="$1"
    local max_retries="${2:-3}"
    local delay="${3:-5}"
    
    for i in $(seq 1 $max_retries); do
        echo "Attempt $i of $max_retries"
        
        if yt-dlp --retries 3 --fragment-retries 3 "$url"; then
            echo "✓ Download successful"
            return 0
        fi
        
        echo "Attempt $i failed, waiting ${delay}s..."
        sleep $delay
        delay=$((delay * 2))  # Exponential backoff
    done
    
    echo "✗ All retry attempts failed"
    return 1
}

# Handle rate limiting
handle_rate_limit() {
    local url="$1"
    
    yt-dlp --limit-rate 1M --retries 5 --fragment-retries 3 "$url"
    
    if [ $? -ne 0 ]; then
        echo "Rate limited, waiting 60 seconds..."
        sleep 60
        yt-dlp --limit-rate 500K "$url"
    fi
}

10.4 Logging and Monitoring

#!/bin/bash
# logging_download.sh

LOG_DIR="./logs"
mkdir -p "$LOG_DIR"

DOWNLOAD_LOG="$LOG_DIR/downloads_$(date +%Y%m%d).log"
ERROR_LOG="$LOG_DIR/errors_$(date +%Y%m%d).log"

log_download() {
    local status="$1"
    local url="$2"
    local message="$3"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    case "$status" in
        "START")
            echo "[$timestamp] START: $url" >> "$DOWNLOAD_LOG"
            ;;
        "SUCCESS")
            echo "[$timestamp] SUCCESS: $url | $message" >> "$DOWNLOAD_LOG"
            ;;
        "ERROR")
            echo "[$timestamp] ERROR: $url | $message" >> "$ERROR_LOG"
            ;;
    esac
}

# Usage in download function
download_with_logging() {
    local url="$1"
    
    log_download "START" "$url"
    
    if yt-dlp "$url" 2>&1; then
        log_download "SUCCESS" "$url" "Download completed"
        return 0
    else
        log_download "ERROR" "$url" "Download failed"
        return 1
    fi
}

10.5 Performance Optimization

Network Optimization:

# Optimal network settings
yt-dlp \
    --concurrent-fragments 4 \
    --rate-limit 5M \
    --socket-timeout 30 \
    --retries 10 \
    --fragment-retries 10 \
    "https://example.com/stream/master.m3u8"

Parallel Batch Processing:

# Using GNU parallel
parallel -j 3 yt-dlp -o "./downloads/%(title)s.%(ext)s" {} :::: urls.txt

# Using xargs
cat urls.txt | xargs -P 3 -I {} yt-dlp -o "./downloads/%(title)s.%(ext)s" {}

11. Troubleshooting and Edge Cases

11.1 Common Errors and Solutions

11.1.1 Access and Authentication Errors

Error: "403 Forbidden" or "Access Denied"

Solutions:

# Add proper headers
yt-dlp --add-header "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64)" \
       --add-header "Referer:https://example.com" \
       "https://example.com/stream/playlist.m3u8"

# Use browser cookies
yt-dlp --cookies-from-browser chrome "https://example.com/stream/playlist.m3u8"

# Test with curl first
curl -I -H "User-Agent: Mozilla/5.0" -H "Referer: https://example.com" "https://example.com/stream/playlist.m3u8"

11.1.2 Encryption Errors

Error: "Invalid data found when processing input"

Solutions:

# For AES-128 encrypted streams
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -i "playlist.m3u8" -c copy output.mp4

# Check if key is accessible
curl -I "$(grep 'URI=' playlist.m3u8 | cut -d'"' -f2)"

# Use yt-dlp which handles encryption automatically
yt-dlp "https://example.com/stream/playlist.m3u8"

Error: "HLS stream is DRM protected"

Solution: DRM-protected streams (SAMPLE-AES, Widevine, FairPlay, PlayReady) cannot be downloaded with open-source tools without proper authorization. Use official apps/platforms for offline viewing.

11.1.3 Geographic Restrictions

Error: Download stalls or returns error for region-blocked content

Solutions:

# Use geo-bypass option
yt-dlp --geo-bypass "https://example.com/stream/playlist.m3u8"

# Specify country
yt-dlp --geo-bypass-country US "https://example.com/stream/playlist.m3u8"

# Use with proxy/VPN
yt-dlp --proxy socks5://127.0.0.1:1080 "https://example.com/stream/playlist.m3u8"

11.2 Diagnostic Commands

#!/bin/bash
# diagnose_stream.sh

diagnose_m3u8() {
    local url="$1"
    
    echo "=== M3U8 Stream Diagnosis ==="
    echo "URL: $url"
    echo
    
    # Test accessibility
    echo "1. Testing accessibility..."
    local status=$(curl -o /dev/null -s -w "%{http_code}" "$url")
    echo "   HTTP Status: $status"
    
    # Check content type
    echo "2. Checking content type..."
    curl -sI "$url" | grep -i "content-type"
    
    # Download and analyze playlist
    echo "3. Analyzing playlist..."
    local content=$(curl -s "$url" | head -30)
    
    if echo "$content" | grep -q "EXT-X-STREAM-INF"; then
        echo "   Type: Master Playlist"
        echo "   Available streams:"
        echo "$content" | grep "EXT-X-STREAM-INF"
    else
        echo "   Type: Media Playlist"
    fi
    
    # Check encryption
    echo "4. Checking encryption..."
    if echo "$content" | grep -q "EXT-X-KEY"; then
        echo "   Encryption detected:"
        echo "$content" | grep "EXT-X-KEY"
    else
        echo "   No encryption detected"
    fi
    
    # List formats with yt-dlp
    echo "5. Available formats (yt-dlp)..."
    yt-dlp -F "$url" 2>/dev/null || echo "   Unable to list formats"
}

11.3 Network and Timeout Issues

# Configure timeouts and retries
yt-dlp \
    --socket-timeout 60 \
    --retries 10 \
    --fragment-retries 10 \
    --retry-sleep linear:1:5:2 \
    "https://example.com/stream/playlist.m3u8"

# Force IPv4/IPv6
yt-dlp --force-ipv4 "https://example.com/stream/playlist.m3u8"

# Test with different DNS
nslookup cdn.example.com 8.8.8.8

11.4 Video Integrity Verification

# Verify downloaded file
verify_video() {
    local file="$1"
    
    if [ ! -f "$file" ]; then
        echo "File not found: $file"
        return 1
    fi
    
    # Check file size
    local size=$(du -h "$file" | cut -f1)
    echo "File size: $size"
    
    # Validate with ffprobe
    if ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 "$file" >/dev/null 2>&1; then
        echo "✓ Video file is valid"
        
        # Get duration
        local duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$file")
        echo "Duration: ${duration}s"
        
        return 0
    else
        echo "✗ Video file appears to be corrupted"
        return 1
    fi
}

12. Conclusion

12.1 Summary of Findings

This research has comprehensively analyzed HLS/M3U8 video streaming infrastructure, revealing consistent patterns across CDN providers and delivery mechanisms. Our analysis identified:

Key Technical Findings:

  • HLS utilizes a hierarchical playlist structure with master and variant playlists
  • Common CDN patterns across CloudFront, Akamai, and Cloudflare enable predictable URL detection
  • AES-128 encryption is the most common protection method and is downloadable with proper tools
  • SAMPLE-AES and DRM-protected content require official platforms for access

12.2 Recommended Tool Priority

Based on our research, we recommend this tool hierarchy:

  1. yt-dlp: Primary tool with extensive format support and site compatibility
  2. FFmpeg: Direct stream processing with encryption support
  3. N_m3u8DL-RE: Specialized HLS/DASH downloader with advanced features
  4. Streamlink: Live stream and VOD capture
  5. wget/curl: Direct URL downloads as fallback

12.3 Implementation Priority

Essential Implementations:

  1. M3U8 URL detection and extraction from web pages
  2. Quality selection with intelligent fallbacks
  3. AES-128 encrypted stream handling
  4. Error handling with retry logic
  5. Batch processing for multiple URLs

Advanced Implementations:

  1. Live stream recording with segmentation
  2. Segment recovery for interrupted downloads
  3. CDN failover handling
  4. Performance optimization with parallel downloads

12.4 Performance Considerations

Optimal performance settings:

  • Concurrent Fragments: 3-4 simultaneous downloads per stream
  • Rate Limiting: 1-2 Mbps to avoid throttling
  • Retry Logic: 3-5 retry attempts with exponential backoff
  • Quality Selection: 720p-1080p provides best quality/size balance

12.5 Security and Compliance Notes

Important Considerations:

  • Respect content provider terms of service
  • Implement appropriate rate limiting
  • DRM-protected content cannot be legally downloaded without authorization
  • Consider privacy and data protection requirements

12.6 Future Research Directions

Areas for Continued Development:

  1. CMAF/fMP4 Support: Enhanced fragmented MP4 handling
  2. Subtitle Extraction: Improved WebVTT and embedded subtitle handling
  3. Live DVR: Enhanced live stream time-shifting capabilities
  4. Mobile Platform Support: Better handling of mobile-specific streams
  5. Analytics Integration: Download performance monitoring

Disclaimer: This research is provided for educational and legitimate archival purposes. Users must comply with applicable terms of service, copyright laws, and data protection regulations when implementing these techniques.

Last Updated: December 2024
Research Version: 1.0
Next Review: June 2025

Related

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment