最近做了一个自托管项目 Personal Media Downloader(PMD),定位很简单:把视频网站的下载、管理、播放和上传整合到一个网页里。对标的就是常见的YouTube在线下载网站。
当我学的足够慢,我就可以什么都不用学😋
一、目的
为了实现听歌自由,我看YouTube上的歌也不错,直接下载下来也不是不能听,恰逢deepseek有大更新,于是就有了这么个项目,核心功能就是调用yt-dlp下载视频网站上的视频、音频到服务器,配合music-tag-web把元数据、歌词、封面加进去,然后直接用webdav上传到123云盘,再使用clouddrive2挂载到本地,最终使用emby听歌。是不是超级绕?😇
二、过程
爬哔哩哔哩、YouTube当然也不是从零开始,之前就知道有yt-dlp这个项目的存在,所以本项目只是yt-dlp的前端实现,先用chatgpt简单沟通了1个多小时,获取了很长的提示词,然后使用codex调用deepseek v4 flash 0731的api,一股脑全丢给了ai,17分钟就做出了这个项目的雏形,然后就是不断的调试、验证、新增功能、调试……总耗时大约10h,花费8.39元,本项目保证完全使用ai产出的代码。总的来讲最终是可用的、美观的,但是我不知道是不是安全的,我尽量在提示词中让ai注意安全了,但我并没有能力去检验,所以我认为用ai做一些自用的小工具还是很舒适的,做公开服务应当具备专业知识。
本次vibe coding美名其曰开发,对我来说更像是一场游戏,23年我就用chatgpt改过论文,现在都能做出这种小玩意了,不得不感慨ai的进步如此迅猛。
三、展示一下




四、介绍与部署
4.1介绍(本节纯ai生成)
一个基于 yt-dlp 的自托管个人媒体下载管理平台。粘贴链接即可下载音频/视频,支持实时进度、文件库管理、在线播放与 WebDAV 上传,响应式设计,适配PC与移动端。
PMD基于 yt-dlp,支持 B 站、YouTube 等绝大多数 yt-dlp 支持的网站,只需要粘贴链接,就能下载视频或音频。支持 MP4、MP3、M4A、FLAC 等格式,以及 480P 到 4K 的画质选择,播放列表和合集也可以批量下载。
除了下载之外,PMD 还内置了实时任务管理,通过 WebSocket 实时显示下载进度、速度和剩余时间。下载完成后会自动进入文件库,支持在线播放、大文件流式播放、搜索、排序、多选管理,还可以一键上传到 WebDAV。
项目采用 React + FastAPI + SQLite 技术栈,整个系统只有 前端 Nginx 和 后端 FastAPI 两个容器。
4.2部署
只做了Linux X64架构的镜像,如有需要可自己用ai做一套arm架构的。
生成的配置文件也很详细,若觉得太过繁琐也可自行使用ai精简下。
# ============================================================
# Personal Media Downloader
# ============================================================
# 使用步骤:
# 1. 把本文件放到目标机器任意目录
# 2. 修改下方 JWT_SECRET 为强随机值:
# python -c "import secrets; print(secrets.token_urlsafe(48))"
# 3. 执行 docker compose up -d
# 4. 浏览器访问 http://服务器IP:8080 (默认账号 admin / admin,首登强制改密)
# 数据说明:
# ./data 数据库 + 临时文件 + 日志
# ./downloads 下载的媒体文件
# ============================================================
services:
# ---------- 后端服务:FastAPI + yt-dlp + ffmpeg ----------
backend:
image: liwangsheng/pmd-backend:latest
container_name: pmd-backend
# 如需本地构建(改过源码后测试),取消下一行注释
# build: ./backend
environment:
# 默认时区:中国上海
TZ: Asia/Shanghai
# !!!JWT 签名密钥:部署前必须改为强随机值!!!
# 生成:python -c "import secrets; print(secrets.token_urlsafe(48))"
JWT_SECRET: CHANGE_ME_TO_A_STRONG_RANDOM_SECRET
# 临时文件、日志等基础目录
DATA_PATH: /data
# 数据库目录(与下载文件分开存放)
DB_PATH: /data/db
# 下载完成的媒体文件根目录
DOWNLOADS_PATH: /downloads
# 后端监听端口(容器内,无需修改)
PORT: 8000
# 同时下载/上传的并发数
MAX_PARALLEL: 3
# 定时清理:临时文件保留时长(小时)、日志保留天数、日志轮转大小(MB)、清理间隔(分钟)
TEMP_CLEANUP_HOURS: 24
LOG_RETENTION_DAYS: 14
LOG_MAX_SIZE_MB: 10
CLEANUP_INTERVAL_MINUTES: 60
volumes:
# 数据库 + 临时文件 + 日志
- ./data:/data
# 下载的媒体文件(可单独挂载大容量目录)
- ./downloads:/downloads
# 后端端口默认不对外暴露(仅前端容器内部访问,更安全)
# 如需调试后端 API(如 /docs),取消下面注释:
# ports:
# - "8000:8000"
restart: unless-stopped
# ---------- 前端服务:Nginx 托管页面并反代 /api、/ws ----------
frontend:
image: liwangsheng/pmd-frontend:latest
container_name: pmd-frontend
# 如需本地构建(改过前端代码后测试),取消下一行注释
# build: ./frontend
environment:
# 默认时区:中国上海
TZ: Asia/Shanghai
depends_on:
- backend
ports:
# 对外访问入口:http://服务器IP:8080
- "8080:80"
restart: unless-stopped
为了方便维护,PMD 提供了几个常用的管理命令。
# 重置管理员密码
docker exec -it <后端容器名> python manage.py reset-admin-password
# 重置指定用户密码
docker exec -it <后端容器名> python manage.py reset-user-password <用户名>
# 查看当前系统配置
docker exec -it <后端容器名> python manage.py show-config