Skip to content

feat: add local video support using current logic#2982

Open
diary112233 wants to merge 5 commits into
open-ani:mainfrom
diary112233:pr提交

Hidden character warning

The head ref may contain hidden characters: "pr\u63d0\u4ea4"
Open

feat: add local video support using current logic#2982
diary112233 wants to merge 5 commits into
open-ani:mainfrom
diary112233:pr提交

Conversation

@diary112233

Copy link
Copy Markdown

概述

这个 PR 主要做了两件事:

  1. 增加“使用本地视频”的能力,允许将用户手动选择的本地视频文件直接绑定到剧集,复用现有缓存体系进行管理和播放。
  2. 为桌面端播放器切换增加冷却时间,规避 VLC 在快速切换视频时偶现的卡死或崩溃问题。

背景

现有缓存链路主要围绕远端媒体展开,用户即使已经有本地视频文件,也无法直接接入现有的剧集缓存、播放和管理流程。

另外,桌面端在切换视频时,如果在 stopPlayer 之后立刻加载新媒体,VLC 有概率出现卡死或崩溃,影响连续播放和切换体验。

技术路线

本次实现没有单独新开一套“本地视频播放”逻辑,而是选择复用现有的媒体缓存模型和播放链路,把“外部本地文件”抽象成一种特殊的本地缓存媒体。

这样做的原因是:

  • 可以复用已有的剧集-媒体绑定关系
  • 可以直接接入现有缓存管理页、状态流转和播放入口
  • 可以避免为本地文件额外维护一套平行的数据结构
  • 后续如果需要扩展本地文件相关能力,也可以继续沿用现有缓存体系

播放器切换问题则采用配置化冷却时间的方式处理,在播放器真正加载下一条媒体前增加一个平台可配置的等待时间,尽量将兼容性处理收敛在播放会话内部,而不是散落到上层业务逻辑里。

实现方式

1. 本地视频能力

1.1 将外部文件包装为可播放媒体

新增 ExternalLocalFileMediaFactory,将用户选择的本地文件构造成 Media

  • download 使用 ResourceLocation.LocalFile
  • mediaSourceId 复用 local-file-system
  • kind 标记为 LocalCache
  • 同时生成对应的 MediaCacheMetadata

这样本地文件可以直接进入现有的媒体解析、缓存和播放流程。

1.2 新增外部本地文件缓存存储

新增 ExternalLocalFileMediaCacheStorage,为“外部本地文件绑定”提供单独的存储实现,并注册新的 MediaCacheEngineKey.ExternalLocalFile

核心行为如下:

  • 不拷贝、不移动原始文件,只保存“剧集 <-> 本地文件路径”的绑定关系
  • 绑定同一剧集的新文件时,替换旧绑定
  • 删除缓存时只删除绑定关系,不删除用户原文件
  • 应用恢复时校验本地文件是否仍存在
  • 如果文件已不存在,则自动清理失效元数据

这部分实现尽量贴近原有缓存逻辑,避免引入新的生命周期模型。

1.3 让缓存请求支持“直接使用已选媒体”

EpisodeCacheRequester 中新增 requestSelectedMedia,用于跳过“拉取远端资源列表 -> 选择资源”这一步,直接基于用户已经选定的 Media 进入 Done 阶段。

这使得本地文件场景可以复用现有缓存完成逻辑,而不需要伪造远端请求流程。

1.4 桌面端增加绑定入口

在缓存管理界面中,为桌面端剧集项增加“绑定本地视频”按钮:

  • 使用文件选择器选择本地视频文件
  • 校验文件存在且为普通文件
  • 根据当前条目的 subjectInfoepisodeInfo 创建本地媒体
  • 通过 requestSelectedMedia 直接生成缓存请求
  • 在缓存列表和筛选项中展示“本地文件”类型及对应图标

2. VLC 切换冷却时间

新增 PlayerMediaSwitchCooldownConfig,并在 PlayerSession 中接入:

  • 在停止当前播放器后、加载下一条媒体前,根据配置执行 delay
  • 将该兼容性策略封装在播放会话层,对上层业务透明

平台配置如下:

  • Desktop: 注入 400ms 冷却时间
  • Android: 注入默认值 0ms
  • iOS: 注入默认值 0ms

也就是说,只有桌面端启用了这次兼容性等待,移动端行为保持不变。

平台适用范围

本地视频绑定功能

当前用户可见入口只在 Desktop 开放。

适用平台:

  • Desktop(Windows / macOS / Linux 桌面端)

说明:

  • UI 上通过桌面端文件选择器选择视频文件
  • 缓存管理页新增“绑定本地视频”按钮也只在桌面端展示

对于 Android / iOS:

  • 本次没有开放对应的用户入口
  • 相关公共层能力已接入共享缓存体系,但当前不是面向移动端交付的功能

VLC 切换冷却时间

当前实际生效平台为 Desktop

说明:

  • 桌面端注入 400ms,用于规避 VLC 快速切换媒体时的卡死/崩溃问题
  • Android / iOS 注入默认 0ms,不改变原有行为
屏幕截图 2026-04-18 181224 屏幕截图 2026-04-18 181303 image

@StageGuard

Copy link
Copy Markdown
Member

Is the PR ready to review?

@diary112233

Copy link
Copy Markdown
Author

从功能实现角度来看,这个 PR 已经可以进行 review 了。

本地视频绑定功能已经完成,并且在我本地测试表现正常,编译和测试都可以通过。

不过在合并了最新的上游分支(系统托盘最小化功能的那个分支)之后,CI 开始无法通过。我在本地无法复现这个问题,因此更倾向于是环境相关的问题,而不是这个 PR 本身引入的,目前还没有定位到具体原因。

另外,在测试过程中我发现 VLC 后端在切换媒体源时存在一个潜在问题:卡死更可能发生在 resume -> media().play(...) 这个阶段,而不是上层的 setMediaData()。目前加 400ms 延迟确实可以缓解,但并没有从根本上解决问题。而且这个现象在发行版程序中使用下载好的视频切换剧集的时候也会出现,因此看起来并不是由这个 PR 引入的。

总结一下:

功能层面:已完成,可以 review
CI:在合并上游后失败,可能与环境有关,需要进一步排查
VLC 卡死问题:属于已有问题,并非这个 PR 引入

…opTest` in CI.

Add an explicit `app-data` dependency to `ui-cache` because it directly uses types from that module.
将 `TimeBasedDanmakuSession` companion logger 改为 lazy 初始化,避免纯逻辑方法调用时提前触发 logging 初始化
@diary112233

diary112233 commented May 3, 2026

Copy link
Copy Markdown
Author

我发现这个 CI 失败看起来是偶发的,或者和环境/缓存有关。
同样的代码在旧分支上失败,但我从这个旧分支拉出一个新分支,不做任何代码修改后重新跑 CI 就通过了。
所以我认为这个失败不是我的本地视频绑定功能引入的。

https://github.com/diary112233/animeko/actions/runs/25242351243 这个cl测试通过了,https://github.com/diary112233/animeko/actions/runs/25243090620 这个就没通过,提交哈希是9ceb96ba16a8fcd4825973c6647ab3759bb615e6

https://github.com/diary112233/animeko/actions/runs/25271919092 这个通过了,
https://github.com/diary112233/animeko/actions/runs/25272660922 这个没有通过,提交哈希是52fd6060390964500137da1b4b58060b1f61ed89

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants