Skip to content

Repository files navigation

M3U8 Video Downloader

A M3U8/HLS downloader tool with resume capability and one-click download→merge→compress functionality.

Twitter Follow

中文文档 | English Documentation

Features

  • HTTP proxy support (default: 127.0.0.1:7890, configurable via environment variables or .env file)
  • Proxy disable option: Use --no-proxy flag to disable proxy
  • Configuration file support: Create .env file for persistent settings
  • Hash-based folder structure: Each download task uses unique folder data/{hash}/
  • Resume capability (manual mode): Automatically skips already downloaded segments
  • One-click mode: Download → merge → compress, outputs single file to data/{hash}/
  • Concurrent downloads (manual mode): Default 8 concurrent connections (configurable)
  • Progress display and error tolerance

Installation

npm install

Usage

One-Click Download → Merge → Compress (Recommended)

Output file: data/{hash}/<auto-generated-filename>.mp4 (can specify with --name)

node cli.js "<M3U8_URL>"

# Optional parameters
# --name <file>            Specify output base filename (without extension)
# --codec <h264|hevc>      Video codec (default: h264; hevc for better compression)
# --h265                   Equivalent to --codec hevc
# --crf <num>              Quality/size balance (default: 23; lower = higher quality)
# --preset <p>             Encoding speed/efficiency (default: medium)
# --audio-bitrate <rate>   Audio bitrate (default: 128k)
# --no-proxy               Disable proxy usage

Examples:

# Basic usage
node cli.js "https://example.com/playlist.m3u8" --name my-video --h265 --crf 26 --preset slow

# Disable proxy
node cli.js "https://example.com/playlist.m3u8" --no-proxy

# Use custom proxy (via .env file)
# Create .env file with: HTTP_PROXY=http://your-proxy:8080
node cli.js "https://example.com/playlist.m3u8"

If installed globally (or npm link this repo), you can use directly:

m3u8-one "<M3U8_URL>"

Compress Local Video Files

Compress existing video files with the same encoding options:

node compress.js <INPUT_VIDEO_FILE>

# Optional parameters
# --output <file>          Specify output file path
# --codec <h264|hevc>      Video codec (default: h264)
# --h265                   Equivalent to --codec hevc
# --crf <num>              Quality/size balance (default: 23)
# --preset <p>             Encoding speed/efficiency (default: medium)
# --audio-bitrate <rate>   Audio bitrate (default: 128k)

Examples:

# Basic compression
node compress.js video.mp4 --codec hevc --crf 26

# Specify output file
node compress.js input.mp4 --output compressed.mp4 --preset slow

# Use npm script
npm run compress -- video.mp4 --h265

If installed globally:

m3u8-compress video.mp4 --h265 --crf 26

Download Video Segments (Manual Mode)

node download.js "<M3U8_URL>"

# Disable proxy
node download.js "<M3U8_URL>" --no-proxy

Example

node download.js "https://prod-fastly-us-west-1.video.pscp.tv/Transcoding/v1/hls/o6U3UX5qItJ7V-Jmh9HGBb7uuyNgUHZnemnmw-l24VrxJ2Q5ytrb9q_39wwQVGPdsAGqDXXdy85iKfpfGbvybA/transcode/us-west-1/periscope-replay-direct-prod-us-west-1-public/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0.eyJFbmNvZGVyU2V0dGluZyI6ImVuY29kZXJfc2V0dGluZ18xMDgwcDYwXzEwIiwiSGVpZ2h0IjoxMDgwLCJIaWdoRnJhbWVSYXRlIjp0cnVlLCJLYnBzIjo4MDAwLCJXaWR0aCI6MTkyMH0.OBq8EsoF4c8ydlmfZFxJzACPHYFjmjUaSER2wvsfHso/playlist_16685069917841765633.m3u8?type=replay"

Output

  • One-click mode: Generates single data/{hash}/<name>.mp4
  • Manual mode: Segments and playlist saved in data/{hash}/ (playlist.m3u8 and multiple .ts files)
  • Hash-based folders: Each URL generates unique hash folder for organized file management

Resume Capability

If download is interrupted, simply rerun the same command, the program will:

  1. Check already downloaded segments
  2. Automatically skip existing files
  3. Only download missing or failed segments

Download Statistics

After download completes, it shows:

  • Total: Total segment count
  • Downloaded: Newly downloaded segments in this run
  • Skipped: Skipped segments (already exist)
  • Failed: Failed segment count

Proxy Configuration

Default Proxy

  • HTTP/HTTPS proxy: http://127.0.0.1:7890

