MoeVideo是一个开源弹幕视频播放站点,支持通过BT / yt-dlp + curl-cffi / rebrowser-playwright + chromium导入视频。最近一直在vibe coding这个程序,感觉功能都完善的差不多了,能够满足自己的需求了,索性开源出来分享给大伙一起用,反馈bug或者提需求都可以开issue,如果喜欢的话可以点个小星星支持一下。
技术栈:
- 前端:Next.js App Router + Tailwind CSS
- 后端:Go + Fiber
当前已实现的功能:
- 视频上传
- BT导入视频:支持自动解析种子文件内的媒体文件。
- URL导入视频:yt-dlp + curl-cffi
- 自定义yt-dlp cookies(cookies采用加密存储并支持配置多个站点)
- 回落支持:yt-dlp不支持的站点自动回落到rebrowser-playwright + chromium
- 强制回落:通过环境变量配置指定域名直接走rebrowser-playwright + chromium
- HLS多码率转码:360p 480p 720p 1080p
- 用户中心:可设置头像,签名,个人信息隐私策略等
- 多用户支持:可选开启或关闭注册
- 互动系统:点赞 评论 收藏 粉丝关注
- 视频弹幕支持 (WebSocket)
- 站内搜索:搜索您想看的视频
- 标签页面:支持添加视频标签,按标签排列视频,单独的标签页面
- 排行榜系统:独立的热度算法支持,智能排序热度最高的视频
- ArtPlayer 雪碧图 + VTT
- 跨设备同步播放记录,记忆上次播放位置。
- 完善的管理面板:站点设置 用户管理 视频管理 转码任务管理 分类设置 yt-dlp设置 等
- 本地存储 / S3存储支持
文档还没有全部写好,还有一些细节也没有到位,这篇文章先记录一下Docker的部署步骤。
安装Docker / NGINX / Certbot:
apt -y update
apt -y install curl git nginx python3-certbot-nginx
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
克隆项目存储库并准备数据目录:
git clone https://github.com/xiya233/MoeVideo.git
cd MoeVideo
mkdir -p data/db data/storage data/temp data/redis
编辑.env.docker:
nano .env.docker
假设您使用的域名是:app.example.com (前端)/ api.example.com (后端)至少需要修改下面的内容:
# 前端连接后端的API地址
NEXT_PUBLIC_API_BASE_URL=https://api.example.com/api/v1
# 与NEXT_PUBLIC_API_BASE_URL保持一致
API_BASE_URL=https://api.example.com/api/v1
# 建议至少 32 位高强度随机字符串
JWT_SECRET=replace-this-with-a-very-strong-secret
# 后端API地址
PUBLIC_BASE_URL=https://api.example.com
# HTTPS必须启用
AUTH_COOKIE_SECURE=true
# 留空
AUTH_COOKIE_DOMAIN=
# SameSite建议lax, 兼顾安全和常规站内跳转
AUTH_COOKIE_SAMESITE=lax
AUTH_COOKIE_PATH=/
# 设置前端域名
CORS_ALLOWED_ORIGINS=https://app.example.com
# 改大一点防止因下载速度慢导致超时重试
IMPORT_URL_TIMEOUT_SEC=18000
# 改大一点防止因网速慢导致页面解析超时
IMPORT_PAGE_RESOLVER_TIMEOUT_SEC=90
# 强制走 fallback 的域名列表, 逗号分隔,如不需要可留空
IMPORT_FORCE_FALLBACK_DOMAINS=missav.ai,24av.net
使用GHCR预构建镜像启动:
docker compose --env-file .env.docker -f docker-compose.yml -f docker-compose.ghcr.yml pull
docker compose --env-file .env.docker -f docker-compose.yml -f docker-compose.ghcr.yml up -d --no-build
创建管理员账号:
docker compose --env-file .env.docker run --rm backend \
/app/moevideo-admin bootstrap \
--email admin@example.com \
--username admin \
--password 'ChangeMe-StrongPassw0rd!' \
--db /data/db/moevideo.db
新建NGINX站点配置文件:
nano /etc/nginx/sites-available/moevideo.conf
写入如下内容:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream moevideo_frontend {
server 127.0.0.1:3000;
}
upstream moevideo_backend {
server 127.0.0.1:8080;
}
server {
listen 80;
listen [::]:80;
server_name app.example.com;
client_max_body_size 2048m;
location / {
proxy_pass http://moevideo_frontend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server {
listen 80;
listen [::]:80;
server_name api.example.com;
client_max_body_size 2048m;
location /api/ {
proxy_pass http://moevideo_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /media/ {
proxy_pass http://moevideo_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /healthz {
proxy_pass http://moevideo_backend/healthz;
}
}
启用站点:
ln -s /etc/nginx/sites-available/moevideo.conf /etc/nginx/sites-enabled/moevideo.conf
申请证书:
certbot --nginx -d app.example.com -d api.example.com
登录后访问/admin即可打开管理员面板,建议修改一下yt-dlp的配置,提升下载速度:
--concurrent-fragments 8 --fragment-retries 10 --retries 10 --socket-timeout 30 --force-ipv4 --impersonate Chrome-136
如图所示:
项目截图:
目前s3存储还没有测试,不知道有没有什么bug,建议直接用本地存储。
然后是回落抓取网页媒体链接的功能,逻辑是这样的:yt-dlp支持的站点直接走yt-dlp下载,yt-dlp如提示不支持的url(unsupported url),则走rebrowser-playwright + chromium探测页面的媒体链接,用户手动选择抓取出来的链接再喂给yt-dlp下载。但是目前只对yt-dlp不支持的url(unsupported url)这一退出行为执行回落操作,其他报错退出不做回落操作,比如被cf拦截了,或者页面报403,等等这些都是不会自动回落的。
所以这里有个问题就是要让yt-dlp识别目标网站支不支持得先能够让它成功访问到目标页面,如果本身就被cf拦截或者其他莫名其妙的原因导致无法访问目标页面,yt-dlp退出的行为可能有很多种,只要不是不支持的url(unsupported url)退出的就不会回落,所以我增加了一个功能就是强制(指定)回落:用户可以设置指定域名直接走rebrowser-playwright + chromium。这个功能我测试了下载missav,24av等x站都是没问题的,或者说我就是专门为了下这几个站的视频特地做的= =
荒岛


























