m3u8-downloader
使用并行下载下载加密的 m3u8/HLS 视频。在给定 m3u8 URL 时使用来下载视频,尤其是使用 AES-128 加密的 HLS 流。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw skills install shop:totalclaw:totalclaw~easonc13-m3u8-downloadercURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~easonc13-m3u8-downloader/file -o easonc13-m3u8-downloader.md# M3U8 Video Downloader
Download HLS/m3u8 videos with parallel segment downloads and automatic decryption.
## Prerequisites
- `aria2c` (install: `brew install aria2`)
- `ffmpeg` (install: `brew install ffmpeg`)
## Full Workflow (From Webpage to MP4)
### Step 1: Extract m3u8 URL from webpage
If given a webpage URL (not a direct m3u8), use browser automation to find the stream URL:
```javascript
// In browser console or via browser tool evaluate
(() => {
// Check HLS.js player instance
if (window.hls && window.hls.url) return window.hls.url;
if (window.player && window.player.hls && window.player.hls.url) return window.player.hls.url;
// Search window objects for m3u8 URLs
const allVars = Object.keys(window).filter(k => {
try {
return window[k] && typeof window[k] === 'object' &&
window[k].url && window[k].url.includes('m3u8');
} catch(e) { return false; }
});
return allVars.length > 0 ? allVars.map(k => window[k].url) : 'not found';
})()
```
Use `profile=openclaw` (isolated browser) to avoid browser history.
### Step 2: Handle Master Playlist (Multi-Quality)
Master playlists list quality variants, not segments:
```bash
curl -s "https://example.com/playlist.m3u8"
# Output example:
# #EXT-X-STREAM-INF:BANDWIDTH=8247061,RESOLUTION=1920x1080
# 1080p/video.m3u8
# #EXT-X-STREAM-INF:BANDWIDTH=4738061,RESOLUTION=1280x720
# 720p/video.m3u8
```
Pick the highest quality (e.g., 1080p) and fetch that sub-playlist:
```bash
BASE_URL="https://example.com"
curl -s "${BASE_URL}/1080p/video.m3u8"
```
### Step 3: Extract Segment URLs
Segments may have non-standard extensions (e.g., `.jpeg` instead of `.ts`):
```bash
mkdir -p /tmp/video_download && cd /tmp/video_download
BASE_URL="https://example.com/1080p"
curl -s "${BASE_URL}/video.m3u8" | grep -E "^[^#]" | while read seg; do
echo "${BASE_URL}/${seg}"
done > urls.txt
# Count segments
wc -l urls.txt
```
### Step 4: Parallel Download with aria2c
```bash
aria2c -i urls.txt -j 16 -x 16 -s 16 --file-allocation=none -c true \
--console-log-level=warn --summary-interval=30
```
- `-j 16`: 16 concurrent downloads
- `-x 16`: 16 connections per file
- `-c true`: continue partial downloads
### Step 5: Merge with ffmpeg
```bash
# Get segment count
NUM_SEGMENTS=$(wc -l < urls.txt)
# Generate file list (adjust filename pattern as needed)
for i in $(seq 0 $((NUM_SEGMENTS-1))); do
echo "file 'video${i}.jpeg'" # or video${i}.ts
done > filelist.txt
# Merge (copy streams, no re-encoding)
ffmpeg -y -f concat -safe 0 -i filelist.txt -c copy ~/Downloads/output.mp4
```
### Step 6: Cleanup
```bash
rm -rf /tmp/video_download
```
## Quick Script Usage
```bash
~/clawd/skills/m3u8-downloader/scripts/download.sh "https://example.com/video.m3u8" "output_name"
```
Note: The script may not handle all edge cases (master playlists, non-standard extensions). Use manual process above for complex streams.
## Handling Encrypted Streams (AES-128)
Look for `#EXT-X-KEY:METHOD=AES-128,URI="enc.key"` in the playlist:
```bash
curl -s "https://example.com/path/enc.key" -o enc.key
ffmpeg -allowed_extensions ALL -i local_playlist.m3u8 -c copy output.mp4
```
## Output
Final video saved as `~/Downloads/<output_name>.mp4`
---
## 中文说明
# M3U8 视频下载器
下载 HLS/m3u8 视频,支持并行分片下载和自动解密。
## 前置条件
- `aria2c`(安装:`brew install aria2`)
- `ffmpeg`(安装:`brew install ffmpeg`)
## 完整工作流(从网页到 MP4)
### 步骤 1:从网页提取 m3u8 URL
如果给定的是网页 URL(而非直接的 m3u8),使用浏览器自动化来查找流 URL:
```javascript
// In browser console or via browser tool evaluate
(() => {
// Check HLS.js player instance
if (window.hls && window.hls.url) return window.hls.url;
if (window.player && window.player.hls && window.player.hls.url) return window.player.hls.url;
// Search window objects for m3u8 URLs
const allVars = Object.keys(window).filter(k => {
try {
return window[k] && typeof window[k] === 'object' &&
window[k].url && window[k].url.includes('m3u8');
} catch(e) { return false; }
});
return allVars.length > 0 ? allVars.map(k => window[k].url) : 'not found';
})()
```
使用 `profile=openclaw`(隔离的浏览器)以避免留下浏览历史。
### 步骤 2:处理主播放列表(多清晰度)
主播放列表列出的是清晰度变体,而非分片:
```bash
curl -s "https://example.com/playlist.m3u8"
# Output example:
# #EXT-X-STREAM-INF:BANDWIDTH=8247061,RESOLUTION=1920x1080
# 1080p/video.m3u8
# #EXT-X-STREAM-INF:BANDWIDTH=4738061,RESOLUTION=1280x720
# 720p/video.m3u8
```
选择最高清晰度(例如 1080p)并获取该子播放列表:
```bash
BASE_URL="https://example.com"
curl -s "${BASE_URL}/1080p/video.m3u8"
```
### 步骤 3:提取分片 URL
分片可能使用非标准扩展名(例如用 `.jpeg` 代替 `.ts`):
```bash
mkdir -p /tmp/video_download && cd /tmp/video_download
BASE_URL="https://example.com/1080p"
curl -s "${BASE_URL}/video.m3u8" | grep -E "^[^#]" | while read seg; do
echo "${BASE_URL}/${seg}"
done > urls.txt
# Count segments
wc -l urls.txt
```
### 步骤 4:使用 aria2c 并行下载
```bash
aria2c -i urls.txt -j 16 -x 16 -s 16 --file-allocation=none -c true \
--console-log-level=warn --summary-interval=30
```
- `-j 16`:16 个并发下载
- `-x 16`:每个文件 16 个连接
- `-c true`:继续未完成的下载
### 步骤 5:使用 ffmpeg 合并
```bash
# Get segment count
NUM_SEGMENTS=$(wc -l < urls.txt)
# Generate file list (adjust filename pattern as needed)
for i in $(seq 0 $((NUM_SEGMENTS-1))); do
echo "file 'video${i}.jpeg'" # or video${i}.ts
done > filelist.txt
# Merge (copy streams, no re-encoding)
ffmpeg -y -f concat -safe 0 -i filelist.txt -c copy ~/Downloads/output.mp4
```
### 步骤 6:清理
```bash
rm -rf /tmp/video_download
```
## 快速脚本用法
```bash
~/clawd/skills/m3u8-downloader/scripts/download.sh "https://example.com/video.m3u8" "output_name"
```
注意:该脚本可能无法处理所有边缘情况(主播放列表、非标准扩展名)。对于复杂的流,请使用上面的手动流程。
## 处理加密流(AES-128)
在播放列表中查找 `#EXT-X-KEY:METHOD=AES-128,URI="enc.key"`:
```bash
curl -s "https://example.com/path/enc.key" -o enc.key
ffmpeg -allowed_extensions ALL -i local_playlist.m3u8 -c copy output.mp4
```
## 输出
最终视频保存为 `~/Downloads/<output_name>.mp4`