Disable Proxy

Use --no-proxy flag to disable proxy:

node cli.js "<M3U8_URL>" --no-proxy
node download.js "<M3U8_URL>" --no-proxy
node index.js "<M3U8_URL>" --no-proxy

Custom Proxy via Environment Variables

Set environment variables before running:

export HTTP_PROXY=http://your-proxy:8080
export HTTPS_PROXY=http://your-proxy:8080
node cli.js "<M3U8_URL>"

Legacy Method (Edit Source Code)

To modify proxy in source code, edit these lines in the respective files:

process.env.GLOBAL_AGENT_HTTP_PROXY = 'http://127.0.0.1:7890';
process.env.GLOBAL_AGENT_HTTPS_PROXY = 'http://127.0.0.1:7890';

Configuration via .env File

For persistent configuration, create a .env file in the project root:

cp .env.example .env
# Edit .env file with your preferences

Available Configuration Options

# Proxy Configuration
DISABLE_PROXY=false                    # Set to "true" to disable proxy by default
HTTP_PROXY=http://127.0.0.1:7890       # HTTP proxy address
HTTPS_PROXY=http://127.0.0.1:7890      # HTTPS proxy address

# Download Configuration
OUTPUT_DIR=data                         # Output directory
CONCURRENT_DOWNLOADS=8                  # Number of concurrent downloads

# Video Encoding Defaults (cli.js only)
DEFAULT_CODEC=h264                      # Default video codec (h264 or hevc)
DEFAULT_CRF=23                          # Default CRF value
DEFAULT_PRESET=medium                   # Default encoding preset
DEFAULT_AUDIO_BITRATE=128k              # Default audio bitrate

Priority Order

  1. Command line arguments (highest priority)
  2. .env file configuration
  3. Code defaults (lowest priority)

Example Usage

# Use .env configuration
node cli.js "https://example.com/playlist.m3u8"

# Override .env configuration
node cli.js "https://example.com/playlist.m3u8" --no-proxy --codec h264

Merge Video Segments

After manual mode download completes, you can use ffmpeg to merge all .ts segments into a complete video:

# Enter data directory
cd data

# Merge using ffmpeg
ffmpeg -i playlist.m3u8 -c copy output.mp4

Video Compression (ffmpeg)

The following examples are for compressing videos after merging or directly from M3U8 (smaller size, convenient for sharing/archiving). One-click mode already includes compression, no need for additional processing.

Quality Priority (CRF, Recommended)

ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k -movflags +faststart output.mp4

Higher Compression Ratio (HEVC/H.265)

ffmpeg -i input.mp4 -c:v libx265 -preset medium -crf 28 -c:a aac -b:a 128k output-hevc.mp4

Specify Target Bitrate (Controlled Size)

Single pass:

ffmpeg -i input.mp4 -c:v libx264 -b:v 1500k -maxrate 1500k -bufsize 3000k -c:a aac -b:a 128k output-1500k.mp4

Two-pass (more stable):

ffmpeg -y -i input.mp4 -c:v libx264 -b:v 1500k -pass 1 -an -f mp4 /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 1500k -pass 2 -c:a aac -b:a 128k -movflags +faststart output-2pass.mp4

Reduce Resolution/Frame Rate (Significantly Smaller Size)

ffmpeg -i input.mp4 -vf "scale=-2:720,fps=30" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output-720p.mp4

Compress Directly from M3U8

ffmpeg -i data/playlist.m3u8 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

Tip: Add -pix_fmt yuv420p for better compatibility; use -c copy to remux without compression.

Troubleshooting

Network Errors

If "Client network socket disconnected" error occurs:

  1. Check if proxy is running properly
  2. Rerun the command, resume will skip already downloaded segments

Proxy Connection Failed

Ensure local proxy service (such as Clash, V2Ray, etc.) is running and listening on port 7890.

File Structure

m3u8/
├── cli.js               # One-click download→merge→compress CLI (outputs single file)
├── compress.js          # Video compression tool for local files
├── download.js          # Optimized download script (with resume support)
├── index.js             # Download script based on m3u8-dln
├── package.json
├── .env.example         # Configuration file template
├── .env                 # User configuration file (create from .env.example)
├── data/                # Download output directory
│   ├── {hash1}/        # Task 1 hash folder
│   │   ├── playlist.m3u8
│   │   └── *.ts
│   ├── {hash2}/        # Task 2 hash folder
│   │   ├── playlist.m3u8
│   │   └── *.ts
│   └── ...
└── README.md

License

MIT

About

m3u8 one-click download integration, supports proxy

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages