Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Toxing 视频网站

类B站风格的视频网站,支持多分辨率视频播放、后台管理、自动转码。

功能特性

前台

  • 视频卡片网格列表展示
  • 按分类筛选、关键词搜索
  • video.js 播放器,支持 360p / 480p / 720p / 1080p 清晰度切换
  • HTTP Range 请求,支持拖动进度条和断点续传
  • 响应式布局,适配手机和桌面

后台

  • 管理员登录(JWT 鉴权)
  • 视频上传(支持拖拽,最大 10GB)
  • 视频编辑 / 删除
  • 分类管理(增删)
  • 转码状态实时显示(5 秒轮询)
  • 仪表盘统计概览

转码

  • FFmpeg 自动队列转码
  • H.264 + AAC 编码,兼容所有浏览器
  • 4 个分辨率并行转码:1080p (5Mbps) / 720p (2.5Mbps) / 480p (1Mbps) / 360p (500kbps)
  • 转码完成后自动删除原始文件释放磁盘空间
  • 转码失败的视频会保留记录,方便排查

技术栈

层级 技术
前端 Vue 3 + Vite + Vue Router + Pinia
播放器 video.js 8
后端 Node.js + Express 4
数据库 SQLite (better-sqlite3)
转码 FFmpeg
认证 JWT + bcrypt

项目结构

toxing/
├── .env                          # 环境变量配置
├── .gitignore
├── package.json                  # 根依赖(后端 + 开发工具)
│
├── server/                       # 后端
│   ├── index.js                  #   Express 入口,中间件挂载
│   ├── db/
│   │   └── init.js               #   数据库建表、种子数据
│   ├── middleware/
│   │   └── auth.js               #   JWT 鉴权中间件
│   ├── routes/
│   │   ├── auth.js               #   登录接口(含暴力破解防护)
│   │   ├── videos.js             #   视频公开 API + 管理员 API
│   │   └── categories.js         #   分类 API
│   ├── services/
│   │   ├── transcoder.js         #   FFmpeg 转码队列
│   │   └── password.js           #   密码哈希工具
│   ├── uploads/                  #   原始视频上传目录
│   └── videos/                   #   转码输出目录(按视频 ID 分文件夹)
│
└── client/                       # 前端
    ├── index.html
    ├── vite.config.js
    ├── package.json
    └── src/
        ├── main.js               #   应用入口
        ├── App.vue
        ├── style.css             #   全局样式(B站风格)
        ├── router/index.js       #   路由配置
        ├── stores/auth.js        #   Pinia 认证状态
        ├── api/index.js          #   Axios 封装(自动携带 Token)
        ├── components/
        │   ├── SiteHeader.vue    #   前台导航栏
        │   └── AdminHeader.vue   #   后台导航栏
        └── views/
            ├── Home.vue          #   首页 - 视频列表
            ├── VideoPlay.vue     #   视频播放页
            └── admin/
                ├── Login.vue     #   管理员登录
                ├── Layout.vue    #   后台布局(侧边栏)
                ├── Dashboard.vue #   仪表盘
                └── VideoManage.vue # 视频管理(上传/编辑/删除/分类)

数据库设计

videos 表 — 视频主表

字段 类型 说明
id INTEGER 主键自增
title TEXT 视频标题
description TEXT 视频描述
category_id INTEGER 分类 ID(外键)
original_path TEXT 原始视频路径(转码后删除)
cover_path TEXT 封面图路径(预留)
status TEXT pending / transcoding / completed / failed
created_at DATETIME 创建时间
duration INTEGER 视频时长(秒)

video_resolutions 表 — 分辨率表

字段 类型 说明
id INTEGER 主键自增
video_id INTEGER 关联视频 ID(外键,级联删除)
resolution TEXT 360p / 480p / 720p / 1080p
file_path TEXT 转码后文件绝对路径
file_size INTEGER 文件大小(字节)

categories 表 — 分类表

字段 类型 说明
id INTEGER 主键自增
name TEXT 分类名称(唯一)

admins 表 — 管理员表

字段 类型 说明
id INTEGER 主键自增
username TEXT 用户名(唯一)
password_hash TEXT bcrypt 加盐哈希

API 接口

公开接口

