mybili架构深度解析:Laravel + Octane + Horizon + Redis + SQLite构建NAS下载服务的完整方案
【免费下载链接】mybili哔哩哔哩收藏夹备份程序 ~ アレ 视频不见了哟!项目地址: https://gitcode.com/gh_mirrors/my/mybili
mybili是一款面向 NAS 的哔哩哔哩收藏夹备份下载服务,它用Laravel + Octane + Horizon + Redis + SQLite这套组合,把"定时同步收藏夹 → 队列化下载视频/弹幕 → Web 页面管理"做成了一套可长期无人值守运转的轻量级系统。本文带你完整拆解它的分层架构、任务调度和部署方式,帮助你在 NAS 上稳定运行自己的 B 站视频下载服务。
一、mybili 是什么?NAS 上的 B 站收藏夹备份工具
对很多 UP 主粉丝和收藏党来说,"视频不见了哟!"是最大的噩梦。mybili 做的事情很简单:把你 B 站收藏夹里的视频,按最高画质自动下载并缓存到 NAS 本地。
它的核心能力包括:
- ⏰定时同步:每 10 分钟拉取收藏夹列表和视频信息,缓存标题、封面、简介
- 🚀队列化下载:通过 Redis 队列自动下载视频文件、分 P、音频和弹幕
- 📺Web 管理界面:浏览器即可浏览收藏夹、查看下载进度、在线播放预览
- 📡订阅发现:支持订阅合集与 UP 主,自动发现新视频
- 📂媒体库适配:生成人类可读的目录结构,直接接入 Emby 等媒体库
二、整体架构:5 个组件如何分工协作
mybili 的架构可以概括为一句话:Laravel 写业务,Octane 扛请求,Horizon 管任务,Redis 做缓冲,SQLite 存数据。
| 组件 | 职责 | 在 mybili 中的角色 |
|---|---|---|
| Laravel 11 | Web 框架 | 控制器、模型、服务层全部业务逻辑 |
| Octane + FrankenPHP | 高性能常驻运行时 | 让 PHP 常驻内存,Web 响应更快 |
| Horizon | 队列监控与调度 | 管理所有异步 Job 的并发、失败重试 |
| Redis | 缓存与队列 | 存临时缓存、限流时间槽、任务队列 |
| SQLite | 持久化数据库 | 存储收藏夹、视频、弹幕、设置等数据 |
依赖关系可以在 composer.json 中确认:框架laravel/framework ^11.9,另加laravel/octane和laravel/horizon两个官方扩展。
三、Web 层:Laravel 业务代码的组织方式
打开app/目录,整个业务按标准 Laravel 分层组织:
app/Http/Controllers/:8 个控制器对应 8 类页面,如 CookieController.php 负责上传登录凭证,DownloadQueueController.php 负责下载队列管理app/Models/:核心模型包括Video、VideoPart(分 P)、Danmaku(弹幕)、FavoriteList(收藏夹)、DownloadQueue(下载队列)app/Services/:真正干活的地方。VideoService.php、DownloadVideoService.php、DownloadQueueService.php 等封装了视频抓取、下载、排队逻辑app/Jobs/:15+ 个异步任务,如 DownloadVideoJob.php、DownloadDanmakuJob.php、UpdateFavListJob.php
这种"Controller 薄、Service 厚"的结构,让定时任务、HTTP 请求、队列 Job 三类入口都能复用同一套业务代码。
四、异步层:Redis 队列 + Horizon 任务编排
这是整个架构的"心脏"。mybili 把所有耗时操作都扔进队列:
- 入队:DownloadQueueService.php 用
unique_key做去重,同一视频不会重复入队,并支持priority优先级 - 调度:Horizon 按配置的并发数从 Redis 取出 Job 执行,失败自动重试
- 限流:ScheduledRateLimiterService.php 基于 Redis 的 ZSet 做"预安排时间槽"限流——不是失败了再重试,而是在任务触发时就算好下一次合法执行时间,配合风控挂起机制,把对 B 站接口的请求频率控制得很温和
- 监控:Horizon 自带 Web 仪表盘,每分钟通过
horizon:snapshot收集队列指标
这种设计的最大好处是:Web 进程和下载进程完全解耦。下载一个 2 小时的视频不会影响你浏览网页;反过来 Web 崩溃重启也不会中断正在进行的下载。
五、数据层:为什么是 SQLite?
对 NAS 单用户场景,mybili 做了一个很务实的选择:持久化数据全部放 SQLite,Redis 只存临时缓存和队列。
- 数据库文件就一个(容器内挂载在
/data/database.sqlite),备份 = 拷一个文件 database/migrations/目录下 40 个迁移文件清晰记录了表结构演进:videos、video_parts、danmaku、download_queue等- 早期版本曾把数据存在 Redis 里,项目专门写了 UpgradeRedisToSqlite.php 迁移命令,还配了 CheckCanUpgradedFromRedisMiddleware.php 拦截未完成升级的请求——可见作者对"数据可靠性"的态度
六、定时任务:无人值守的关键
所有"自动"行为都由routes/console.php中的调度器驱动,配合withoutOverlapping()防止任务重叠:
- 每 10 分钟:同步收藏夹列表、增量更新视频(只拉第一页)、更新订阅
- 每天 04:00:全量刷新收藏夹视频、修复无效视频
- 每 1 分钟:从
download_queue表取出任务派发 Job(app:process-download-queue) - 每小时:检查无分 P 的异常视频
注意一个细节:下载调度不直接调 B 站接口,而是先写 SQLite 的download_queue表,再由每分钟一次的调度命令取出来派发给 Horizon 队列。这让下载进度天然可查、可暂停、可重试——你在 Web 页面看到的"下载中/待处理/失败"状态都来自这张表。
七、部署:单容器跑 3 个进程
mybili 的 Docker 镜像(Dockerfile)内置了 4 个工具,并通过 supervisord.conf 管理 3 个常驻进程:
[program:web] command=frankenphp run # Octane Web 服务 [program:schedule] command=php artisan schedule:work # 定时调度器 [program:queue] command=php artisan horizon # 队列 worker三个进程都设置了autorestart=true,任何一个崩溃都会自动拉起。构建阶段则通过多架构(amd64 / arm64)下载静态编译的ffmpeg、yt-dlp、frankenphp,所以无论 x86 还是 ARM NAS(如群晖、飞牛、绿联)都能直接跑。
部署只需两条命令:
mkdir /mnt/user/mybili/data -p docker-compose up -d # 镜像 ellermister/mybili,映射 ./data 存视频、/data 存数据库八、总结:这套架构值得借鉴的 3 个思路
- 常驻进程 + 队列解耦:Octane 让 Web 轻快,Horizon 让重活异步,NAS 这种低功耗设备上也能长期稳定运转
- 轻量存储不妥协:SQLite 单文件数据库 + Redis 临时缓存的组合,省去了维护 MySQL 的负担,备份迁移极其简单
- 温和限速策略:预安排时间槽的限流器(ScheduledRateLimiterService.php)从源头避免触发接口风控,是长期无人值守的关键
如果你在 NAS 上想给 B 站收藏做一个"自动保险箱",mybili 这套 Laravel + Octane + Horizon + Redis + SQLite 方案,就是目前相当完整的答案。🎬
【免费下载链接】mybili哔哩哔哩收藏夹备份程序 ~ アレ 视频不见了哟!项目地址: https://gitcode.com/gh_mirrors/my/mybili
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考