v-save 是一个多平台视频下载器,目前支持抖音、B 站、快手、小红书、YouTube 平台的视频解析预览和下载,其中抖音、B 站、快手已接入官方接口,支持登录态管理与多档画质选择,其他平台持续适配中。
- 统一后端 API,覆盖 Web、Mobile(iOS/Android)、Companion 三端。
- 支持多平台解析、预览、下载任务创建、文件回取与合并下载。
- 支持多平台登录态管理,抖音、b站、快手均已实现官方网页版接口对接以获取更高画质,兼容服务器环境。
- 包含个人中心和后台管理。
- 提供一键部署脚本,自动适配国内外不同网络环境,可检测docker环境自动安装部署。
- ios端支持deeplink,抖音、b站分享链接跳转自动解析,无需手动切换app复制粘贴,提供静默下载模式可后台异步队列自动下载。
| 目录 | 说明 |
|---|---|
backend/ |
NestJS 后端,负责认证、解析、下载、通知、后台治理、Runtime 监控 |
frontend/ |
Vite + React Web 用户端与管理后台 |
mobile/ |
Expo + React Native 移动端 |
companion/ |
macOS 本机登录桥接工具,负责拉起 Chrome 完成抖音扫码 |
scripts/ |
部署与运维脚本 |
- Backend: NestJS、TypeORM、MySQL、Axios、Puppeteer Core
- Frontend: Vite、React、Tailwind CSS、Zustand、Vitest
- Mobile: Expo、React Native、expo-router、SecureStore
- Companion: SwiftUI / AppKit、Chrome DevTools Protocol
适合服务器直接部署完整服务栈:
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh)如果这条命令长时间没有任何输出,通常不是 deploy.sh 本身卡住,而是服务器访问 raw.githubusercontent.com 过慢或不可达。可改用 GitHub 仓库压缩包方式启动:
tmpdir="$(mktemp -d)" \
&& curl -fsSL https://github.com/chopper1026/v-save/archive/refs/heads/main.tar.gz -o "$tmpdir/v-save.tar.gz" \
&& tar -xzf "$tmpdir/v-save.tar.gz" -C "$tmpdir" \
&& bash "$tmpdir/v-save-main/scripts/deploy.sh" --force-region cn常用参数:
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --public-host your.domain.com
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --install-dir /opt/v-save
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --force-region cn
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --refresh-repo
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --image-tag latest如果服务器位于中国大陆,脚本会优先从 Docker 官方 GitHub 仓库下载安装脚本,并默认使用 AzureChinaCloud 安装镜像。若你需要手动覆盖,可这样执行:
export V_SAVE_DOCKER_INSTALL_SCRIPT_URL_CN="https://raw.githubusercontent.com/docker/docker-install/master/install.sh"
export V_SAVE_DOCKER_INSTALL_MIRROR_CN="AzureChinaCloud"
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) --force-region cn脚本会自动完成:
- 检测架构并选择合适的 Docker 镜像。
- 在中国大陆网络环境下自动启用镜像加速。
- 检查 Docker / Docker Compose。
- 生成随机数据库密码、
JWT_SECRET,以及首次初始化用的超级管理员密码。 - 写入部署目录下的
.env与backend/.env。 - 拉起
frontend + backend + mysql。 - 输出访问地址、数据库用户名,以及首次生成的超级管理员密码。
补充说明:
- 如果服务器没有安装
git,脚本会使用仓库压缩包部署;再次运行时默认复用现有安装目录,不会每次都重新下载。 - 如果服务器安装了
git,再次运行脚本时也会默认复用当前安装目录中的现有代码;只有显式加上--refresh-repo时,才会执行git fetch && git pull。 - 脚本默认直接拉取 Docker Hub 上的官方
latest镜像部署,不会在服务器本地构建镜像;如果需要固定版本或回滚,可通过--image-tag或V_SAVE_IMAGE_TAG指定 tag。 - 一键部署默认将前端映射到宿主机
7752端口、后端映射到宿主机7753端口,便于后续通过 1Panel/Nginx/Caddy 做反向代理。 - 注册入口默认关闭。部署完成后可用自动生成的超管账号登录后台,在“系统设置”里手动开启注册入口。
- 一键部署默认超管邮箱是
admin@gmail.com;脚本每次运行都会明文输出当前超管邮箱和密码。若本次没有重置密码,终端会明确提示“脚本本次未重置”。
如果你需要丢弃旧的部署状态、容器、数据卷和端口占用,重新初始化一套全新的环境,可执行下面这组命令。
注意:这会删除现有 MySQL 数据卷,旧数据不可恢复。
docker compose -f /opt/v-save/docker-compose.release.yml --profile with-mysql down 2>/dev/null || true
docker rm -f v-save-mysql v-save-backend v-save-frontend 2>/dev/null || true
docker volume rm v-save_mysql_data 2>/dev/null || true
docker volume rm v-save_backend_tmp 2>/dev/null || true
rm -rf /opt/v-save
rm -f /opt/.v-save-deploy-state.env
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh)如果你只想保留 MySQL 数据、但清理代码目录和容器,请不要删除 v-save_mysql_data 卷;同时需要保留 /opt/.v-save-deploy-state.env,否则脚本会生成新的数据库密码并与旧数据卷中的凭据不匹配。
适合把镜像在本地或 GitHub Actions 中提前构建好,再让服务器只执行 pull + up -d。一键部署脚本现在默认就会走这条路径,并从 Docker Hub 拉取官方镜像。
仓库已提供生产专用 Compose 文件 docker-compose.release.yml 和 Docker Hub 发布工作流 docker-publish.yml。
在 GitHub 仓库中准备下面这些配置:
- Secrets:
DOCKERHUB_USERNAMEDOCKERHUB_TOKEN
- Variables:
V_SAVE_BACKEND_IMAGE,例如yourname/v-save-backendV_SAVE_FRONTEND_IMAGE,例如yourname/v-save-frontend- 可选:
V_SAVE_NPM_REGISTRY、V_SAVE_APT_MIRROR、V_SAVE_APT_SECURITY_MIRROR、V_SAVE_PIP_INDEX_URL、V_SAVE_ALPINE_MIRROR、V_SAVE_VITE_API_BASE_URL
工作流会在推送 main 分支或 v* tag 时,自动构建并推送多架构镜像到 Docker Hub,同时生成:
latest- Git commit short SHA
- Git tag 名(仅 tag 发布时)
服务器默认会从 Docker Hub 拉取:
chopper1026/v-save-backend:latestchopper1026/v-save-frontend:latest
如果你需要显式覆盖镜像名或 tag,可传参:
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh) \
--backend-image yourname/v-save-backend \
--frontend-image yourname/v-save-frontend \
--image-tag latest也可以先写环境变量,再执行脚本:
export V_SAVE_BACKEND_IMAGE=yourname/v-save-backend
export V_SAVE_FRONTEND_IMAGE=yourname/v-save-frontend
export V_SAVE_IMAGE_TAG=latest
bash <(curl -fsSL https://raw.githubusercontent.com/chopper1026/v-save/main/scripts/deploy.sh)启用该模式后,服务器只会:
- 拉起
mysql pull后端与前端镜像- 使用
docker-compose.release.yml启动容器
如果需要回滚,只要把 V_SAVE_IMAGE_TAG 改成旧版本 tag 或旧的 git SHA,再重新执行脚本。
cd backend && npm install
cd ../frontend && npm install
cd ../mobile && npm install --legacy-peer-deps
cd ../companion && npm installcd backend
cp .env.example .env把 backend/.env 中的 JWT_SECRET 改成至少 24 位随机字符串,再启动:
npm run start:dev后端默认地址:http://localhost:3001/api
cd frontend
npm run devWeb 默认地址:http://localhost:3000
cd mobile
cp .env.example .env
npm run typecheck
npm run ios
# 或 npm run android注意:
EXPO_PUBLIC_API_BASE_URL必须指向手机能访问的后端地址。- 真机调试不要使用
localhost,请改成http://<LAN-IP>:3001/api。 npm run prebuild不再用于日常启动;如果你确实要重建原生工程,请改用npm run native:rebuild。
cd companion
npm run generate:xcodeproj
npm run devCompanion 默认仅监听本机:http://127.0.0.1:37219
适合本机调试 Web + Backend:
cp backend/.env.docker.example backend/.env然后至少完成两项配置:
- 把
backend/.env里的JWT_SECRET改成真实随机值。 - 按你的数据库环境修改
DATABASE_HOST / DATABASE_USER / DATABASE_PASSWORD。
如果你只是想拉起前后端容器:
docker compose up -d --build
docker compose ps如果你要连同 MySQL 一起拉起,推荐直接使用上面的一键部署脚本,因为它会自动生成并对齐根目录 .env、backend/.env、MySQL 账号和后端连接配置,避免手工配置不一致。
JWT_SECRET必填,必须使用强随机值。当前版本会拒绝公开默认值或占位值启动。DATABASE_HOSTDATABASE_PORTDATABASE_USERDATABASE_PASSWORDDATABASE_NAMECORS_ORIGINSPUBLIC_API_ORIGINWEB_PUBLIC_ORIGINSUPER_ADMIN_EMAILSSUPER_ADMIN_BOOTSTRAP_EMAILSUPER_ADMIN_BOOTSTRAP_PASSWORDSUPER_ADMIN_BOOTSTRAP_NICKNAME
参考文件:
backend/.env.examplebackend/.env.docker.example
EXPO_PUBLIC_API_BASE_URL
参考文件:
mobile/.env.example
cd backend
npm run lint
npm run test
npx jest src/download/download.service.spec.ts --runInBandcd frontend
npm run lint
npm run test
npx vitest run src/hooks/useDouyinBridgeAuth.test.tscd mobile
npm run typecheckcd companion
npm testbash scripts/deploy.test.sh所有接口(除标注外)均需要 JWT 认证(Authorization: Bearer <token>)。
POST /api/auth/registerPOST /api/auth/loginGET /api/system-settings/publicGET /api/proxy/fetchPOST /api/runtime/client-eventsGET /healthz
POST /api/download/parse— 解析视频链接POST /api/download/get-url— 获取下载链接POST /api/download/create-task— 创建异步下载任务GET /api/download/tasks/:id— 查询任务状态GET /api/download/tasks/:id/file— 下载任务产物文件GET /api/download/merge— 合流下载POST /api/download/prepare-native-silent— 原生静默下载准备GET /api/download/quality-status— 查询画质补全状态
GET /api/download/history— 查询下载历史(支持分页、平台、日期筛选)GET /api/download/stats— 下载统计DELETE /api/download/history— 按条件清空历史DELETE /api/download/history/batch— 批量删除历史DELETE /api/download/history/:id— 删除单条历史
GET /api/users/profilePATCH /api/users/profilePATCH /api/users/account/passwordPATCH /api/users/account/phone
GET /api/notificationsGET /api/notifications/unread-countPATCH /api/notifications/:id/readPATCH /api/notifications/read-allDELETE /api/notifications/clear
GET /api/bilibili/auth/statusPOST /api/bilibili/auth/qrcodeGET /api/bilibili/auth/qrcode/pollPOST /api/bilibili/auth/refreshDELETE /api/bilibili/auth/session
GET /api/douyin/auth/statusPOST /api/douyin/auth/sessionPOST /api/douyin/auth/bridge/startGET /api/douyin/auth/bridge/statusPOST /api/douyin/auth/bridge/completeDELETE /api/douyin/auth/session
GET /api/kuaishou/auth/statusPOST /api/kuaishou/auth/qrcodeGET /api/kuaishou/auth/qrcode/pollPOST /api/kuaishou/auth/sessionDELETE /api/kuaishou/auth/session
GET /api/admin/users— 用户列表GET /api/admin/users/audit— 用户审计日志PATCH /api/admin/users/:id/role— 修改用户角色PATCH /api/admin/users/:id/status— 修改用户状态GET /api/admin/system-settings— 系统设置PUT /api/admin/system-settings— 更新系统设置GET /api/admin/audit— 操作审计GET /api/admin/download-modes/schema— 下载模式 SchemaGET /api/admin/download-modes/configs— 下载模式配置PUT /api/admin/download-modes/configs/:platform/:clientType— 更新下载模式配置GET /api/admin/runtime-dashboard— Runtime 监控面板GET /api/admin/runtime-dashboard/chains— Runtime 链路列表GET /api/admin/runtime-dashboard/chains/:traceId— Runtime 链路详情GET /api/auth/health— 认证健康状态
- 仓库不包含已跟踪的真实
.env、私钥或第三方服务密钥。 - Web 端登录态只保存在
sessionStorage,不会再把明文密码写入浏览器持久存储。 - 抖音登录态管理页不再显示 Cookie 片段。
- 部署脚本会生成随机密钥;数据库密码会在当前部署终端摘要里显示,超级管理员初始化密码只会在首次生成时明文显示一次,
JWT_SECRET仅写入配置文件。
- Mobile 详细说明见
mobile/README.md - Companion 详细说明见
companion/README.md