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
- Introduction
- HLS/M3U8 Infrastructure Overview
- URL Patterns and Detection
- CDN Analysis and Provider Patterns
- Stream Formats and Encryption
- yt-dlp Implementation Strategies
- FFmpeg Processing Techniques
- Alternative Tools and Backup Methods
- Live Stream Recording
- Implementation Recommendations
- Troubleshooting and Edge Cases
- 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:
- Upload: Original video uploaded to processing servers
- Transcoding: Multiple formats generated at various quality levels
- Segmentation: Video split into small chunks (typically 2-10 seconds)
- Encryption: Optional AES-128 or SAMPLE-AES encryption applied
- Playlist Generation: M3U8 manifests created with segment references
- CDN Distribution: Files distributed across global CDN network
- 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:
- Open DevTools (F12 or Ctrl+Shift+I)
- Navigate to the Network tab
- Load or play the video on the page
- Filter by "m3u8" in the search bar
- 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.netorakamaized.netdomains - 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.netdomain - 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:
- yt-dlp: Primary tool with extensive format support and site compatibility
- FFmpeg: Direct stream processing with encryption support
- N_m3u8DL-RE: Specialized HLS/DASH downloader with advanced features
- Streamlink: Live stream and VOD capture
- wget/curl: Direct URL downloads as fallback
12.3 Implementation Priority
Essential Implementations:
- M3U8 URL detection and extraction from web pages
- Quality selection with intelligent fallbacks
- AES-128 encrypted stream handling
- Error handling with retry logic
- Batch processing for multiple URLs
Advanced Implementations:
- Live stream recording with segmentation
- Segment recovery for interrupted downloads
- CDN failover handling
- 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:
- CMAF/fMP4 Support: Enhanced fragmented MP4 handling
- Subtitle Extraction: Improved WebVTT and embedded subtitle handling
- Live DVR: Enhanced live stream time-shifting capabilities
- Mobile Platform Support: Better handling of mobile-specific streams
- 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