片头片尾跳过 - MiCat-S/Mi302 GitHub Wiki
Mi302 从大家看剧时的操作学出每一季的片头和片尾,让播放器显示“跳过片头”。学得不准或想先设好的季,也可以手动设置。这一页说明怎么学、怎样手动设置、播放器拿到什么、怎样用 SenPlayer 测试,以及数据存在哪里。
播放器播放时每隔几秒会上报一次播放位置。Mi302 从这些上报里看出“在开头跳过了一段”和“在片尾停下、切到下一集”,记成这一集的片头片尾。
- 不读取视频、不碰 115,也不需要 ffmpeg。
- 只学剧集的集,电影不学。
- 做法参考 Emby 神医助手(StrmAssistant)的“片头探测 - 播放行为”。
| 条件 | 规则 |
|---|---|
| 从哪里开始跳 | 片头区内:前 10 分钟;片长不到 40 分钟时是前 25%(24 分钟的动画是前 6 分钟);不知道片长时用前 10 分钟 |
| 一次往前跳多少 | 15 秒到 3 分钟;超过 3 分钟算跳过剧情,不算片头 |
| 不是倍速播放 | 位置前进的量要超过实际经过时间的 3 倍再加 15 秒 |
| 记下什么 | 跳之前最后上报的位置 → 跳之后第一次上报的位置 |
只看跳的那一下,之后怎么播不管。因为用的是上报的位置,会有几秒误差。
片尾需要知道片长。片长来自 nfo 的 <runtime>,或媒体信息(X-mediainfo.json、ffprobe 探测);不知道片长的集不学片尾。
| 条件 | 规则 |
|---|---|
| 片尾区 | 最后 5 分钟;片长不到 20 分钟时是最后 25% |
| 情况一:停下 | 在片尾区里停止播放(切到下一集、关掉),离结尾还有 20 秒以上 → 记下停下的位置 |
| 情况二:往前跳 | 从片尾区里往前跳(同样不能是倍速播放),跳到离结尾不到 20 秒的地方,或一次跳 60 秒以上 → 记下跳之前的位置 |
| 不算 | 离结尾不到 20 秒才停(等于播完了);还没到片尾区就开始跳 |
“一次跳 60 秒以上”是为了片尾曲后面还有下集预告的情况:跳过了片尾曲,但不一定跳到结尾。
- 每个用户对每一集的片头、片尾各只保留最后一次记录。
- 这一集自己有记录(不论是谁的):片头的开始、结束各取中位数;片尾开始取中位数。
- 这一集没有自己的记录:用同一季其他集的记录。片头同样取开始、结束的中位数;片尾取“距离结尾多久”的中位数,再套到这一集的片长上(这一集也要知道片长)。
- 自己的记录优先,不和整季混在一起算。
- 取中位数,所以偶尔有人乱跳不会覆盖掉。
- 这一季有手动设置时,设了的部分用手动的值,不看上面这些,见下面的“手动设置”。
三种格式都提供,播放器识别哪种就用哪种:
| 格式 | 在哪里 | 内容 |
|---|---|---|
| Emby 章节标记 | 项目详细数据的 Chapters(/Users/{userId}/Items/{id}、/Items/{id},或查询时带 Fields=Chapters) |
MarkerType 为 IntroStart、IntroEnd、CreditsStart 的章节,接在媒体信息的章节后面 |
| Jellyfin Intro Skipper 插件 |
GET /Episode/{id}/IntroTimestamps(也识别 /v1)、GET /Episode/{id}/Timestamps
|
以秒为单位的片头(和片尾);没有片头时 IntroTimestamps 返回 404 |
| Jellyfin 10.10 媒体片段 | GET /MediaSegments/{id} |
Intro、Outro 两种片段 |
这些是播放器请求数据时才计算的。刚学到的片头,播放器下次加载那一集就能拿到。
SenPlayer 读取的是 Emby 的章节标记(上表第一种)。测试步骤:
- 确认“整理”标签页“片头片尾”卡片“设定”里的“学片头片尾并给播放器”开着(默认开)。
- 在 SenPlayer 里打开一部有片头的剧的某一集,先正常播放几秒。
- 在片头区内(前 10 分钟,短的集是前 25%)一次往前跳过片头,长度在 15 秒到 3 分钟之间,例如拖动进度条。
- 跳过之后继续播放 10 到 20 秒,让 SenPlayer 上报新的位置。
- 回到管理页面看“片头片尾”卡片,这一季应该出现“片头 X → Y”。
- 在 SenPlayer 里打开同一季的另一集:播到片头时应该出现跳过片头的按钮。
没有学到时,到“日志”标签页搜索 學到片頭(日志内容是繁体中文,要输入繁体字才搜得到)。常见原因:一次跳超过 3 分钟、开始跳的位置已经过了片头区、跳之前或之后播放器还没上报位置。
片尾的测法:在最后 5 分钟内(离结尾 20 秒以上)停止播放或切到下一集,卡片上会出现“片尾在结尾前 …”。这一集要知道片长。
在“整理”标签页的“片头片尾”:
- 上方的数字是“学到的季”“有纪录的集”和“手动设定的季”。
- 搜索框:输入剧名找某一部剧的每一季,还没学到的季也能找到。原名、简繁体、拼音全拼、首字母都认,例如
qyn。 - 没有搜索时,列表列出有学到记录或手动设置的季,最近有动静的排在前面,一页 20 季。每一季显示剧名、第几季、“片头 X → Y”和“片尾在结尾前 …”,括号标出是“学到”还是“手动”;手动设置的季有“手动”标签。这些值用那一季的第 1 集来计算。
- 每一季的“编辑”:手动设置,见下一节。
- “清除全部”:确认后删除所有学到的记录,之后看剧时重新学。手动设置不会被清掉。
- “设定”里的“学片头片尾并给播放器”:
server.intro_skip,切换时立即保存。
学得不准、或者想在还没人看之前先设好时,搜索剧名,点那一季的“编辑”:
| 字段 | 选项 |
|---|---|
| 片头 | “自动(照播放行为学)”、“手动设定”(填开始和结束)、“这一季没有片头” |
| 片尾 | “自动(照播放行为学)”、“手动设定”(填从结尾前多久开始)、“这一季没有片尾” |
- 时间写成“分:秒”(例如
1:35)、“时:分:秒”或秒数。还没手动设置过时,输入框先填好学到的值,改一点就行。 - 片尾记的是“从结尾前多久开始”,所以同一季片长不同的集也对得上;要知道片长(nfo 的
<runtime>或媒体信息)才能提供给播放器。 - 勾选“这部剧的每一季都用这个设定”,同一部剧的每一季都保存成一样的设置。
- 有学到记录的季,还有“清除这一季学到的纪录”。
- 手动设置的部分直接给播放器,不再按播放行为;片头、片尾可以分开设置,另一个照样自动学。播放行为照样记录,把两个都改回“自动”就回到学到的值。
- 片头的结束和片尾的长度都不能超过 60 分钟,片头的开始要早于结束。
关掉“学片头片尾并给播放器”后:
- 不再学习新的记录。
- 不再提供给播放器:没有章节标记,Intro Skipper 的接口返回 404 或
Valid: false,媒体片段为空。 - 已经学到的记录和手动设置都保留在数据库里,重新打开后继续使用。要删除学到的记录请点“清除全部”。
- 手动设置也要开着这个开关才会提供给播放器。
- 学到的记录存在数据库
data/library.db的intro_obs表:每一集、每个用户、片头或片尾各一条,记录开始、结束位置和时间。 - 重启、更新都不会丢失,每天的自动备份也包含它,见 备份与还原。
- 只有“当前这一次播放”放在内存里:每个用户每一集最后上报的位置和时间,停止播放或 6 小时没有动静就丢弃。所以恰好跨过重启的那一跳学不到。
- 手动设置存在同一个数据库的
intro_manual表,每一季一条。 - 集从媒体库移除时(文件删除、改名),它的记录也跟着删除;季不见了,它的手动设置也跟着删除。