mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-11 22:06:17 -08:00
test(multiple-subtitles): [PKG-MULTI-SUB-09] isolate old-core source seeking from caption loss
This commit is contained in:
1 parent
efed847cdf
commit
31f9024bff
11 files changed
+8419
-18
No files matched your search
@@ -151,9 +151,12 @@ active cue; the matrix explicitly records lost simultaneous languages for1.1.0+
|
||||
and candidate, while1.0.0's index-merged cue displays both. This remains an open
|
||||
compatibility issue, not an approved limitation. CORE-SUBTITLE-OFFSET-01 corrects
|
||||
paused offsets in the candidate core; published Firefox hosts retain their exact
|
||||
historical defect observations. WebKit5.3.0/5.4.0 source-switch failures remain
|
||||
under task05 investigation. See its change and validation JSON for original failures
|
||||
and the independent core offset change for the corrected candidate evidence.
|
||||
historical defect observations. Task09 traced apparent WebKit5.3.0/5.4.0 caption
|
||||
loss to native seeks ending near zero: the cue itself remained intact. A no-plugin
|
||||
control reproduces the same old-host problem. Candidate core already waits for
|
||||
source seeking to complete. The ordering probe retains immediate old calls, while
|
||||
caption combinations wait for native seeking to settle before an independent seek.
|
||||
See task09's change/validation record and the core offset change for precise scope.
|
||||
The matrix is runnable with `yarn test:browser test/browser/multiple-subtitles-combinations.spec.js`;
|
||||
do not replace these failures with skips or count boundary observations as acceptance.
|
||||
See `../../refactor/baselines/multiple-subtitles-contract.md` for exact historical differences.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,81 @@
|
||||
# PKG-MULTI-SUB-09: distinguish source seeking from caption loss
|
||||
|
||||
Baseline: efed847cdfcbe5110e88b31527c46e622bcc83ee. This task closes the
|
||||
misattributed switching finding with independent native evidence and corrects
|
||||
integration sequencing. No production code, public type, dependency, version,
|
||||
lockfile or built artifact changes. PKG-MULTI-SUB-05 remains doing.
|
||||
|
||||
## Root cause evidence
|
||||
|
||||
The original WebKit failures retained a valid Translation cue at1..3 seconds,
|
||||
but the actual media clock was approximately0.002 seconds, with no active cues.
|
||||
The subtitle was correctly absent at that time; the intended seek to1.5 had not
|
||||
landed. Those reports predate currentTime instrumentation.
|
||||
|
||||
`multiple-subtitles-switch.spec.js` compares no plugin, current plugin, and actual
|
||||
npm plugin1.2.0 on cores5.3.0/5.4.0/candidate. Each case plays real local media,
|
||||
enters/exits native fullscreen, then performs three source changes. It captures
|
||||
native currentTime writes and media events, Promise settlement state, first seek
|
||||
completion and a second seek only if the first missed after native seeking ended.
|
||||
The property probe forwards to the original native getter/setter; it does not
|
||||
intercept or replace source operations. Outcomes and full traces are stored in
|
||||
[multiple-subtitles-switch-validation.json](../baselines/multiple-subtitles-switch-validation.json).
|
||||
|
||||
The first WebKit run confirms5 misses in18 old-core source changes, including
|
||||
both no-plugin old-core controls. All9 candidate-core changes land correctly.
|
||||
Old core promises sometimes resolve while video.seeking is still true, allowing
|
||||
the caller's new seek to overlap native restoration. After the restoration has
|
||||
ended, a fresh seek reaches the cue interval and both old/new plugins display it.
|
||||
Candidate source/switch.ts already waits for native seeking to finish and uses
|
||||
the position restoration logic covered by BASE-LIFE-44/CORE-19. No plugin-level
|
||||
seek retry, clock rewrite, blanket source reload or global core patch is needed.
|
||||
|
||||
The actual-main three-engine trace run has no missed first seeks in81 changes,
|
||||
but old WebKit hosts still settle during native seeking in6 of18 changes. This
|
||||
variation is retained; it is an intermittent old-host race, not proof that the
|
||||
initial misses were fixed by rerunning. All27 candidate-core changes in that run
|
||||
have seeking=false at settlement and honor the first caller seek.
|
||||
|
||||
## Test sequencing and validation
|
||||
|
||||
The caption combination test now waits for video.seeking=false after switchUrl
|
||||
before testing the separate user seek/caption behavior. The immediate old-call
|
||||
path is retained in the independent ordering test above, including its misses.
|
||||
This wait is a predicate on real native state, not a fixed delay or a silent
|
||||
retry of the acceptance assertion. It does not claim old switchUrl promises have
|
||||
been changed or all historical playback contracts are correct.
|
||||
|
||||
One later full run exposed an unrelated fixture sequence: it started exiting
|
||||
fullscreen when the document property changed but before the public enter event
|
||||
arrived, resulting in old-core notifications[false,false]. The normal enter/exit
|
||||
scenario now waits for the entering event before requesting exit; the original
|
||||
strict final[true,false] assertion remains. The failed trace is retained. No
|
||||
production fullscreen correction is claimed by this test-sequencing adjustment.
|
||||
|
||||
- Initial source WebKit ordering probe:9 cases pass their observation/candidate
|
||||
assertions, including the5 old first-seek misses noted above.
|
||||
- Actual core and plugin main artifacts, three engines:84 cases,83 passing
|
||||
assertions,1 fullscreen-sequencing failure. All27 ordering cases pass, and the
|
||||
run also includes explicitly labelled historical overlap/offset defects.
|
||||
- After the entering-event predicate correction, the affected timed-combination
|
||||
matrix is rerun unchanged otherwise:9/9 pass across three cores and engines.
|
||||
Do not describe this as a fresh84-case all-green run.
|
||||
- The two changed browser scripts pass lint;50 CI regression tests pass. Final
|
||||
plan/risk and risk-validator checks cover the completed task state.
|
||||
|
||||
MULTI-SUB-SWITCH-01 is resolved as a classified old-core seeking issue already
|
||||
handled in the candidate core, with the original calls and failures preserved.
|
||||
This does not resolve MULTI-SUB-MERGE-01 or complete device/distribution acceptance.
|
||||
Use the actual loaded core/plugin hashes when comparing future runs; the fixture
|
||||
supports both source builds and the existing explicit artifact map.
|
||||
|
||||
## Maintenance and rollback
|
||||
|
||||
Keep source readiness, actual seek landing and caption rendering distinct when
|
||||
debugging media failures. Run the ordering probe with/without the plugin before
|
||||
adding plugin retries for an underlying player clock problem. Keep candidate
|
||||
first-seek assertions strict; old observations must never count as correct calls.
|
||||
Both suites run under yarn test:browser. A normal core/plugin build was not needed
|
||||
because production bytes are unchanged; the checked artifacts came from the prior
|
||||
completed implementation commits. Revert this independent task09 commit to remove
|
||||
the new probe and integration predicates. Local commit only, no push/publication.
|
||||
+7
-5
@@ -2,9 +2,9 @@
|
||||
|
||||
> 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。
|
||||
|
||||
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 248 项,范围 22 个包及工作区/示例。
|
||||
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 249 项,范围 22 个包及工作区/示例。
|
||||
|
||||
状态:todo 55 / doing 17 / blocked 0 / done 176 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
状态:todo 55 / doing 17 / blocked 0 / done 177 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
|
||||
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
| 包 | 基线版本 | 任务 |
|
||||
| --- | --- | --- |
|
||||
| artplayer | 5.4.1 | CORE-01, CORE-02, CORE-03, CORE-04, CORE-05, CORE-06, CORE-07, CORE-08, CORE-09, CORE-10, CORE-11, CORE-12, CORE-13, CORE-14, CORE-15, CORE-16, CORE-17, CORE-18, CORE-19, CORE-20, CORE-21, CORE-23, CORE-22, CORE-24, SITE-BUILD-01, CORE-25, ENG-12, CORE-SUBTITLE-OFFSET-01 |
|
||||
| artplayer | 5.4.1 | CORE-01, CORE-02, CORE-03, CORE-04, CORE-05, CORE-06, CORE-07, CORE-08, CORE-09, CORE-10, CORE-11, CORE-12, CORE-13, CORE-14, CORE-15, CORE-16, CORE-17, CORE-18, CORE-19, CORE-20, CORE-21, CORE-23, CORE-22, CORE-24, SITE-BUILD-01, CORE-25, ENG-12, CORE-SUBTITLE-OFFSET-01, PKG-MULTI-SUB-09 |
|
||||
| artplayer-plugin-ads | 2.1.0 | PKG-ADS-01, PKG-ADS-02, PKG-ADS-03, PKG-ADS-04, PKG-ADS-05, PKG-ADS-06 |
|
||||
| artplayer-plugin-ambilight | 1.1.0 | PKG-AMBILIGHT-01, PKG-AMBILIGHT-02, PKG-AMBILIGHT-03, PKG-AMBILIGHT-04, PKG-AMBILIGHT-PROXY-01, PKG-AMBILIGHT-05, PKG-AMBILIGHT-06, PKG-FACTORY-01 |
|
||||
| artplayer-plugin-asr | 2.1.0 | PKG-ASR-01, PKG-ASR-02, PKG-ASR-03, PKG-ASR-04, PKG-ASR-05, PKG-ASR-06, PKG-ASR-07, PKG-ASR-08, PKG-ASR-09 |
|
||||
@@ -28,7 +28,7 @@
|
||||
| artplayer-plugin-document-pip | 1.1.0 | PKG-DPIP-01, PKG-DPIP-02, PKG-DPIP-03, PKG-DPIP-04, PKG-DPIP-05, PKG-DPIP-06 |
|
||||
| artplayer-plugin-hls-control | 1.1.0 | PKG-HLS-01, PKG-HLS-02, PKG-HLS-03, PKG-HLS-04, PKG-HLS-SDK-01, PKG-HLS-05, PKG-HLS-06 |
|
||||
| artplayer-plugin-jassub | 1.1.0 | PKG-JASSUB-01, PKG-JASSUB-02, PKG-JASSUB-03, PKG-JASSUB-04, PKG-JASSUB-05, PKG-JASSUB-06, PKG-JASSUB-07, PKG-JASSUB-08, PKG-JASSUB-09 |
|
||||
| artplayer-plugin-multiple-subtitles | 1.2.0 | PKG-MULTI-SUB-01, PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-04, PKG-MULTI-SUB-07, PKG-MULTI-SUB-08, PKG-MULTI-SUB-05, PKG-MULTI-SUB-06 |
|
||||
| artplayer-plugin-multiple-subtitles | 1.2.0 | PKG-MULTI-SUB-01, PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-04, PKG-MULTI-SUB-07, PKG-MULTI-SUB-08, PKG-MULTI-SUB-05, PKG-MULTI-SUB-06, PKG-MULTI-SUB-09 |
|
||||
| artplayer-plugin-vast | 1.2.0 | PKG-VAST-01, PKG-VAST-02, PKG-VAST-03, PKG-VAST-04, PKG-VAST-05, PKG-VAST-06 |
|
||||
| artplayer-plugin-vtt-thumbnail | 1.1.0 | PKG-VTT-THUMB-01, PKG-VTT-THUMB-02, PKG-VTT-THUMB-03, PKG-VTT-THUMB-04, PKG-VTT-THUMB-05, PKG-VTT-THUMB-06 |
|
||||
| artplayer-proxy-canvas | 1.1.0 | PKG-AMBILIGHT-PROXY-01, PKG-CANVAS-01, PKG-CANVAS-02, PKG-CANVAS-03, PKG-CANVAS-04, PKG-CANVAS-05, PKG-CANVAS-06, PKG-FACTORY-01 |
|
||||
@@ -229,7 +229,8 @@
|
||||
| PKG-MULTI-SUB-07 | artplayer-plugin-multiple-subtitles<br>修复字幕内嵌时间戳序列化 | PKG-MULTI-SUB-03 | 保留数字时间戳节点、修正无效 NaN 输出、明确旧/新字幕输出差异 | 旧九份实现可复现,候选有效内嵌时间戳及文字/CSS/原生字幕通过,公开工厂与选择接口不变 | H | done |
|
||||
| PKG-MULTI-SUB-08 | artplayer-plugin-multiple-subtitles<br>修复字幕实体解码与嵌套标签包装 | PKG-MULTI-SUB-04, PKG-MULTI-SUB-07 | 使用解析器既有实体表入口修复多余分号;保护字面文本并以兄弟节点包装标签,保留CSS钩子和时间戳 | 冻结旧实现复现、实体/双重编码/标签/选择重置回归、新旧核心真实字幕显示通过;vendor原文与来源校验不变,类型/分发兼容 | M | done |
|
||||
| PKG-MULTI-SUB-05 | artplayer-plugin-multiple-subtitles<br>验证新旧核心和组合 | PKG-MULTI-SUB-04, CORE-22, PKG-MULTI-SUB-07, PKG-MULTI-SUB-08 | 与核心字幕/偏移/全屏组合,旧名称调用不变 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | doing |
|
||||
| PKG-MULTI-SUB-06 | artplayer-plugin-multiple-subtitles<br>验证分发并同步文档 | PKG-MULTI-SUB-05, ENG-07, CORE-SUBTITLE-OFFSET-01 | multiple.subtitles.js、parser 来源许可及打包边界 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
|
||||
| PKG-MULTI-SUB-06 | artplayer-plugin-multiple-subtitles<br>验证分发并同步文档 | PKG-MULTI-SUB-05, ENG-07, CORE-SUBTITLE-OFFSET-01, PKG-MULTI-SUB-09 | multiple.subtitles.js、parser 来源许可及打包边界 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
|
||||
| PKG-MULTI-SUB-09 | artplayer-plugin-multiple-subtitles, artplayer<br>定位旧核心切源寻址与字幕显示边界 | PKG-MULTI-SUB-08, CORE-19 | 无插件及旧新插件对照、真实事件轨迹、原切源失败归因和组合测试顺序 | 保留旧核心立即寻址观察,候选首次寻址与正常字幕组合通过;不把原生时钟失败误归为字幕丢失 | M | done |
|
||||
|
||||
## 5 包迁移:artplayer-plugin-jassub
|
||||
|
||||
@@ -647,3 +648,4 @@
|
||||
- PKG-AUTO-THUMB-10: [记录](changes/2026-09-14-PKG-AUTO-THUMB-10-encoding.md) [记录](baselines/auto-thumbnail-encoding-validation.json)
|
||||
- ENG-LINT-01: [记录](changes/2026-09-14-ENG-LINT-01-manifest-order.md) [记录](baselines/manifest-lint-validation.json)
|
||||
- CORE-SUBTITLE-OFFSET-01: [记录](changes/2026-09-14-CORE-SUBTITLE-OFFSET-01-paused.md) [记录](baselines/subtitle-offset-validation.json)
|
||||
- PKG-MULTI-SUB-09: [记录](changes/2026-09-14-PKG-MULTI-SUB-09-switch-order.md) [记录](baselines/multiple-subtitles-switch-validation.json)
|
||||
@@ -1,5 +1,20 @@
|
||||
# 进度与证据
|
||||
|
||||
## PKG-MULTI-SUB-09 切源显示问题归因完成
|
||||
|
||||
失败时字幕cue仍在1至3秒,媒体却停在约0.002秒;新增无插件/候选插件/旧1.2.0
|
||||
对照并记录原生currentTime写入、事件和Promise状态。首轮WebKit27次切源中旧
|
||||
核心18次有5次立即seek未到达,两个无插件旧核心组也复现;候选9次全部到达。
|
||||
正式main三引擎81次切源无失位,但旧WebKit仍有6次在seeking中结算;候选27次
|
||||
均在原生定位结束后结算并兑现首个seek。确认是已有旧核心寻址问题,候选CORE-19
|
||||
路径已处理,无需在多字幕插件追加重试或改时钟。原失败及立即调用路径完整留证。
|
||||
84项正式产物矩阵83断言通过,1项测试未等待全屏进入通知即退出而失败;保留
|
||||
严格true/false顺序断言,补事件谓词后受影响9项三引擎全通过,不声称重跑84项。
|
||||
脚本lint与CI50项通过。见[归因记录](changes/2026-09-14-PKG-MULTI-SUB-09-switch-order.md)
|
||||
和[证据](baselines/multiple-subtitles-switch-validation.json)。关闭误归因的SWITCH风险,
|
||||
无生产、声明、依赖、版本或构建产物修改;249项为177 done、17 doing、55 todo。
|
||||
任务05仍未完成,下一步处理旧5.1核心的双语渲染适配,再补剩余组合与分发验收。
|
||||
|
||||
## CORE-SUBTITLE-OFFSET-01 暂停字幕偏移修复完成
|
||||
|
||||
原生video/track探针确认Firefox155暂停时cue时间更新后活动标记陈旧;候选核心
|
||||
|
||||
@@ -266,4 +266,4 @@
|
||||
| AUTO-THUMB-ENCODE-TIMEOUT-01 | resolved / 源码/产物事实 | Pending JPEG encoding has no bounded lifetime after frame readiness finishes | PKG-AUTO-THUMB-10 |
|
||||
| MULTI-SUB-MARKUP-01 | resolved / 已复现 | Semantic cue nodes receive HTML wrappers inside their annotation fields | PKG-MULTI-SUB-08 |
|
||||
| MULTI-SUB-OFFSET-01 | resolved / 已复现 | Paused Firefox subtitle offset leaves out-of-time native cues active and captions visible | PKG-MULTI-SUB-05, CORE-SUBTITLE-OFFSET-01 |
|
||||
| MULTI-SUB-SWITCH-01 | open / 待取证 | Intermittent WebKit core5.3.0 caption loss after selected-track source switch | PKG-MULTI-SUB-05 |
|
||||
| MULTI-SUB-SWITCH-01 | resolved / 已复现 | Intermittent WebKit core5.3.0 caption loss after selected-track source switch | PKG-MULTI-SUB-05, PKG-MULTI-SUB-09 |
|
||||
+16
-7
@@ -6028,21 +6028,30 @@
|
||||
{
|
||||
"id": "MULTI-SUB-SWITCH-01",
|
||||
"title": "Intermittent WebKit core5.3.0 caption loss after selected-track source switch",
|
||||
"confirmation": "unverified",
|
||||
"workspaceState": "One Windows WebKit26.6 run lost Translation after switchUrl and seek1.5; diagnostic rerun passed without a production change. Root cause and reproducibility are unresolved; do not mark accepted or fixed. Expanded153 offset/lifecycle run again lost the selected caption after source switch on published5.3.0 and5.4.0 in WebKit, while candidate core passed. Root cause remains unclassified; the offset fix does not close this issue.",
|
||||
"compatibleResolution": "Inspect native track loading and source-switch ordering with deterministic state evidence; distinguish historical host failure from fixture ordering and candidate regression.",
|
||||
"confirmation": "reproduced",
|
||||
"workspaceState": "Original failing snapshots kept the1..3 cue intact but video time was near0.002. Independent no-plugin and published1.2/current-plugin WebKit traces reproduce5 old-core first-seek misses, with promises sometimes settled during native seeking. Candidate already waits and honors every first seek. Actual main three-engine probes and corrected normal caption sequencing pass; old race observations remain explicit.",
|
||||
"compatibleResolution": "Classify the old-host source/native-seek race separately from caption rendering; preserve immediate-call probes, require candidate first seeks, and wait for real native source completion before independent caption-seek assertions.",
|
||||
"closureCriteria": "Root cause classified with targeted evidence, any required fix validated, and changed candidate/old-core combination rerun without hiding the original failure.",
|
||||
"status": "open",
|
||||
"status": "resolved",
|
||||
"owners": [
|
||||
"PKG-MULTI-SUB-05"
|
||||
"PKG-MULTI-SUB-05",
|
||||
"PKG-MULTI-SUB-09"
|
||||
],
|
||||
"evidence": [
|
||||
"refactor/changes/2026-09-14-PKG-MULTI-SUB-05-combinations.md",
|
||||
"refactor/baselines/multiple-subtitles-combinations-validation.json",
|
||||
"test/browser/multiple-subtitles-combinations.spec.js",
|
||||
"refactor/changes/2026-09-14-CORE-SUBTITLE-OFFSET-01-paused.md",
|
||||
"refactor/baselines/subtitle-offset-validation.json"
|
||||
]
|
||||
"refactor/baselines/subtitle-offset-validation.json",
|
||||
"refactor/changes/2026-09-14-PKG-MULTI-SUB-09-switch-order.md",
|
||||
"refactor/baselines/multiple-subtitles-switch-validation.json",
|
||||
"test/browser/multiple-subtitles-switch.spec.js"
|
||||
],
|
||||
"resolutionEvidence": [
|
||||
"refactor/changes/2026-09-14-PKG-MULTI-SUB-09-switch-order.md",
|
||||
"refactor/baselines/multiple-subtitles-switch-validation.json"
|
||||
],
|
||||
"resolutionRationale": "No-plugin controls reproduce the same miss and a settled seek restores correct old/new captions without changing plugin data. Candidate source code already provides the necessary readiness guard (BASE-LIFE-44/CORE-19 context). This resolves the suspected plugin-switch defect; it does not approve every historical source call or complete package task05."
|
||||
}
|
||||
]
|
||||
}
|
||||
+23
-1
@@ -2430,7 +2430,8 @@
|
||||
"dependsOn": [
|
||||
"PKG-MULTI-SUB-05",
|
||||
"ENG-07",
|
||||
"CORE-SUBTITLE-OFFSET-01"
|
||||
"CORE-SUBTITLE-OFFSET-01",
|
||||
"PKG-MULTI-SUB-09"
|
||||
],
|
||||
"status": "todo",
|
||||
"risk": "H",
|
||||
@@ -5157,6 +5158,27 @@
|
||||
"changes/2026-09-14-CORE-SUBTITLE-OFFSET-01-paused.md",
|
||||
"baselines/subtitle-offset-validation.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PKG-MULTI-SUB-09",
|
||||
"phase": "5 包迁移:artplayer-plugin-multiple-subtitles",
|
||||
"title": "定位旧核心切源寻址与字幕显示边界",
|
||||
"scope": [
|
||||
"artplayer-plugin-multiple-subtitles",
|
||||
"artplayer"
|
||||
],
|
||||
"dependsOn": [
|
||||
"PKG-MULTI-SUB-08",
|
||||
"CORE-19"
|
||||
],
|
||||
"status": "done",
|
||||
"risk": "M",
|
||||
"deliverable": "无插件及旧新插件对照、真实事件轨迹、原切源失败归因和组合测试顺序",
|
||||
"acceptance": "保留旧核心立即寻址观察,候选首次寻址与正常字幕组合通过;不把原生时钟失败误归为字幕丢失",
|
||||
"evidence": [
|
||||
"changes/2026-09-14-PKG-MULTI-SUB-09-switch-order.md",
|
||||
"baselines/multiple-subtitles-switch-validation.json"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+10
-1
@@ -221,7 +221,8 @@ Explicit single-active-cue probes record historical and candidate overlap defect
|
||||
their passing assertions do not mean simultaneous captions are compatible.
|
||||
Candidate paused Firefox offsets are corrected by CORE-SUBTITLE-OFFSET-01. Old
|
||||
Firefox hosts retain explicit defect observations; their behavior is not silently
|
||||
counted as correct. WebKit source-switch failures remain under investigation.
|
||||
counted as correct. Task09 classified the apparent WebKit source-switch caption
|
||||
loss as an old-host seek landing near zero, reproducible without any plugin.
|
||||
See `refactor/changes/2026-09-14-PKG-MULTI-SUB-05-combinations.md` before changing
|
||||
expectations. Reports include native active cues and rendered text. The new frozen
|
||||
5.1.2 core route verifies archive integrity and member hashes before serving.
|
||||
@@ -235,3 +236,11 @@ without creating an Artplayer instance to compare native timing edits, cue
|
||||
reinsertion and mode toggling. It records actual time within the required interval,
|
||||
not a fabricated millisecond-exact seek landing. These diagnostic observations
|
||||
do not claim every native engine strategy is correct.
|
||||
|
||||
`multiple-subtitles-switch.spec.js` records source Promise settlement, native
|
||||
currentTime writes/events and actual seek landing with no plugin, candidate and
|
||||
published1.2.0. Old first-seek misses are retained as observations; every candidate
|
||||
first seek must land. The caption combination fixture separately waits for native
|
||||
source seeking to finish and for fullscreen-enter notification before testing
|
||||
subsequent commands. It retains exact caption and enter/exit order assertions;
|
||||
do not add delays or plugin retries to cover old core readiness behavior.
|
||||
@@ -84,6 +84,7 @@ for (const core of cores.filter(core => !['published-5.1.2', 'published-5.1.7'].
|
||||
})
|
||||
await page.locator('#play').click()
|
||||
await expect.poll(() => page.evaluate(() => (document.fullscreenElement || document.webkitFullscreenElement) === window.art.template.$player)).toBe(true)
|
||||
await expect.poll(() => page.evaluate(() => window.fullscreenEvents)).toEqual([true])
|
||||
await expect(page.locator('.art-subtitle-a')).toBeVisible()
|
||||
expect(await page.evaluate(() => (document.fullscreenElement || document.webkitFullscreenElement).contains(window.art.template.$subtitle))).toBe(true)
|
||||
await page.evaluate(() => {
|
||||
@@ -94,6 +95,9 @@ for (const core of cores.filter(core => !['published-5.1.2', 'published-5.1.7'].
|
||||
await expect(page.locator('.art-subtitle-a')).toHaveCount(0)
|
||||
await expect(page.locator('.art-subtitle-b')).toHaveText('Translation')
|
||||
await page.evaluate(() => window.art.switchUrl('/test/pattern.mp4?subtitles-combination'))
|
||||
// Old core promises can settle during their native restoration seek.
|
||||
// The immediate-seek path is retained separately in multiple-subtitles-switch.spec.js.
|
||||
await expect.poll(() => page.evaluate(() => window.art.video.seeking)).toBe(false)
|
||||
await seek(page, 1.5)
|
||||
await expect(page.locator('.art-subtitle-b')).toHaveText('Translation')
|
||||
await page.evaluate(() => window.art.plugins.multipleSubtitles.reset())
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { hash } from '../../refactor/scripts/releases.mjs'
|
||||
import { multipleSubtitlesCandidate, multipleSubtitlesHistorical } from '../helpers/multiple-subtitles.js'
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
const candidate = await multipleSubtitlesCandidate()
|
||||
const published = (await multipleSubtitlesHistorical()).find(item => item.name === 'published-1.2.0-main')
|
||||
const variants = [null, candidate, published]
|
||||
|
||||
for (const core of ['published-5.3.0', 'published', 'candidate']) {
|
||||
for (const implementation of variants) {
|
||||
test(`Source seek ordering / ${core} / ${implementation?.name || 'no-plugin'}`, async ({ page, browser }, testInfo) => {
|
||||
await page.route('**/test/switch-caption.vtt', route => route.fulfill({ contentType: 'text/vtt', body: 'WEBVTT\n\n00:01.000 --> 00:03.000\nCaption\n' }))
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
if (implementation)
|
||||
await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; ${implementation.code}; window.multipleFactory = module.exports.default || module.exports; })();` })
|
||||
await page.evaluate(() => {
|
||||
window.createPlayer('/test/pattern.mp4')
|
||||
const video = window.art.video
|
||||
window.switchTrace = []
|
||||
window.switchState = () => ({ time: video.currentTime, seeking: video.seeking, duration: video.duration, readyState: video.readyState, paused: video.paused, source: video.currentSrc, active: Array.from(window.art.template.$track.track.activeCues || [], cue => cue.text), displayed: window.art.template.$subtitle.textContent })
|
||||
const record = (event, value) => window.switchTrace.push({ event, value, ...window.switchState() })
|
||||
const descriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'currentTime')
|
||||
Object.defineProperty(video, 'currentTime', {
|
||||
configurable: true,
|
||||
get() { return descriptor.get.call(this) },
|
||||
set(value) {
|
||||
record('write-currentTime', value)
|
||||
descriptor.set.call(this, value)
|
||||
},
|
||||
})
|
||||
for (const event of ['loadedmetadata', 'loadeddata', 'canplay', 'seeking', 'seeked', 'emptied', 'pause'])
|
||||
video.addEventListener(event, () => record(event))
|
||||
})
|
||||
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
|
||||
if (implementation) {
|
||||
await page.evaluate(async () => {
|
||||
await window.art.plugins.add(window.multipleFactory({ subtitles: [{ name: 'caption', url: '/test/switch-caption.vtt' }] }))
|
||||
})
|
||||
await expect.poll(() => page.evaluate(() => window.art.template.$track.track.cues?.length)).toBe(1)
|
||||
}
|
||||
await page.locator('#play').click()
|
||||
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.1)
|
||||
await page.locator('#pause').click()
|
||||
await page.evaluate(() => {
|
||||
document.querySelector('#play').onclick = () => {
|
||||
window.art.fullscreen = true
|
||||
}
|
||||
})
|
||||
await page.locator('#play').click()
|
||||
await expect.poll(() => page.evaluate(() => Boolean(document.fullscreenElement || document.webkitFullscreenElement))).toBe(true)
|
||||
await page.evaluate(() => {
|
||||
window.art.fullscreen = false
|
||||
})
|
||||
await expect.poll(() => page.evaluate(() => Boolean(document.fullscreenElement || document.webkitFullscreenElement))).toBe(false)
|
||||
const outcomes = []
|
||||
for (let round = 0; round < 3; round++) {
|
||||
await page.evaluate(round => window.art.switchUrl(`/test/pattern.mp4?seek-order=${round}`), round)
|
||||
const settled = await page.evaluate(() => window.switchState())
|
||||
await page.evaluate(() => new Promise((resolve) => {
|
||||
window.art.once('video:seeked', resolve)
|
||||
window.art.seek = 1.5
|
||||
}))
|
||||
await expect.poll(() => page.evaluate(() => window.art.video.seeking)).toBe(false)
|
||||
const firstSeek = await page.evaluate(() => window.switchState())
|
||||
const landed = Math.abs(firstSeek.time - 1.5) < 0.05
|
||||
if (!landed) {
|
||||
await page.evaluate(() => new Promise((resolve) => {
|
||||
window.art.once('video:seeked', resolve)
|
||||
window.art.seek = 1.5
|
||||
}))
|
||||
await expect.poll(() => page.evaluate(() => window.art.video.seeking)).toBe(false)
|
||||
}
|
||||
await expect.poll(() => page.evaluate(() => Math.abs(window.art.currentTime - 1.5))).toBeLessThan(0.05)
|
||||
if (implementation)
|
||||
await expect(page.locator('.art-subtitle-caption')).toHaveText('Caption')
|
||||
outcomes.push({ round, settled, firstSeek, landed, afterSettledSeek: await page.evaluate(() => window.switchState()) })
|
||||
}
|
||||
await testInfo.attach('source-seek-order', { contentType: 'application/json', body: JSON.stringify({ core, plugin: implementation?.name || 'none', pluginSha256: implementation ? hash(implementation.code) : null, browser: browser.version(), outcomes, trace: await page.evaluate(() => window.switchTrace), scope: 'Three real source changes with immediate versus settled seek; old misses are recorded, candidate must honor every first seek' }) })
|
||||
if (core === 'candidate')
|
||||
expect(outcomes.every(item => item.landed)).toBe(true)
|
||||
await page.evaluate(() => window.art.destroy())
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user