rust,树莓派··约 3 分钟读完

视频网站 M3U8 链接经常失效?自己搭个下载服务一劳永逸

摘要:自建M3U8视频下载服务解决方案 针对M3U8链接易失效的问题,作者开发了基于Rust的服务器端下载方案。该方案通过浏览器油猴脚本捕获链接,由服务器执行下载任务,直接存储至NAS或服务器硬盘。优势包括:不占用本地空间、多设备共享下载队列、后台持续运行。服务端采用5MB的轻量级二进制程序,支持systemd自启动,内存占用仅80MB。特别处理了M3U8链接快速过期问题,并实现自动转码为MP4格式。项目已开源,兼容树莓派等设备。
rust后端音视频

视频网站 M3U8 链接经常失效?自己搭个下载服务一劳永逸

用油猴脚本抓过视频的人应该都有这种经历:好不容易抓到 M3U8 链接,粘贴到下载器里,结果提示"解析失败"。不是下载器的问题,是链接过期了。

我之前也是这么折腾的——浏览器抓链接 → 粘贴到下载器 → 失败 → 刷新页面重新抓 → 再试。而且下载到本地硬盘,几个 G 的视频下几个,硬盘空间数字肉眼可见地往下掉。

后来换了个思路:让浏览器只负责抓链接,下载交给服务器去做。

服务端下载的体验

这样有几个好处:

  • 浏览器关了也不影响下载,任务在服务器上跑
  • 视频直接存 NAS 或服务器硬盘上,不用占本机空间
  • 手机、平板、电脑共享同一个下载队列,不用各端重复操作
  • 下载完成后浏览器弹个系统通知,看一眼就行

怎么搭

实现其实不复杂。后端用 Rust + axum 写了个 Web 服务,编译出来 5MB 的二进制,配置个 systemd 开机自启就完事了。

# 服务配置文件 /etc/systemd/system/down.service [Unit] Description=down Server After=network.target [Service] ExecStart=/home/down/m3u8_downloader Restart=on-failure [Install] WantedBy=multi-user.target

油猴脚本这边做了个简化版,去掉之前"下载到浏览器"的逻辑,改成纯发送链接到服务端。检测到 M3U8 链接后,自己选择要不要提交下载:

// 只发链接到服务端,不下到浏览器 const taskName = `视频名_${Date.now()}`; const taskId = await startDownload(m3u8Url, taskName);

遇到过的问题

中间踩了个坑:有些视频源返回的 M3U8 链接几秒钟就过期。服务端收到的是 POST 请求,但去请求 M3U8 的时候服务器已经返回 HTML 错误页了。

解决方案:在下载逻辑里加了 Content-Type 检查,第一次请求如果返回 text/html 就直接报错,不做重试。这样用户快速重新提交一次就行了。

输出目录的小技巧

设置里可以把输出目录指到 NAS 的挂载路径,下载完直接进媒体库。FFmpeg 自动把 TS 转成 MP4,兼容性没问题。

项目完全开源,树莓派 3B+ 以上都能跑,内存占用稳定在 80MB 左右: https://github.com/Sunrisies/m3u8_download