方法 路径 说明
GET /api/videos 视频列表(分页、分类筛选、搜索)
GET /api/videos/:id 视频详情(含分辨率列表)
GET /api/videos/:id/stream/:resolution 视频流(支持 Range)
GET /api/categories 所有分类
POST /api/auth/login 管理员登录

管理员接口(需 JWT)

方法 路径 说明
GET /api/admin/videos 视频管理列表(含所有状态)
POST /api/admin/videos 上传视频(multipart/form-data)
PUT /api/admin/videos/:id 编辑视频信息
DELETE /api/admin/videos/:id 删除视频及所有文件
GET /api/admin/videos/:id/status 转码状态查询
POST /api/admin/categories 创建分类
DELETE /api/admin/categories/:id 删除分类(有视频时拒绝)
GET /api/admin/auth/info 当前管理员信息

请求参数

GET /api/videos

参数 类型 说明
page int 页码,默认 1
limit int 每页条数,默认 12
category_id int 分类 ID
search string 搜索关键词(匹配标题)

POST /api/admin/videos (multipart/form-data)

字段 类型 说明
video file 视频文件(mp4/mkv/avi/mov/wmv/flv/webm)
title string 标题(可选,默认取文件名)
description string 描述
category_id int 分类 ID

安装与运行

前置条件

  • Node.js >= 18
  • FFmpeg(需加入系统 PATH)

1. 安装依赖

npm install
cd client && npm install && cd ..

2. 配置环境变量

编辑 .env 文件:

# 生产环境务必更换为一个随机长字符串
JWT_SECRET=your-random-secret-here
PORT=3000
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-strong-password

生成随机密钥:

node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"

3. 启动开发环境

# 同时启动后端和前端(后端 :3000,前端 :5173)
npm run dev

4. 生产环境部署

# 构建前端
npm run build

# 启动服务(前端静态文件由 Express 托管)
npm run server

访问 http://localhost:3000 即可。

转码流程

管理员上传视频
      │
      ▼
  文件存入 server/uploads/
  数据库记录 status = pending
      │
      ▼
  转码队列取出任务
  status = transcoding
      │
      ▼
  ffprobe 获取视频时长
      │
      ▼
  FFmpeg 并行转码 4 个分辨率
  ┌─────────┬─────────┬─────────┬─────────┐
  │ 1080p   │ 720p    │ 480p    │ 360p    │
  │ 5Mbps   │ 2.5Mbps │ 1Mbps   │ 500kbps │
  │ preset: │ medium  │         │         │
  └────┬────┴────┬────┴────┬────┴────┬────┘
       │         │         │         │
       ▼         ▼         ▼         ▼
  写入 video_resolutions 表
      │
      ▼
  status = completed
  删除原始文件

每个分辨率输出到 server/videos/{视频ID}/{分辨率}.mp4

安全措施

措施 说明
密码加密 bcrypt 自动生成唯一盐,10 轮哈希
暴力破解防护 同一账号 5 次失败后锁定 15 分钟
JWT 24 小时过期,请求头 Bearer Token
限流 全局 100 次/15 分钟,登录 10 次/15 分钟,上传 20 次/小时
HTTP 安全头 helmet 中间件(XSS、MIME、点击劫持等防护)
SQL 注入 参数化查询(better-sqlite3 prepared statements)
文件上传 白名单限制视频格式,10GB 大小上限

常见问题

Q: FFmpeg 转码很慢怎么办?

转码速度取决于 CPU 性能和视频分辨率。可以通过修改 server/services/transcoder.js 中的 preset 参数加速:

  • ultrafast — 最快,文件较大
  • fast — 较快,质量尚可
  • medium — 默认,平衡速度和质量
  • slow — 较慢,压缩率更高

Q: 上传大文件时浏览器超时?

前端已使用 Axios 的 onUploadProgress 显示进度。如 Nginx 代理需要调大超时:

client_max_body_size 10G;
proxy_read_timeout 3600s;

Q: 如何修改管理员密码?

直接修改 .env 中的 ADMIN_PASSWORD,然后删除 server/data.db 重新初始化。或编写脚本通过 bcrypt 生成新哈希更新数据库。

Q: 数据库文件在哪里?

SQLite 数据库文件为 server/data.db,首次启动自动创建。生产环境注意定期备份。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages