feat(jellyfin): 支持 Jellyfin Intro Skipper 及原生 MediaSegments 片头片尾跳过 - #3246
feat(jellyfin): 支持 Jellyfin Intro Skipper 及原生 MediaSegments 片头片尾跳过#3246XYenon wants to merge 7 commits into
Conversation
572e542 to
1510a90
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1510a901ed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
8a85e08 to
9503dae
Compare
|
请不要找 codex review, 他的 review 基本没有参考价值( |
|
merge main please |
为什么修改:Jellyfin/Emby 数据源此前未提取视频片头片尾 (OP/ED) 章节信息,导致在播放 Jellyfin 媒体源时无法自动或一键跳过 OP/ED。
做了什么:
1. 数据模型层:MediaExtraFiles 中新增 MediaChapter 及 chapters 列表定义。
2. Jellyfin 数据源:BaseJellyfinMediaSource 在请求 getItem/getEpisodes 时添加 fields=MediaStreams,Chapters 字段,并依次支持 Jellyfin 10.10+ 原生 /MediaSegments/{itemId} API、Intro Skipper 插件 /Episode/{itemId}/IntroTimestamps API 及 Item 嵌入章节,将其解析为 MediaChapter 列表。
3. 播放器及 UI:EpisodeViewModel 支持将选定媒体的 extraFiles.chapters 合并至 combinedChaptersFlow 中;PlayerSkipOpEdState 支持按章节名称 (OP/ED/Intro/Outro 等) 自动识别并跳过。
4. 单元测试:新增 PlayerSkipOpEdStateTest 及 BaseJellyfinMediaSourceTest DTO 反序列化单元测试。
测试情况:
- ./gradlew :datasource:jellyfin:desktopTest ✅ BUILD SUCCESSFUL (3/3 passed)
- ./gradlew :app:shared:desktopTest --tests "*PlayerSkipOpEdStateTest*" ✅ BUILD SUCCESSFUL
Co-authored-by: XYenon <register@xyenon.bid>
1. 延迟章节 API 请求 (P1):在 fetch() 匹配流程中先执行 matches(query) 过滤,仅对筛选留下的目标剧集延迟发起 fetchChaptersAndSegments() 网络请求,避免对全季剧集进行串行请求。 2. 正向精确匹配 OP/ED 标记 (P2):MediaSegments API 请求时添加 includeSegmentTypes=Intro,Outro 限制,且仅保留 Intro/Outro 类型;在 PlayerSkipOpEdState 中改用正向名称匹配 (isOpEdName),支持 op, ed, intro, outro, opening, ending, 片头, 片尾, 片头曲, 片尾曲 等正向标记。 Co-authored-by: XYenon <register@xyenon.bid>
Amp-Thread-ID: https://ampcode.com/threads/T-019fb10d-dd57-74de-9c02-2c8c943031c8 Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: XYenon <register@xyenon.bid>
Co-authored-by: XYenon <register@xyenon.bid>
Amp-Thread-ID: https://ampcode.com/threads/T-019ffe3c-414e-70b3-a05c-28d878217e1d Co-authored-by: XYenon <register@xyenon.bid>
Amp-Thread-ID: https://ampcode.com/threads/T-01a04103-79e2-727d-b1d8-f9a3fabacb1f Co-authored-by: XYenon <register@xyenon.bid>
Amp-Thread-ID: https://ampcode.com/threads/T-01a04103-79e2-727d-b1d8-f9a3fabacb1f Co-authored-by: XYenon <register@xyenon.bid>
d53682e to
0fd7525
Compare
背景与目的 (Why)
此前播放 Jellyfin / Emby 数据源视频时,由于未提取媒体服务器中的视频章节/时间戳信息,导致无法识别片头片尾 (OP/ED),也无法自动或手动跳过 OP/ED。
本 PR 增加了对 Jellyfin 10.10+ 原生 MediaSegments API 以及经典 Intro Skipper 插件的兼容支持,使得播放 Jellyfin 媒体源时能够自动读取并应用 OP/ED 标注。
变更内容 (What)
数据模型拓展 (
datasource/api)MediaExtraFiles中新增MediaChapter数据结构(包含name,durationMillis,offsetMillis)及chapters: List<MediaChapter>属性。Jellyfin 数据源解析 (
datasource/jellyfin)BaseJellyfinMediaSource:fields=MediaStreams,Chapters。fetchChaptersAndSegments:GET /MediaSegments/{itemId}):解析Intro/Outro/Recap/Preview/Commercial标记。GET /Episode/{itemId}/IntroTimestamps):解析IntroStart与IntroEnd时间戳。Item.Chapters。播放器与 ViewModel 集成与优先级 (
app/shared)EpisodeViewModel:提取选中媒体的extraFiles.chapters,合并至combinedChaptersFlow。调整优先级策略为:Jellyfin 章节数据c存在时优先采用(a + c),未提供时回退使用在线 AutoSkip 规则(a + b)。PlayerSkipOpEdState:增加按章节名称关键字(OP,ED,Intro,Outro,Opening,Ending)自动识别跳过逻辑。EpisodeVideo中跳过按钮与opEdSkipDuration的状态响应绑定。单元测试 (
commonTest)PlayerSkipOpEdStateTest验证按名称匹配 OP 章节。BaseJellyfinMediaSourceTest验证 Jellyfin DTO 的反序列化。测试验证情况 (Verification)
./gradlew :datasource:jellyfin:desktopTest单元测试通过 (3/3 passed)./gradlew :app:shared:desktopTest --tests "*PlayerSkipOpEdStateTest*"单元测试通过./gradlew :datasource:jellyfin:assemble :datasource:datasource-api:assemble编译构建成功