Skip to content

MediaDock:服務端項目介紹與 Flutter 開發說明

MediaDock:服务端项目介绍与 Flutter 开发说明 ​

1. 项目定位 ​

MediaDock 是面向个人 NAS 的本地媒体管理与播放服务。NAS 只运行服务端,Flutter 负责所有客户端功能。

本项目不依赖 Jellyfin、Komga、下载器或外部资源搜索服务。媒体内容全部来自 NAS 上用户自行配置并有权访问的本地目录。

2. 总体架构 ​

text
Flutter 客户端
    │ HTTP / HTTPS
    ▼
MediaDock 服务端
    ├── FastAPI API
    ├── PostgreSQL 元数据数据库
    ├── 本地媒体扫描器
    ├── 视频/音频流转发
    ├── 小说章节读取
    ├── 漫画图片读取
    └── 播放与阅读进度
        │
        ▼
NAS 本地媒体目录

Web 管理后台不再作为产品客户端;后续所有播放、阅读和管理页面统一使用 Flutter 实现。

3. 支持的媒体类型 ​

视频 ​

第一版支持:mp4、mkv、avi、mov、webm、m4v、ts。

服务端保存文件信息、时长、分辨率、编码、封面和播放进度。播放采用原文件转发,接口必须支持 HTTP Range,以便断点播放和拖动进度。第一版暂不做 FFmpeg 转码。

音频 ​

第一版支持:mp3、flac、m4a、aac、ogg、wav。

优先读取 ID3、FLAC 或 MP4 标签;缺少标签时从文件名和目录名推断歌曲、专辑和歌手信息。

小说 ​

第一版支持:txt、md、epub。

TXT/Markdown 按章节解析,EPUB 解析书名、作者、封面、目录和正文。正文按章节接口读取,不一次性返回整本书。

漫画 ​

第一版支持图片目录和 cbz,图片格式包括 jpg、jpeg、png、webp。

CBZ 按 ZIP 图片包处理,按页提供图片接口。暂不支持 CBR。

4. 本地目录规划 ​

建议统一挂载:

yaml
volumes:
  - ./data/media:/data/media:ro

容器内目录示例:

text
/data/media/
├── movies/
├── tv/
├── music/
├── novels/
├── manga/
└── .metadata/
    ├── posters/
    ├── backdrops/
    └── covers/

服务端只允许读取 /data/media 及其子目录,防止路径越界。

目录配置支持多个媒体库,每个目录包含名称、相对路径、媒体类型、启用状态、扫描状态、文件数量和最后扫描时间。

5. 扫描机制 ​

扫描器负责发现新文件、更新已变化文件,并将不存在的文件标记为不可用,不直接删除用户数据。

建议先支持手动扫描全部目录或单个目录,之后增加定时扫描和增量扫描。

扫描结果至少包含:文件名、相对路径、文件大小、MIME 类型、修改时间、媒体类型、封面路径、解析出的标题、季集数和元数据状态。

6. 服务端接口概览 ​

认证 ​

text
POST /api/auth/login
GET  /api/auth/getUserInfo
POST /api/auth/refreshToken

目录与扫描 ​

text
GET    /api/directories
POST   /api/directories
PATCH  /api/directories/{id}
DELETE /api/directories/{id}
POST   /api/directories/{id}/scan
POST   /api/directories/scan
GET    /api/scans/{id}

媒体 ​

text
GET /api/media
GET /api/media/{id}
GET /api/media/{id}/cover
GET /api/media/{id}/stream

媒体列表支持类型、目录、关键词和分页筛选。视频与音频统一使用 stream 接口,根据媒体类型返回正确的 MIME 类型,并支持 Range 请求。

小说阅读 ​

text
GET /api/books/{id}
GET /api/books/{id}/chapters
GET /api/books/{id}/chapters/{chapter_id}

漫画阅读 ​

text
GET /api/manga/{id}
GET /api/manga/{id}/chapters
GET /api/manga/{id}/chapters/{chapter_id}/pages
GET /api/manga/{id}/chapters/{chapter_id}/pages/{page}

进度与收藏 ​

