Shelf

Shelfapp · v0.1.0

闭源开发中

Rill

轻量、原生的 macOS 下载管理器:多线程动态分段、断点续传、浏览器接管、HLS 嗅探、B站/X 站点下载

popup.png

Rill

轻量、原生的 macOS 下载管理器。多线程动态分段、断点续传、浏览器接管、网页视频嗅探(含 HLS)、队列 / 限速 / 计划任务。

  • 原生 Swift 6 + SwiftUI,macOS 26+,Universal 安装包约 6 MB
  • 下载引擎:IDM 式动态分段 —— 连接空闲时把「剩余最多」的分段一分为二,尾部不拖慢
  • 断点续传:分段进度落盘,If-Range 校验远程文件未变;链接过期可「刷新下载地址」保留进度
  • HLS:master 选清晰度、AES-128 解密、fMP4、分片级续传;有 ffmpeg 时无损合并为 MP4
  • 悬浮进度窗(可关)、自动下载到默认目录(可选)、一键清除列表(不删文件)
  • 浏览器:Chrome / Brave 扩展(Native Messaging):接管下载、右键菜单、批量链接、视频/音频/HLS 嗅探
  • 站点集成:哔哩哔哩按需下载 视频 / 音频 / 字幕 / 弹幕 / 封面;X (Twitter) 下载推文中的 原图 / 视频。每一项单独勾选,默认值按站点记忆

站点下载(哔哩哔哩)

入口:扩展 popup 在视频/番剧页显示「下载此页面」;或在 Rill 里粘贴链接(也认 BV…、av…、ep…、ss…);剪贴板监听同样识别。

维度 选项 输出
视频 格式(自动 / DASH / 单文件 MP4)、清晰度、编码(AVC/HEVC/AV1) 名称.mp4,与音频合并(ffmpeg 优先,系统框架兜底,失败则保留独立文件)
音频 音质(含杜比 / Hi-Res) 合并进视频,或单独 名称.m4a / .flac
字幕 语言(可多选,含 AI 字幕)、格式 SRT / WebVTT / ASS 名称.zh-CN.srt
弹幕 XML / ASS(轨道排布,防遮挡底部字幕区) 名称.danmaku.ass / .xml
封面 — 名称.jpg
  • 多P / 番剧:每集一个任务,默认只勾当前这一集,放在以标题命名的文件夹里
  • 登录态:扩展交来页面时顺带交来 Cookie,Rill 按站点记住(~/Library/Application Support/Rill/site-sessions.json,0600),粘贴链接时复用;可在 设置 → 站点 清除。未登录时 DASH 最高 480P、单文件 MP4 最高 720P,「自动」格式会据此选择
  • 流地址约 2 小时过期:任务开始 / 续传时才向站点取地址,失效时自动重新获取,已下载的分段保留
  • 已完成的任务可在详情里「追加下载」其他维度,或「重试失败的内容」

站点下载(X / Twitter)

  • 推文链接(x.com/…/status/…、twitter.com/…):列出推文里的全部图片和视频;引用推文的媒体作为第二项,默认不勾选
  • 图片一律请求 name=orig 原图(不是 large / small 缩略图),失败时回退 4096x4096;多图按 01 02 … 编号,保存到 Pictures
  • 视频 / GIF:可选清晰度,默认最高码率 MP4
  • pbs.twimg.com/media/… 图片直链(包括浏览器里右键「图片另存为」被 Rill 接管的下载)同样按原图下载,文件名带正确扩展名
  • 数据来自嵌入推文使用的公开 syndication 接口,公开推文无需登录;受保护 / 年龄限制的推文暂不支持

扩展新站点

站点层与下载引擎解耦,新增站点只需:

  1. 在 Packages/RillCore/Sources/RillCore/Sites/<Site>/ 实现 SiteExtractor:descriptor(网址规则、支持的维度)、catalog(列出分集与可选项,不取流地址)、materialize(按用户选择给出本次要下的产物)、可选的 generators(字幕/弹幕等本地生成)
  2. 在 SiteRegistry.standard 注册一行

浏览器扩展的页面识别规则由 app 在 ping 时下发,无需改扩展;字幕 / 弹幕的 SRT、VTT、ASS、XML 输出在 Sites/Shared/ 中可直接复用。

目录

Packages/RillCore/     核心逻辑(无 UI),可独立 swift test
  Engine/              HTTPStreamer(带背压)、Downloader(分段引擎)、BundleDownloader(站点多产物)、MediaMux、Probe、FileWriter、RetryPolicy
  HLS/                 M3U8Parser、HLSDownloader、AES 解密、合并
  Scheduling/          DownloadManager(队列/持久化/计划)、RateLimiter(令牌桶)、Preferences
  Sites/               站点抽象(SiteExtractor / MediaCatalog / BundleSelection)、Shared(字幕/弹幕格式)、Bilibili
  Persistence/         GRDB 存储
  IPC/                 Unix socket 服务端(仅当前用户)
App/                   SwiftUI 界面、剪贴板监听、通知、浏览器注册
NativeHost/            rill-nmh:浏览器 Native Messaging 宿主(打包进 Rill.app/Contents/MacOS)
BrowserExtension/      Chrome MV3 扩展(无构建步骤,直接“加载已解压的扩展程序”)
Scripts/               测试服务器、图标生成、界面快照、安装与发布脚本

开发

brew install xcodegen          # 工程由 project.yml 生成
xcodegen generate
open Rill.xcodeproj

测试(启动本地 Range/HLS 测试服务器,校验 SHA-256):

cd Packages/RillCore && swift test

站点冒烟测试会访问真实网络,默认跳过:

RILL_LIVE_BILIBILI=1 swift test --filter BilibiliLiveTests
RILL_LIVE_X=1 swift test --filter XLiveTests

安装到应用目录

Scripts/install.sh            # Release 构建 → 替换 /Applications/Rill.app → 重新启动

安装浏览器扩展(Chrome / Brave)

设置 → 浏览器 → 「安装扩展…」(或菜单 下载 → 安装浏览器扩展):

  1. Rill 注册 Native Messaging 宿主,并打开浏览器的扩展页面
  2. 悬浮的安装向导里:开启「开发者模式」,把「Rill 扩展」拖进扩展页面 (或点「加载已解压的扩展程序」,⇧⌘G 粘贴向导里拷贝的路径)
  3. 扩展连上 Rill 后向导自动显示「安装成功」

扩展文件位于 ~/Library/Application Support/Rill/Extensions/chrome,ID 固定为 cdpdmipkkfhbkfgfaadhajkeedeegoic。 非商店扩展在 macOS 上无法静默安装(Chrome 的安全策略);上架 Chrome Web Store 后可改为真正的一键安装(Brave 同样使用 Chrome 商店)。

发布

DEVELOPER_ID="Developer ID Application: … (TEAMID)" TEAM_ID=TEAMID NOTARY_PROFILE=rill Scripts/release.sh

不带环境变量时生成 ad-hoc 签名的本地测试 DMG。

待办

  • Sparkle 自动更新(需要 EdDSA 密钥与 appcast 托管地址)
  • 无 ffmpeg 时的原生 TS → MP4 转封装
  • Chrome Web Store 上架(上架后把商店分配的扩展 ID 加入 Native Messaging 的 allowed_origins)
  • HLS 直播录制
  • 哔哩哔哩:课程(cheese,pugv/* 接口)、UGC 合集(ugc_season)批量展开
  • X:借助浏览器登录态(GraphQL)支持受保护 / 年龄限制的推文

版本

  1. v0.1.02026-09-30
    • 首个发布(dd3eadc)
    • 动态分段下载引擎、断点续传、HLS
    • Chrome / Brave 扩展接管
    • 站点集成:哔哩哔哩(视频/音频/字幕/弹幕/封面)、X (Twitter)
    • Universal,ad-hoc 签名(首次打开需右键→打开)