Skip to Content
Documentation系统架构

系统架构

MemShare 采用移动端 + API 中心 + 专用语音服务 + 异步 Worker 的分层架构。用户请求走同步 HTTP;耗时转写走异步队列(基于数据库状态轮询)。

架构总览

分层说明

客户端(native)

  • 面向 iOS / Android,使用 Expo Router 组织页面
  • 通过 better-auth 与 API 完成登录与会话管理
  • 本地处理:视频选片、封面生成、音频提取@memshare/expo-media-processor-module)、文件指纹计算
  • 播放层支持本地文件与 YouTube(WebView),字幕与播放进度同步

API 网关(api)

  • 统一入口,默认监听 :8080
  • 路由前缀 /api,OpenAPI 文档位于 /api/doc,Swagger UI 位于 /api/ui
  • 职责:
    • 用户鉴权(/api/auth/*
    • 媒体库 CRUD(/api/media
    • 字幕分页读取(/api/media/{id}/subtitles/{language}
    • Worker 专用接口(/api/worker/*X-Worker-Key 鉴权)
  • 持久化:PostgreSQL(Prisma ORM)
  • 对象存储:Cloudflare R2 或兼容 S3 的 MinIO

语音服务(speech)

  • 独立 Python 服务,默认监听 :8000
  • 无状态:接收音频文件,通过 SSE 流式返回转写与分析结果
  • 不直接访问数据库;由 Worker 消费 SSE 并回写 API

任务处理器(worker)

  • 长轮询 API 的 /api/worker/jobs/next
  • 两类任务:youtube_download(下载音频)与 transcribe(转写)
  • 转写时调用 Speech SSE,每收到一段即 POST 回 API 增量写入
  • 与 API、Speech 解耦,可水平扩展多个 Worker 实例(任务认领通过数据库乐观锁)

数据流原则

路径模式说明
用户 → API同步 REST登录、列表、详情、上传预签名
用户 → R2直传音频不经 API 中转,降低带宽压力
Worker → SpeechSSE 长连接转写可能持续数分钟,流式消费
Worker → APIREST 回调状态更新、字幕片段追加
App → API轮询处理中的媒体每 5s 拉取字幕

去重与共享

系统维护两层媒体概念:

  • Media:全局媒体库,按 fileHash(本地文件)或 youtubeVideoId(YouTube)去重
  • UserMedia:用户个人收藏,可覆盖标题、打标签

字幕(Subtitle)按 fileHash 关联。当新用户添加已有指纹的媒体时,attachSubtitlesByFileHash 会自动挂载历史字幕并将 subtitleStatus 置为 success,跳过 Worker 队列。

安全边界

  • 用户接口:Session / Cookie,经 requireAuth 中间件保护
  • Worker 接口:共享密钥 WORKER_API_KEY,请求头 X-Worker-Key
  • Speech 服务:内网部署,不对外暴露;仅 Worker 调用
  • R2 访问:预签名 URL,限时读写