text
GET    /api/progress
PUT    /api/media/{id}/progress
PUT    /api/books/{id}/progress
PUT    /api/manga/{id}/progress
GET    /api/favorites
POST   /api/favorites/{media_id}
DELETE /api/favorites/{media_id}

7. 视频刮削与 TMDB ​

视频刮削是可选功能,不影响本地扫描和播放。

TMDB 用于获取:

  • 中文及原标题
  • 简介
  • 年份
  • 类型
  • 演员和导演
  • 评分
  • 海报
  • 背景图
  • 电视剧季集信息

推荐流程:

text
扫描本地文件
→ 解析文件名和年份
→ TMDB 搜索候选
→ 用户在 Flutter 中确认
→ 保存 TMDB ID 和元数据
→ 下载并缓存海报、背景图

建议服务端配置:

env
TMDB_API_KEY=
TMDB_API_READ_TOKEN=
TMDB_LANGUAGE=zh-CN

没有 TMDB Key 时,仍然可以使用本地文件扫描、播放、搜索和进度功能;只是不能自动获取在线影视信息。海报优先使用本地伴随图片,其次才使用 TMDB 缓存图片。

使用 TMDB 数据和图片时,应遵守 TMDB 当前 API 使用条款并保留必要署名。TMDB 只提供元数据,不提供影视文件。

8. Flutter 客户端规划 ​

Flutter 是唯一客户端,使用统一 API 完成:

  • 登录与令牌管理
  • 首页和媒体库
  • 视频播放
  • 音乐播放、队列和后台播放
  • 小说目录与章节阅读
  • 漫画图片阅读
  • 播放和阅读进度同步
  • 收藏与历史
  • 管理员目录配置和扫描
  • TMDB 候选匹配与刮削管理

建议技术选型:

库用途
DioHTTP 请求
GetX状态管理和路由
just_audio音乐播放
media_kit视频播放,待最终验证
get_storage本地令牌和客户端偏好

Flutter 不直接访问 NAS 文件系统,只通过服务端 API 访问媒体;播放地址携带认证信息或使用短期播放令牌。

9. 安全要求 ​

  • 所有业务接口保留登录鉴权。
  • 文件路径必须限制在 /data/media 内。
  • 禁止通过参数读取任意宿主机文件。
  • 视频、音频、图片接口检查文件存在性和媒体归属。
  • 生产环境不展示数据库错误堆栈。
  • TMDB 凭据只保存在服务端,不放入 Flutter 客户端。
  • 媒体目录使用只读挂载,避免服务端误修改原始文件。
  • 播放和阅读进度写入 PostgreSQL,客户端只缓存临时状态。

10. 明确移除的功能 ​

本版本不包含:

  • Web 前端和浏览器后台
  • Jellyfin
  • Komga
  • 下载中心
  • 磁力链接和 BT 下载
  • qBittorrent、Transmission、aria2
  • 外部资源搜索
  • 在线字幕下载
  • 视频转码
  • CBR、PDF、DOCX 阅读

11. 开发顺序 ​

服务端阶段 ​

  1. 纯 API Docker 部署收口。
  2. 新增多媒体目录和扫描任务模型。
  3. 实现视频、音频、小说、漫画扫描。
  4. 实现媒体列表、详情、封面和本地搜索。
  5. 实现 Range 流转发。
  6. 实现小说章节和漫画页面接口。
  7. 实现播放/阅读进度与收藏。
  8. 实现可选 TMDB 刮削。
  9. 固化 Flutter API 契约。

Flutter 阶段 ​

  1. 登录。
  2. 首页和媒体库。
  3. 视频播放。
  4. 音乐播放。
  5. 小说阅读。
  6. 漫画阅读。
  7. 进度、收藏和历史。
  8. 目录管理、扫描管理和 TMDB 刮削管理。

12. 版本目标 ​

建议服务端版本:MediaDock v1.1.0。

目标是建立一个稳定的 NAS 本地媒体 API,让 Flutter 成为统一客户端。第一版优先保证本地媒体读取、播放、阅读和进度同步,复杂的转码、联网刮削扩展和多用户能力放到后续版本。