适用场景:抓取自己已购买/已授权的小鹅通直播回放、课程视频。核心思路是「通过网络面板抓取播放清单(m3u8)→ 批量下载分片 → 用 ffmpeg 拼接成完整 mp4」。文件抓下来后是无损的,画质音质与原片一致。
一、原理速览
小鹅通的直播回放/视频,典型工作方式:
- 视频被切成很多个 10 秒分片(
.ts),由播放器逐个请求播放。 - 一个文本清单文件 m3u8 记录了全部分片的字节区间和时长,以及有无加密。
- 分片地址形如:
其中playlist.f3_0.ts?start=0&end=2165383&type=mpegts&sign=...&t=...&time=...&us=...&uuid=...start/end是该分片在整段流里的字节偏移,sign/t/us/uuid/time是鉴权参数(有时效,过期需重新抓)。
关键点:
- 只要拿到 m3u8 清单,就能拿到全部分片的下载地址。
- 如果清单里没有
EXT-X-KEY,说明未加密,可直接下载拼接。 - 如果时间太长签名的
t/time过期,重新回网页刷新一次播放清单即可。
⚠️ 提醒:Network 里的请求带鉴权信息(可能含登录凭证),只用于你自己的设备,不要外发。
二、第一步:抓到 m3u8 清单(关键)
以下用 Chrome/Edge 操作:
- 登录小鹅通课程/回放页,进入视频播放页。
- 按
F12打开开发者工具,切到 Network(网络) 面板。 - 顶部过滤器框输入
m3u8。 - 点击播放,或拖动进度条,让播放器重新拉取清单。
- 请求列表会出现一条以
.m3u8结尾的记录(体积很小,几 KB),名字类似playlist.f3.m3u8/index.m3u8。 - 右键该请求 → Copy → Copy as cURL,整段复制。
如果过滤
m3u8没结果,就清空过滤器,找到名字里含m3u8的请求即可(注意别抓成大量.ts分片)。
抓到的 cURL 长这样:
curl --url 'https://encrypt-k-vod.xet.tech/522ff1e0vodcq1252524126/dc874c6a5001834817865932933/playlist.f3.m3u8?sign=2d65ea85...&t=6a98da93&us=...&time=...&uuid=...' \
-H 'Referer: https://app4vz27eou7929.h5.xet.pomoho.com/' \
-H 'User-Agent: Mozilla/5.0 ...'
三、第二步:下载 m3u8 到本地
把上面 cURL 里的地址(含 ?sign=...)保存成本地 playlist.m3u8 文件。
可以用 cURL 自己下载:
curl -s -o playlist.m3u8 \
-H "Referer: https://app4vz27eou7929.h5.xet.pomoho.com/" \
-H "User-Agent: Mozilla/5.0" \
"https://encrypt-k-vod.xet.tech/.../playlist.f3.m3u8?sign=...&t=...&us=...&time=...&uuid=..."
查看清单,确认是否加密:
grep "EXT-X-KEY" playlist.m3u8 # 有输出 = 加密;无输出 = 未加密
四、第三步:批量下载全部分片
用 Python 解析 m3u8,生成下载清单并 16 路并行下载:
import os, urllib.parse
base = "https://encrypt-k-vod.xet.tech/522ff1e0vodcq1252524126/dc874c6a5001834817865932933/"
raw = open("playlist.m3u8", encoding="utf-8").read()
segs = [l for l in raw.splitlines() if l and not l.startswith("#")] # 每个分片URL
os.makedirs("segs", exist_ok=True)
with open("seg_cmds.txt", "w") as f:
for i, s in enumerate(segs):
u = urllib.parse.urljoin(base, s)
f.write(f"segs/{i:04d}.ts\t{u}\n")
print("分片数量:", len(segs))
# 16 路并行下载(带上 Referer 和 UA)
awk -F'\t' '{print $1"\t"$2}' seg_cmds.txt | \
xargs -P 16 -n 2 bash -c 'o="$0"; u="$1"; \
curl -s -o "$o.fetch" -H "Referer: https://app4vz27eou7929.h5.xet.pomoho.com/" \
-H "User-Agent: Mozilla/5.0" "$u" && mv "$o.fetch" "$o"'
# 校验:分片数量一致、没有空文件
ls segs/*.ts | wc -l
find segs -name "*.ts" -size -1000c | wc -l
五、第四步:拼接成完整 mp4(无损)
用 ffmpeg 的 concat 方式逐段拼接,不重新编码,速度快且无损:
python3 -c "
with open('segs_list.txt','w') as f:
for i in range(853): # 853 改成你的实际分片数
f.write(f\"file 'segs/{i:04d}.ts'\n\")
"
ffmpeg -y -f concat -safe 0 -i segs_list.txt -c copy -movflags +faststart 输出.mp4
校验结果:
ffprobe -v error -show_entries format=duration,size \
-show_entries stream=codec_name,codec_type,width,height \
-of default=noprint_wrappers=1 输出.mp4
六、遇到问题怎么办
| 现象 | 原因 / 处理 |
|---|---|
| 下载分片返回 403 | 签名过期,t/time 是时效参数;回网页重新播放一次,重新抓 m3u8 |
m3u8 里有 EXT-X-KEY(加密) |
需把 key 地址一并拿到;ffmpeg 有可能自动处理,否则需手动下载 key 后解密 |
| 找不到 m3u8 请求 | 先播放/拖动进度条刷新;清空过滤器找含 m3u8 的请求;勾选「保留日志」再刷新页面 |
| 视频很长、分片很多 | 耐心等下并行下载即可;16 路并行一条 2GB 视频通常几分钟内完成 |
七、可选:屏幕录制兜底方案
如果上面拿不到清单(例如 DRM/加密非常严),可用屏幕录制兜底:
- macOS:黑盒虚拟声卡 + QuickTime/OBS 录屏录音。
- 得到的是
.mov/.m4a,后续可用 ffmpeg 转格式/抽取音频:# 提取音频 ffmpeg -i 录制.mov -vn -acodec copy 音频.m4a
按本指南抓取的视频请确保你有对应内容的观看/授权权限,仅限个人学习使用。
评论 (0)
还没有评论,来抢沙发。