通过抓包下载微信小程序中的视频
立泉有这个需求是因为《无界·线上艺术》在春节上架了单雯
和施夏明
的传承版昆曲《牡丹亭》,是我一直在寻找的演出视频。她/他们是我眼中这个时代最好的杜丽娘
和柳梦梅
,一定要下载收入资源库。
You-Get
和Downie
是我常用的下载工具,支持所有主流视频网站,而且Downie
还可以用User-Guided Extraction
模式手动下载不支持网站的内容。不过它们都需要视频所在网页的URL
链接才能解析,而这个小程序播放器并非公开网页,没有暴露出任何URL
,所以此路不通。
只剩下一种方法,抓包,无论软件怎么隐藏,都必须通过网络把服务器上的源视频下载到本地才能播放,一定会产生大量TCP
数据包,通过Wireshark
追踪一定能找到源视频地址。主流视频平台一般会采用诸如分段、加密等方式增加解析难度,但我不觉得一个冷门的小公司产品会这么做,试试看。
Wireshark
首先解决如何用Mac
端Wireshark
捕捉手机端数据包的问题,一种方式是用连接有线网络的Mac
开启网络共享创建Wi-Fi
热点,手机连接此热点后产生的所有网络数据都会通过Mac
,即可被捕捉。另一种方式是先用Charles
之类的软件在Mac
上创建代理服务,然后同局域网内手机设置代理指向它,也可以实现转发网络数据包。但iPhone
内置的代理只有HTTP Proxy
,不借助第三方软件只能把HTTP
通信包转发到Mac
,而有些视频流并非HTTP
协议,所以连接Mac
热点更好一些。
只有连接有线网络的Mac
可以开启Wi-Fi
共享。
手机播放视频时发现Wireshark
捕捉到大量与同一个IP
交互的TCP
数据包,上层是HTTP
协议:
试着Follow
它的TCP Stream
,发现明文HTTP
请求:
图中Host
和GET
组合就是视频的URL
地址:
http://130*********.vod2.myqcloud.com/32a5c501vodcq130*********/9111a3b75285890814193748493/************UA.mp4
从HTTP
的Rang
参数和206
响应码可以看出客户端是在以分段方式请求数据,视频总长度1,313,589,669
字节,本次请求的是0~262,143
字节。这种分段请求是播放器加载网络媒体的一种实现方式,根据进度条位置按需下载对应的数据片段,而非不切实际把整个视频下载下来。不过普通MP4
视频是嵌套结构,客户端必须从头加载而不能只靠中间的部分数据播放,这种方式要求源视频必须是特殊的Fragmented MP4
。另一种常见播放方式是HLS
,先把原视频切割成小片段,生成作为索引的M3U8
文件,客户端再按需请求这些片段,实现渐进式加载播放。
用浏览器打开URL
,运气不错,无须授权并且是未分割的完整视频,可以直接保存到本地。
惊鸿一瞥,单雯
和施夏明
的【山桃红】后半段,我真的是第一次看到✨。
HTTPS
不过大部分情况下从Wireshark
看到的并不是HTTP
,而是密密麻麻的TLS
,即加密HTTPS
:
Follow
它的TCP Stream
会看到加密后的HTTP
报文,理所当然一片乱码,分辨不出有效信息:
本以为Wireshark
能像Charles
那样把自己的根证书导入系统再以中间人方式监听HTTPS
通信,但搜索一番发现并不可以,它比Charles
更底层而不能这样做。
仅有的两种方法在下载微信视频时都不可行:
- 要求提供服务端的
HTTPS
私钥(怎么可获得🤷🏻)。 - 要求从浏览器导出
HTTPS
使用的实际通信密钥(微信小程序视频不可能用浏览器打开🤷🏻)。
车到山前必有路,既然已经知道客户端是使用HTTPS
分段请求资源的方式下载视频,那就用Charles
看看:
成功解密,完整URL
映入眼帘,左边一列是大量分段请求,Charles
用媒体
标记也验证了它们就是下载的视频片段。
尾声
之前一直以为网络视频都是先在服务端被分割后再供客户端点播,即HLS
和M3U8
,原来也可以不分割,让客户端使用HTTP
分段请求特性按需下载片段。这并非从书上看到的结论,而是自己在需求驱动下一步步剥茧抽丝发现的,这些探索过程十分有趣。