一部有声书分成几十个文件,手机听到第十九章,换电脑又得翻文件名找位置。播放器能打开音频,却不一定能把书名、章节和播放进度一起管理好。Audiobookshelf 可以把有声书和播客整理成媒体库,让不同设备通过同一个账号继续收听。
先准备几本自己有权使用的音频,建一个小库,核对顺序、章节和进度,再迁入大量文件。VPS 要有足够的存储和出站带宽;如果经常离线听,还要测试客户端实际下载的内容。服务器能够在线播放,不能代表手机断网以后仍有完整文件。
数据分开存,迁移时才知道要带走什么
官方 Docker 镜像用 /config 保存 SQLite 数据库,用 /metadata 保存书籍信息、封面、日志和应用备份。音频文件另外挂载,常用路径为 /audiobooks 和 /podcasts。账号与进度、书目与封面、原始音频分别存在这些位置,只复制其中一处无法恢复完整媒体库。
数据库目录使用 VPS 的本地磁盘,不放在远程共享文件系统上。音频可以很大,选磁盘时先统计文件总量,再给导入、封面和备份留空间。播放过程中如果涉及转码,CPU 需求会随音频格式、客户端和并发变化,不适合仅凭“支持音频”就判断一台小机器够不够。
下面假设 Docker Engine 与 Compose 插件已经安装,当前账号有 Docker 权限。Caddy 安装在宿主机,audio.example.com 已解析到 VPS,80、443 可正常访问。示例域名、SSH 账号和文件路径都要替换。
mkdir -p /opt/audiobookshelf/{config,metadata,audiobooks,podcasts}
cd /opt/audiobookshelf
docker version
docker compose version
用四个挂载目录启动服务
将下面的内容保存为 compose.yaml。宿主机使用 13378 端口,容器实际监听 80,不要把两个端口一起改成 13378。四个数据目录互不嵌套,方便独立核对和备份。
services:
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:latest
restart: unless-stopped
ports:
- "127.0.0.1:13378:80"
environment:
TZ: Asia/Shanghai
volumes:
- ./config:/config
- ./metadata:/metadata
- ./audiobooks:/audiobooks
- ./podcasts:/podcasts
首次拉取当前稳定镜像后,记录摘要,并固定到核对过的正式版本或摘要。latest 会变化,edge 用于跟随开发提交,不适合拿来维持日常媒体库。修改运行用户时使用镜像支持的 user:,并同步调整目录权限;不要照搬其他媒体软件的 PUID 参数。
docker compose config --quiet
docker compose pull
docker image inspect ghcr.io/advplyr/audiobookshelf:latest --format '{{json .RepoDigests}}'
docker compose up -d
docker compose ps
docker compose logs --tail=100 audiobookshelf
curl -I http://127.0.0.1:13378/
如果日志显示无法创建数据库,先检查 config 的挂载、所有者和剩余空间。出现问题时保留目录,不要删库重装。应用容器重建以后,账号和一条测试播放记录应该仍然存在,这能验证数据确实落在了持久目录。
第一位管理员先在私人入口创建
在自己的电脑通过 SSH 转发访问初始化界面,打开本机 13379 端口。替换账号和服务器地址,创建管理员并设置独立密码。
ssh -N -L 13379:127.0.0.1:13378 [email protected]
准备让手机访问时,在宿主机 Caddy 添加下列站点段,验证配置后重载服务。Caddy 的反向代理支持应用需要的 WebSocket;若前面又加了另一层代理,还要检查它有没有阻断长连接。
audio.example.com {
reverse_proxy 127.0.0.1:13378
}
如果 Caddy 在另一个容器里,改用共享 Docker 网络上的服务地址,回环地址不能跨容器访问。首次用正式域名登录后,先测试播放与拖动进度,再连接客户端。登录页面可用而播放失败时,继续看媒体请求、权限和代理日志,不能只检查首页。
管理员管理媒体库,日常收听可以另建普通账号。家庭成员分别使用自己的账号,播放进度才能区分;共享一个账号会把不同人的位置混在一起。给成员开放指定库,确认无权访问的库确实不可见。公开 RSS 或其他分享入口需要单独核对范围,不要默认沿用登录后的权限。
先把一本书的目录整理好
按作者和书名建立目录,把同一本书的章节放在一起。多文件音频使用稳定的编号,例如 01、02 到 20,比未经整理的下载文件名更容易判断顺序。一本书拆进多个毫无关系的文件夹,扫描结果也可能被拆开。
在网页创建有声书库,选择容器内 /audiobooks,不能填宿主机 /opt/audiobookshelf/audiobooks。扫描完成后检查书名、作者、章节数、封面和总时长。目录结构、音频标签和已有元数据都可能参与识别,遇到不一致时先了解库的元数据优先级,再改原始文件。
不要直接对全部音频批量写标签或合并文件。先保留原始副本,对一本书做修改并核对播放器效果。工具能够合并音频不代表输出一定保留你需要的章节;章标题和时间点要在最终文件中实际检查。
播客单独建库,先订阅一个公开节目,核对下载目录、最新单集和保留规则。自动下载会继续消耗空间,VPS 小盘尤其需要看增长速度。已经下载的单集和尚未下载的订阅记录是两种状态,备份时要分清。
换设备继续听,做一次完整验证
浏览器播放一段,暂停后退出,再从另一台设备登录同一账号,检查进度是否一致。继续播放一小段并暂停,回到第一台设备确认更新。只看到同一本书出现在两端,不能证明进度同步已经工作。
选择客户端时查看其连接自建实例和离线功能的支持范围。填入正式 HTTPS 地址,确认服务器版本兼容;下载一本短书,再关闭网络试播,检查文件是否完整、章节是否可选。部分离线状态需要恢复网络后才同步,观察冲突处理,避免把两个设备长期同时播放同一本书。
在手机上测试锁屏、耳机暂停和网络切换。浏览器播放与原生客户端的后台行为可能不同,长时间听书应选实际能稳定使用的方式。播放卡顿时记录客户端、文件格式和时间点,再看服务器是否转码、CPU 是否持续占满以及传输是否断开。
同一文件在浏览器正常、某个客户端异常,可以先换另一份常见格式音频对比。不要急着重新编码全部媒体。服务端、代理、客户端和文件本身都可能参与问题,找到是哪一层再处理。
备份进度,也备份原始音频
应用内备份主要帮助恢复应用状态,不能替代原始媒体的独立副本。小库可以安排短暂停机,打包四个目录与 Compose;大库应分别备份媒体文件和应用数据,并记录同一批备份的时间及版本。
cd /opt/audiobookshelf
mkdir -p /opt/backups
docker compose stop audiobookshelf
tar -czf "/opt/backups/audiobookshelf-$(date +%F-%H%M).tgz" compose.yaml config metadata audiobooks podcasts
docker compose start audiobookshelf
执行前确认备份位置有空间,打包失败也要恢复服务。把副本复制到另一台机器或独立存储;压缩包和原文件都在同一块 VPS 磁盘上,无法应对整机丢失。备份中包含账号与私人收听记录,应限制访问。
恢复时用备份对应的镜像,在独立目录、不同回环端口启动,先不接正式域名。检查账号、书目、封面、较早的播放进度和几本书的实际播放,再确认播客文件是否齐全。升级前读发布说明并做新备份,发生数据库迁移以后,回退需要旧版本与升级前数据配套。
库整理稳定以后,再逐步加入更多书。每次导入都检查扫描结果,比等几百本书混在一起再重做目录省事。保存原始音频和整理规则,下次迁移时就能带走完整的媒体库和自己的收听位置。