LinPlayer 架构说明(Architecture)
面向二次开发与排障的开发者文档。本文以当前
main分支代码结构为准。
1. 文档目标
- 快速理解项目的“分层边界”和“关键调用链”。
- 明确每个目录/模块该放什么,不该放什么。
- 为后续新增服务器类型、播放能力、TV 能力提供落点参考。
2. 架构总览
LinPlayer 采用“页面层 + 状态层 + 适配层 + API 层 + 播放层 + 平台服务层”的结构:
text
Flutter 页面(lib/*.dart)
-> AppState (packages/lin_player_state)
-> Server Adapter (packages/lin_player_server_adapters)
-> API Client (packages/lin_player_server_api)
-> Emby/Jellyfin/WebDAV/Plex 等服务
播放页(lib/player_screen*.dart, lib/play_network_page*.dart)
-> lin_player_player (PlayerService / Danmaku / 播放控制)
-> media_kit(mpv) 或 video_player_android(Exo)3. 顶层目录职责
.github/- CI/CD、Nightly/Latest 发布流程、安装包脚本。
assets/- 图标、Anime4K shader、TV 代理资源、TV 远程网页静态资源。
lib/- Flutter 业务页面与应用编排(入口、路由、页面、平台服务 glue)。
packages/- 模块化后的核心包(state/ui/player/server/api/core/prefs)与 patched 依赖。
docs/- 用户与开发文档。
tool/- 构建辅助脚本(如 TV 代理资源拉取)。
workers/- 辅助 Worker(当前有
workers/dandanplay-proxy)。
- 辅助 Worker(当前有
4. 分层说明
4.1 页面与编排层(lib/)
入口:lib/main.dart
职责:
- 初始化媒体后端(
MediaKit.ensureInitialized())。 - 初始化设备信息与 User-Agent(
ServerApiBootstrap.configure(...))。 - 加载全局状态(
AppState.loadFromStorage())。 - 根据设备类型与当前服务类型,选择 Home 壳:
- TV:
lib/tv/tv_shell.dart - Desktop:
lib/desktop_ui/desktop_shell.dart - Mobile/Tablet:
lib/home_page.dart或lib/webdav_home_page.dart
- TV:
关键页面:
- 服务管理:
lib/server_page.dart - 首页与库:
lib/home_page.dart、lib/library_page.dart、lib/library_items_page.dart - 详情页:
lib/show_detail_page.dart - 播放页:
- MPV:
lib/player_screen.dart、lib/play_network_page.dart - Exo:
lib/player_screen_exo.dart、lib/play_network_page_exo.dart
- MPV:
- WebDAV:首页壳与浏览器:
lib/webdav_home_page.dart、lib/webdav_browser_page.dart - 聚合检索:
lib/aggregate_service_page.dart
4.2 状态层(packages/lin_player_state)
核心:packages/lin_player_state/lib/app_state.dart
职责:
- 全局状态中心(
ChangeNotifier)。 - 持久化(SharedPreferences)与缓存(库缓存、首页缓存、播放偏好、弹幕偏好、TV 偏好等)。
- 服务管理流程:
addServer(...)(Emby/Jellyfin)addWebDavServer(...)addPlexServer(...)enterServer(...)/leaveServer()
- 数据加载流程:
loadItems(...)、loadHome(...)、loadMediaStats(...)
相关模型:
packages/lin_player_state/lib/server_profile.dartpackages/lin_player_state/lib/local_playback_handoff.dartpackages/lin_player_state/lib/route_entries.dart
4.3 适配层(packages/lin_player_server_adapters)
核心接口:packages/lin_player_server_adapters/lib/server_adapters/server_adapter.dart
职责:
- 定义统一服务能力接口
MediaServerAdapter,对页面层屏蔽服务端差异。 - 在工厂
server_adapter_factory.dart中按产品线选择具体适配器实现。
现有实现:
lin/lin_emby_adapter.dart(Emby/Jellyfin 主实现)emos/emos_adapter.dartuhd/uhd_adapter.dart
页面侧统一接入点:
lib/server_adapters/server_access.dart(resolveServerAccess(...))
4.4 API 层(packages/lin_player_server_api)
主要文件:
services/emby_api.dartservices/plex_api.dartservices/webdav_api.dartservices/webdav_proxy.dartservices/server_share_text_parser.dartnetwork/lin_http_client.dart
职责:
- 原始 HTTP 能力与协议细节(header、鉴权、重试、fallback)。
- 业务接口封装:鉴权、列表、详情、播放信息、播放上报、章节、相似推荐等。
说明:
- Emby/Jellyfin 共用
EmbyApi(通过MediaServerType区分 header 与 prefix 策略)。 - WebDAV 负责目录列举与鉴权处理(含 Digest/Basic)。
- Plex 负责 PIN 登录和服务器资源发现(当前项目中主要是“登录与保存服务器信息”)。
4.5 播放层(packages/lin_player_player)
主要文件:
player_service.dart:MPV 播放能力封装。src/player/playback_controls.dart:播放控制 UI 复用组件。src/player/danmaku_stage.dart+danmaku*.dart:弹幕管线。src/player/anime4k.dart:Anime4K shader 管线。dandanplay_api.dart:在线弹幕匹配与下载。
说明:
- MPV 路径使用
media_kit。 - Exo 路径使用
video_player_android(并通过 patched 包增强轨道能力)。
4.6 UI 基建层(packages/lin_player_ui)
主要文件:
src/ui/app_theme.dart、theme_sheet.dart、ui_scale.dartsrc/ui/glass_background.dart、frosted_card.dartsrc/ui/app_components.dart、rating_badge.dart等
职责:
- 统一主题、风格模板、缩放与基础组件。
- 保证页面层不重复实现公共视觉逻辑。
4.7 配置与偏好层(packages/lin_player_prefs)
主要文件:
preferences.dartinteraction_preferences.dartdanmaku_preferences.dartanime4k_preferences.dart
职责:
- 偏好枚举、配置模型定义(供
AppState与 UI 使用)。
4.8 核心配置层(packages/lin_player_core)
主要文件:
app_config/app_config.dartapp_config/app_feature_flags.dartapp_config/app_product.dartstate/media_server_type.dart
职责:
- 产品线差异(
lin/emos/uhd) - 功能开关(允许的 server type)
- 基础枚举与全局配置上下文
5. patched 依赖说明
packages/media_kit_patched- 为 MPV 路径提供更细粒度参数传递能力。
packages/video_player_android_patched- 增强 Exo 轨道相关能力(音轨/字幕轨选择等)。
pubspec.yaml 中通过 dependency_overrides 强制覆盖到项目内 patched 包。
6. 关键业务链路
6.1 启动链路
main.dart初始化媒体内核、设备信息、AppConfig。AppState.loadFromStorage()恢复服务、主题、偏好、缓存。- 根据设备类型进入
TvShell/DesktopShell/ 普通 Home。 - 启动可选服务:TV Remote、Built-in Proxy、自动更新检查。
6.2 添加服务器链路
页面:lib/server_page.dart
- Emby/Jellyfin:
AppState.addServer(...)- 内部通过 adapter/API 完成鉴权与基础信息拉取。
- WebDAV:
AppState.addWebDavServer(...) - Plex:
- 账号授权流(PIN)+ 资源选择,或手动填 token。
- 最终进入
AppState.addPlexServer(...)。
6.3 首页/列表加载链路
- 页面触发
AppState.loadHome()/loadItems(...)。 AppState使用当前 active server 构建访问上下文。- 调 adapter 拉取数据并写入本地缓存。
notifyListeners()驱动 UI 更新。
6.4 播放链路(网络媒体)
入口:show_detail_page.dart / 列表页 -> play_network_page*.dart
- 通过
resolveServerAccess(...)获取adapter + auth。 fetchPlaybackInfo(...)获取PlaySessionId/MediaSources。- 组装流 URL 与 header,交给 MPV 或 Exo 播放。
- 播放期间上报:
reportPlaybackStartreportPlaybackProgressreportPlaybackStoppedupdatePlaybackPosition
6.5 播放链路(本地文件/WebDAV)
- 本地:
player_screen*.dart直接从本地路径建立播放列表。 - WebDAV:
webdav_browser_page.dart- 先通过
webdav_proxy.dart注册本地代理 URL。 - 再把 URL 作为本地播放队列交给播放器。
- 先通过
6.6 弹幕链路
- 播放页叠加
DanmakuStage。 - 数据来源:本地 XML 或在线(
dandanplay_api.dart)。 - 渲染参数来自
AppState(透明度、字号、速度、去重、防遮挡等)。
6.7 TV 专项链路
- TV 遥控网页:
tv_remote_service.dart- 内置 HTTP + WebSocket 服务,提供移动端控制入口。
- TV 内置代理:
built_in_proxy_service.dart- 管理 mihomo 进程、配置生成、代理规则及 UI 面板资源。
7. 平台与壳层
7.1 Desktop 壳层
目录:lib/desktop_ui/
职责:
- 提供桌面端独立壳与页面组织。
- 与移动端共享状态层、适配层、API 层。
- 详细设计与组件拆分:
docs/dev/DESKTOP_UI_ARCHITECTURE.md
7.2 TV 壳层
目录:lib/tv/
职责:
- TV 首页、背景模式、首启向导、遥控操作体验。
8. 数据与持久化策略
持久化入口:AppState(SharedPreferences)
典型内容:
- 当前服务与服务器列表。
- 主题、缩放、交互手势、播放器偏好。
- 弹幕偏好、TV 偏好、自动更新设置。
- 轻量缓存:库列表、首页区块、部分统计信息。
9. 扩展指南
9.1 新增一个服务端类型
建议步骤:
- 在
lin_player_core扩展MediaServerType与 FeatureFlag。 - 在
lin_player_server_api新增 API 客户端。 - 在
lin_player_server_adapters实现新的 Adapter。 - 在
ServerAdapterFactory与server_page.dart接入。 - 在
AppState补充服务保存/切换逻辑。
9.2 新增播放能力
建议步骤:
- 优先落在
lin_player_player(而不是页面直接写)。 - 页面层只做参数编排与状态展示。
- 涉及平台特性时,通过 patched 包或平台通道落地。
9.3 新增 UI 模板或全局视觉能力
建议步骤:
- 在
lin_player_ui扩展主题/样式模型。 - 由
AppState持久化模板/参数。 - 页面层仅消费,不重复定义 token。
10. 调试与维护建议
- 静态检查:
flutter analyze - 测试:
flutter test - 平台构建前先确认:
flutter doctor -v - 对外接口异常优先查:
- 当前 active server 信息
- Adapter 选型是否正确
- API prefix / token / userId 是否一致
- 播放异常优先查:
fetchPlaybackInfo返回的MediaSources- 选中的音轨/字幕索引
- MPV/Exo 内核是否匹配当前片源
11. 相关文档
docs/dev/README.mddocs/dev/ANDROID_SIGNING.mddocs/dev/TV_PROXY_ROADMAP.mddocs/SERVER_IMPORT.md
如果你准备继续模块化重构,建议下一步先统一:
- 页面层对
AppState的直接读写边界 - 播放页的共享 ViewModel/Controller 抽象
- 详情页(剧/集)的公共组件拆分