test(vtt-thumbnail): [PKG-VTT-THUMB-05] verify historical core and fullscreen combinations

This commit is contained in:
Harvey Zhao committed 2026-09-14 09:57:21 +08:00
1 parent 4fa5c68be9
commit 07d5bfef2e
14 files changed
+2984 -10

No files matched your search

@@ -110,8 +110,13 @@ plugin. Empty or comment-only input remains a valid empty preview.
The exported callable has a writable self `.default` alias, restoring the usable 1.0.x
CommonJS default access while retaining direct calls. It does not add a name property to the
registration Promise. Earlier `thumbnails` control names are separately frozen and remain
combination/distribution work for tasks 05-06. The approved declaration migration does not
registration Promise. The old 1.0.1 plugin uses `thumbnails`, which works with the
recorded 5.1.6 core. Core 5.1.7 already reserves that name, and the actual 1.0.1
bundle rejects registration on 5.1.7, 5.4.0 and the candidate core. These reproduced
historical failures are not successful compatibility cells. Later plugins and
this candidate use `vtt-thumbnail`; do not silently replace the core's reserved
control or introduce an alias over it. This pairing remains part of task05/release
review. The approved declaration migration does not
complete the remaining package or device acceptance.
## Verification and future changes
@@ -123,14 +128,27 @@ yarn test:vtt-thumbnail
yarn test:vtt-thumbnail-types-package
yarn build:ts artplayer-plugin-vtt-thumbnail
yarn test:browser test/browser/vtt-thumbnail-lifecycle.spec.js
yarn test:browser test/browser/vtt-thumbnail-combinations.spec.js
yarn build artplayer-plugin-vtt-thumbnail
```
The unit helper can load actual main/legacy files with ARTPLAYER_VTT_THUMBNAIL_ARTIFACT or
the frozen former implementation with ARTPLAYER_VTT_THUMBNAIL_BASELINE=1. Historical tests
are distinct from candidate expectations. Browser tests use real published/candidate cores,
native fetch/abort, mouse hover, sprite decoding and cleanup. Their scope is not full old
core/device coverage, installed tarballs, mobile Safari or the online editor.
native fetch/abort, mouse hover, sprite decoding and cleanup. The task05 combination
checkpoint adds actual DOM screenshot pixels, Chapter coexistence, web/native
fullscreen and source switch against core 5.1.6, 5.1.7, 5.3.0, 5.4.0 and candidate.
The 5.3.0 archive is an adjacent stable comparison, not the unpublished 5.3.1
source-associated version. Historical 1.0.2/1.0.3/1.1.0 main bundles run with
candidate core; 1.0.1 runs with 5.1.6 and retains its later-core failure tests.
Compact-arrow input for 1.0.x compiled artifacts is labeled explicitly; ordinary
arrow parser failures remain in the existing historical contract tests.
Mobile integration uses an Android user agent and synthetic DOM touch payloads
through actual core handlers with real media seeking and the 500ms hide timer.
It is not trusted OS input, physical Android or Safari/iOS verification. Task05
remains open for required device evidence and historical-pair disposition;
installed main/legacy/ESM consumers and the actual local editor remain task06/EX-03.
Modify parsing in parseVtt, requests in request, layout/timers in preview, and ownership in
lifetime. Preserve the normal/failure lifecycle tests alongside any parser improvements.
@@ -57,6 +57,13 @@ JavaScript default access, the direct factory, and legacy distribution entrypoin
See [ARCHITECTURE.md](ARCHITECTURE.md) for module ownership, testing commands and remaining
compatibility validation.
The old 1.0.1 JavaScript bundle registers a control named `thumbnails`. It works
with the tested core 5.1.6, but conflicts with the built-in control reserved by
core 5.1.7 and later tested cores (5.4.0 and the refactor candidate). The current
plugin uses `vtt-thumbnail`; retain that name when integrating custom controls.
This documented historical combination failure predates the refactor. Native
desktop tests and emulated touch checks do not certify physical mobile devices.
## License
MIT © Harvey Zhao
File diff suppressed because it is too large. Load diff
+246
View File
@@ -0,0 +1,246 @@
{
"schemaVersion": 1,
"task": "PKG-VTT-THUMB-05",
"sourceCommit": "4fa5c68be9d2d0d60d725c2a87b8d92a4dc8a85a",
"capturedAt": "2026-09-14T01:40:29.729Z",
"metadata": {
"url": "https://registry.npmjs.org/artplayer/5.1.6",
"status": 200,
"sha256": "e1f9c3b9887fc4143a1b5b89f001cb05c013dee611dd427bfb89f5d27ac6641d"
},
"association": "Published core corresponding to usable VTT 1.0.1 archive source association; not a claimed minimum supported core. Core 5.3.1 was previously confirmed absent, so 5.3.0 is an adjacent stable comparison only.",
"release": {
"name": "artplayer",
"version": "5.1.6",
"metadataUrl": "https://registry.npmjs.org/artplayer/5.1.6",
"tarball": "https://registry.npmjs.org/artplayer/-/artplayer-5.1.6.tgz",
"integrity": "sha512-cqnVVLKCKWCryKl6Pmop50/Di9IQwOeNNQs5qWGzJDPiM0qTC7Q/Enusa+8JQid8p09fvp4Vc32ViSSYutdEeQ==",
"sha256": "0cd1e52efdb08a9b4c0184df45a1828ac956abf6bb9775b75e62c27beffc8bbc",
"files": {
"package/README.md": "2070b94087839a80dc01616a3114cbe2d3a4950018188f433752880daf7843f8",
"package/dist/artplayer.js": "6a7b1f3007ecda9f399e6cff606490dd745c495e19ce10e864a401ff09996172",
"package/dist/artplayer.legacy.js": "73c9193a8903e196adb7107e0c54a259609b06532004eb4da6fa3199d0a3ecb0",
"package/dist/i18n/cs.js": "0e353e313076ab5bc812c69d95c65dd4f41304be8cd3248b4fb1e66cc96361ef",
"package/dist/i18n/es.js": "e95e0c3d9e67d9aa9560a1d4ad34d7e524bb654573af63b583b0e230f397a918",
"package/dist/i18n/fa.js": "9e491847bacba5115af6c436461cce7b62b27913d73201a25f1ab33357fac820",
"package/dist/i18n/fr.js": "47f8c2741b8c65a71d02061b4d9659d5c9634c9b4670d16852d649fe5ca3674c",
"package/dist/i18n/id.js": "eb485192730c9a23aafb6b82b71cb3440e66790b9527fa735e1a23e132597170",
"package/dist/i18n/pl.js": "1ca2be239bda3d652431e8d4d8e41170d737b90193c151bbbfe9c1716d67c4f8",
"package/dist/i18n/ru.js": "ff7d1323f5fb21ead2834ae140da9e4a35cc2f80070f213623795b63daad79e6",
"package/dist/i18n/tr.js": "3981931b76ade9f8b8c6a862a18e702aed2644445b18a338bf2b58f9b16cde87",
"package/dist/i18n/zh-tw.js": "e6ed01c7cf38d47f36027ee916181aa5a243de4872d2fbcb2bca91668df84aa3",
"package/package.json": "412253a67616ed94c058a4eefdb5f0e7b863f696a92e5ac9e3e82c87ce5aec0d",
"package/src/config/index.js": "6419ff29300032a0c3535a396d7c977cf4ac09d9edc6b3a04eeec7256ea5f6d4",
"package/src/contextmenu/aspectRatio.js": "2e880ea29ed71d6e05192f10de246e0646754817f8135ac71bc4f082c7f60ec1",
"package/src/contextmenu/close.js": "4df0e913b1755409f034cbb54027b4518f05490ef66ad84b6f0e995899f41bc4",
"package/src/contextmenu/flip.js": "6f7574f7b5dfb0464e86e5910cc7b6f64ae06cbbef8d9a2a30086050a3952404",
"package/src/contextmenu/index.js": "2d1503ff5cd0ff038bbbdc9e52b7d8fc6b2c8d836e0474306ec1bb04b00cdfa3",
"package/src/contextmenu/info.js": "b7286de4d650d115493ef98891b77ff0deddb7e6c5725d93c8874890304885c1",
"package/src/contextmenu/playbackRate.js": "2b470a632bba8c40ffc46c00374e80bd3ea2325cf0c9e5ddfad81a03fd149847",
"package/src/contextmenu/version.js": "d15f750e2af7c9de92ce85fd765541cd0deb00dbff6fa7544b90ba2e00354f40",
"package/src/control/airplay.js": "3f5a5c82edfd8e0104311d1bc6224a216e8823d977f4d3d2efd2230232f1096e",
"package/src/control/fullscreen.js": "fab9bd25ace5b85b643207cc781fc1ccf73bdc6abdeeb35d7863cfe21ce25da3",
"package/src/control/fullscreenWeb.js": "c4e8f2ed78556ed5a1fef61477d4fd4acd2bbf2226b0969604cabea3b8cf8152",
"package/src/control/index.js": "6fa98c681854b5d1870f44dda4a96605888cb3c2ccc47e2294f86a372f468fff",
"package/src/control/pip.js": "abf03561ccf8209e58b961c32d013a24e190b275f5c420f237eb5c9eea836de7",
"package/src/control/playAndPause.js": "e29d017f0c629a583b970d08ffe91169d43c573e2fa50e5467182a3e2ca06d34",
"package/src/control/progress.js": "8fe464a3cdb45323b8e080cf9e0d8b7ef9e3046e87deac011f14a9607945c8c9",
"package/src/control/screenshot.js": "66d1baddda0e7aeecfa13b345b95c388e9b030e56ed41b6ab5bd7fd65305fb8c",
"package/src/control/setting.js": "5aafdb3a26b0526d38c1de2a721d818a61ea06c1c3ef9fce54aa467cb3999c7e",
"package/src/control/thumbnails.js": "5a0614ca37d8668e4ed9af51ac09ee7f7fc2c69ac49b56a43b764c9db5bb20d6",
"package/src/control/time.js": "b29e4abdab8a52a120534d268b56ea502e7394a1d0a3ce0986b5f90a4251dded",
"package/src/control/volume.js": "4411722264c3f27adf65d2f3191e95ceb3b89734fc1afa436d5e40f4450a67a7",
"package/src/events/clickInit.js": "c71e5709da54b6dbd650744c3cfea43f74cbad39080da4db5c049452e4a8c595",
"package/src/events/documentInit.js": "3588e34c434555ac474c92519f1aba8d8f9b442b9cf32d15a12e136bcbca0ae2",
"package/src/events/gestureInit.js": "d11294980ffa4a5c68d9059d1fcf773c60ee4dcd3230ff1adb6de78b29d5da09",
"package/src/events/hoverInit.js": "e7ad02a7b3a2fa654b29d6016cc8b70950185a9fae422fa259b443046c9f0b5d",
"package/src/events/index.js": "9e89b16e3082c9d4c74accd8e58b8e5229bfd07a29e63018be1c3ce81f18ecda",
"package/src/events/moveInit.js": "396c374c161a62c7b74fc52ff8e8efe99016eac2b3ce9fa4f2476751b8f46d51",
"package/src/events/resizeInit.js": "c1cfb19f57bab631d5a6fe0691c4b1c26e1cc9d7f412069368aa2a467ecd9c1f",
"package/src/events/updateInit.js": "40cd0fd049e660ff58c83e20823409b9461077924a9a777406866c3aa345296e",
"package/src/events/viewInit.js": "b04b1356495e5edc19c435b3263665d8b0906a21329391a2e24051d1b5943868",
"package/src/hotkey.js": "ca9ecd041f2d2081fdc8f6bc2ba13c9eddc90afb1cdddef3bdb9907866efaa94",
"package/src/i18n/cs.js": "ebf7b10a0c1eab982935047019016e1e4e639c3184cf01805c651fa5473caf42",
"package/src/i18n/es.js": "90f2acedb4387b323ce57de3d693361caa130aa85f979f748ff3e5126b849b62",
"package/src/i18n/fa.js": "5b97bc2a038a4e75b56c2e5408412355c0eb54efae3033dcebce889442b3bb55",
"package/src/i18n/fr.js": "91901814ebcffc0c282e817fe7467c59406eb2d7c388fe5d6513078dd06db3a8",
"package/src/i18n/id.js": "7207ba2e88336d6342665ab8037e1ef1710c1ee09ac9d7c040237e4a3d5b8c5b",
"package/src/i18n/index.js": "5408964b30ab298ebfa8bdaa4c45a1bc5f517682a0032c15ac98fb11867b8855",
"package/src/i18n/pl.js": "1f0b0849c3de39faebcf5a14c068374344cfb9de5745f6e5abedc5d569aea529",
"package/src/i18n/ru.js": "44ec0ab1ba6794315069adf178ab9ac645922ba408aedfe09ef8b79daf70e776",
"package/src/i18n/tr.js": "f94e874dbe8e4a7aacbd4444a7040e9bf9ac140e442f33fed31e376ce8f52a41",
"package/src/i18n/zh-cn.js": "10707cf170c062e3450587d21cc12156cb88843a6766c61eedafed0d2cf34a12",
"package/src/i18n/zh-tw.js": "b7dedc5616f12345b17c8ec185853b08d0ef572fb7460df79fc0206f0c8b6d97",
"package/src/icons/airplay.svg": "095f71bbac1aabde07963c645cb2071f790873fb2730363224e004321a01242a",
"package/src/icons/arrow-left.svg": "ac8cb60bf1f9436b9fc27eef2c65787dd879f01fb7ed2070b74be8a4d3167e0e",
"package/src/icons/arrow-right.svg": "9e2aa8a84ee9879bb70fb4fbae8eeb2a020e9a02c7bde14dede819d33acdff3c",
"package/src/icons/aspect-ratio.svg": "a71df3064cba45f402698b4c11fe21798b9af9aa6c5d0d689262889ffa386ab1",
"package/src/icons/check.svg": "672230ecd40c42b5354aad702ba6b018a9b765655bc96a53ba003fee41d8413a",
"package/src/icons/close.svg": "bb9e23e5305d11ec3d8f75a50ecdf3150deab8614c7df2af588873f2d78f06c2",
"package/src/icons/config.svg": "adbe547dfde4b44399da319ccdfc29fca57bcdbec8c6af5e36a2eeb97ecc2041",
"package/src/icons/error.svg": "d85a72e27ceaa38221637405cb0a5be270a297da58f1b0428498f568fab7570a",
"package/src/icons/fast-forward.svg": "709887f67e76e76d17fec37025c7405d85e9be28466d49602c1aa18732c89cef",
"package/src/icons/flip.svg": "ea6d9328823bb8454af65250030f02584239fcf8fbc2fb937dd1a1bac7602c28",
"package/src/icons/fullscreen-off.svg": "612577a443da55433bef698f1f4a426d0223c70cf1bcec3b27221bff753ae621",
"package/src/icons/fullscreen-on.svg": "bbec64253a42ef5ea26f6289d58254a7e86af3c0d627b2eb2ae357ef47cd04db",
"package/src/icons/fullscreen-web-off.svg": "57fa0e8780baa7f27befdeeb9ec2e772a1185a469a5f7ce05ed760d93ac8c434",
"package/src/icons/fullscreen-web-on.svg": "c6283f3ef124ea47e27b725ef5757a0b586dd5371cbefcdf2180dfabfe6375a9",
"package/src/icons/index.js": "b0107676f57ad6d04e507976f5582e64d4dd71309ae395897f608f2591896320",
"package/src/icons/loading.svg": "ffcf5d814e6f3931a370bb4f0d2675381c2adb8f6d29dd1ee8f5df33d8175e75",
"package/src/icons/lock.svg": "1acb0566c08175200cdd47f0ce7f72ca1ae2761962cc3b134be4d44398cfcee2",
"package/src/icons/pause.svg": "9efe05ebf5610befddebcac51b3c9a491001189ff86204cb47928eb1617f6c7a",
"package/src/icons/pip.svg": "52d1e150d1364aed20917d83a2f7ab7589fb9df9655f3d3afaea3c4387800812",
"package/src/icons/play.svg": "c35562d20028d52ce329f35f90496a06d4dc5b6dc39df7ebcfb027f6f2393958",
"package/src/icons/playback-rate.svg": "cbc025c7780a5e5c31160182d70131202fa41a661d20ec2933e0bb1f488f1cd8",
"package/src/icons/screenshot.svg": "49f7d90198fb0bcbc29848f40b0a8c042b78c07ecef1cfc5184e2e84a61b4bd4",
"package/src/icons/setting.svg": "7f6454d1c7f037d5a7144a898abedc89ca339534166d620dfa45efcd4c74ee3c",
"package/src/icons/state.svg": "9d777729e9287c6dc7f8d0687a257ffd40bd817fa84f24eb98dfebb3256b6e35",
"package/src/icons/switch-off.svg": "0bf5803437823035b816fb8bec148c06b4e01f85ea987cedda87269da6aab412",
"package/src/icons/switch-on.svg": "1d87b42af5e7141f9defdc790567534288d84858d5068dd15093d5ef12f37f9c",
"package/src/icons/unlock.svg": "f341e80530c2b6b218495c7ed3b9e4f268d70d2c931c0bf76efed1add8bab745",
"package/src/icons/volume-close.svg": "b9dbeaf9043c8014cd29d0e4a21a82ce567bc6b85497c310cca5f68bceeb31b2",
"package/src/icons/volume.svg": "baebc4ede3013202a4b13202a8d961cb0e5e065ee03733816022b2541d13884f",
"package/src/index.js": "01ac24c9cc37f788995b0072769a46532bb569271ffdf4e3f734bab3fae2da67",
"package/src/info.js": "7fc50f9549ab4cc91422dea5182fe6250cf8273501425cb371a5870393bc39c1",
"package/src/layer.js": "ed576b5a805684852de55b56e65bf295ef8422e51e58a7f0fb7ad9987639f262",
"package/src/libs/screenfull.js": "3ff8b0abec9b100b4c25476627f7bd505466ae77a0700c95347e9e6e05f45bc6",
"package/src/loading.js": "f47a310ae4acfbd45bf34786901377844a08b4acc40d169f99b1af7ab02e4988",
"package/src/mask.js": "c28ab44ab96255f9357d39e184a048aa12f0822073d38a82c63d59b6cd2a0936",
"package/src/notice.js": "ef17bef61d6ff1e67f5e722a100ab5f5f9e4779f1297b06e16b5a9a32168cd67",
"package/src/player/airplayMix.js": "83346ea049d0a17b6943926f67e6c3a1e7242bcd978933dd77cd16ae3dca39ef",
"package/src/player/aspectRatioMix.js": "9f262f3fb47d23dc784aa31ea3264980567dcecdbfed592f2a26251d9473bdac",
"package/src/player/attrMix.js": "ae4103f3ede68f9ae87a16fa2c1e2b3bd3b03ec6190eb0ea8ace0c4b61216a29",
"package/src/player/autoHeightMix.js": "3c24c9b2a8ccc95f0b6b682e506565c0616f1b96f3d98bd20d219616d2dc4234",
"package/src/player/autoSizeMix.js": "65a480384c0939fda230e01b0deea43df757174d44828259f43abc3f63ed65c0",
"package/src/player/cssVarMix.js": "ea05acb553183ae60d42829ccf96deef06fbdb400424071777bd39c6ed6e683c",
"package/src/player/currentTimeMix.js": "41e5a6ac03d0dcd6883d5b08e2c74e0421b3d68e819f2b9c1e7f27aaf26bd7e8",
"package/src/player/durationMix.js": "87922cfb4a55db593e1c0187bf1912cf5b7c9b3b0136341723692a60f95efe01",
"package/src/player/eventInit.js": "f5f7412e652e8b2709443e2e2833d949e3563c002794d78cf466200e27af7be1",
"package/src/player/flipMix.js": "416485570461e7ef3c0346b528bedd8846bd24473d51ce6e33ac7abf61a24dfd",
"package/src/player/fullscreenMix.js": "44607d23d05d45816dd51503678d70dd73a212ec01caf66af8f2be5ab94ea271",
"package/src/player/fullscreenWebMix.js": "168aa2b5ddf6b0305a565bacb73ade7c49942d7e8abcbe3198d4089e071d17b3",
"package/src/player/index.js": "518d54576f7cf1a7cec6031743a19ad1a475df54e539546a722c174ee4c2cf1b",
"package/src/player/loadedMix.js": "cd984138d0bee78d8e822ae424a4f61adc5530327283e2db72b1942f6b464f22",
"package/src/player/miniMix.js": "37cba99a8a8b9ca666cf79f85d47096a4f475da376ada1adc9d5d39f905bf2fc",
"package/src/player/optionInit.js": "ca8978d55edd199a8ea6ccffdafa6d5ee0b1eebc818333b73d81574daadb0493",
"package/src/player/pauseMix.js": "f96b7d2f17a01144bb5299612a794b4e971d7e389444f3769a272fa164f82886",
"package/src/player/pipMix.js": "f6c1970557258374f1007b16eaea05a2ceaf4319ad1cc6c7c0e4971b080775a8",
"package/src/player/playMix.js": "1e37d4ff7d5a5508c9f656d391993ec28a5a4627aca7917d4601164f6fdc5d63",
"package/src/player/playbackRateMix.js": "51f862cfec9744b7414a75fd1cd2aaaaf41d240300a21d024320ca85ede71415",
"package/src/player/playedMix.js": "0d345bac5914a3403cc2b7f5c8d68ab61a4c53e9085602d8e28950dab7175936",
"package/src/player/playingMix.js": "2ba6c2c9e495bcabb91da43d0c8162742c80f9fe39ee60e15eb01e7c5761348f",
"package/src/player/posterMix.js": "b50ee061fa1ded74b77a2e0b0e7306d9f8f87854d8b72368e2e84f2a89568850",
"package/src/player/qualityMix.js": "3e43a8a6e0c0004e8f88a42457db61c20bb2184203675d19cd5761f936ae15a3",
"package/src/player/rectMix.js": "9f319e6d2cf20af90d9c5f8291099132c982e299034474e735ad5e8b1ddf7c6e",
"package/src/player/screenshotMix.js": "40bb2ae541ba41a60bdfe315c9fe35da25954132ad8c52f184281dc341e6af24",
"package/src/player/seekMix.js": "2bb1f1923aad7a989b4cadb3fe79e02176adb123425a356a93541eb8cd0885d4",
"package/src/player/stateMix.js": "ff8618ab6424f9d34337ebf5294449d2eea5cf76307b654cfff1e53e71c3ae54",
"package/src/player/subtitleOffsetMix.js": "5dfc80bce7921ce305259fe0a6f92a79f6bb09c1c7ca00132e3595a25fcdfca7",
"package/src/player/switchMix.js": "34bcc9d0c55ccb4b859583e22c0516171c719fa95c2b9b0af3232ad2455d789e",
"package/src/player/themeMix.js": "4f5394da3fc6fae0b5996a4d0a9d875fd8f9a9def759e946fc6a64af595dc3de",
"package/src/player/toggleMix.js": "9ec0e69ade2445e8e583eb94d226825efe2c109274eeed244c1e035e39b024a9",
"package/src/player/typeMix.js": "2a2284a7c1368c33054c8f8df473fa2cac71bb97dced04b3c61097854e05351e",
"package/src/player/urlMix.js": "f30f285ab3b071a47c3f82b6150f89664ab03fc8c403a8c953e197a7d457e5fd",
"package/src/player/volumeMix.js": "9847e9cdd994023db1ab1df7f71177ec52b9eea16105f9297cc0cfab0d5fe040",
"package/src/plugins/autoOrientation.js": "b334635916271821f15d5669c78bd54353c73f789e5f3881b3f42892c25e3887",
"package/src/plugins/autoPlayback.js": "9aaf05c22f7ca3c36fe4f8adcb1cc0374d4aceeef0e22d0f11b1c2cb99aebf35",
"package/src/plugins/fastForward.js": "77f2bf8f4d3b81328da0ca95bc74eb5f8b36ab70b0f0fa406d90ee5448ada697",
"package/src/plugins/index.js": "5a25986996ffa174cfd7678a072d2b703c4ab903b357c4635678703defdd03ef",
"package/src/plugins/lock.js": "e3aa7dfe8380cec6ff8f64fc6b97211dc3a2f6d0b6fd67d40cc6ecc176c8db0d",
"package/src/plugins/miniProgressBar.js": "8d22005b3a42820c7b6c53f0abaaed38f94a5fa12239e27f28efccd379c2c5eb",
"package/src/scheme/index.js": "42f14c584e0e663f8f0a111954fdb26e56ebabd4c5e45c455fa740f03d268b47",
"package/src/setting/aspectRatio.js": "b1cf508b7806776ac7e952cd1791da8dabce4177219f8c59e9fe4784be5aa1fa",
"package/src/setting/flip.js": "1ecf3b33579f8fb564763a83b2aaca1949fa582816f185b58684cc341aa39dee",
"package/src/setting/index.js": "259b5749eda09fbcb8ec3ffb300c2d7c25c87a5710fb58401b75745a0e771540",
"package/src/setting/playbackRate.js": "77826765484758cafab1d000baab857d856d38caca80d25cacfc52988d3a1259",
"package/src/setting/subtitleOffset.js": "7112aa437e203b4449eba9a95a5885fce9bb09c15c879bceb79536b3f152823b",
"package/src/storage.js": "416f090c331fa27ff49838e58967c77f334bff4bb000cdc116d2579f5ac56021",
"package/src/style/artplayer.less": "662cfc3f079e75e50c18199511d533f4e35f7eac21aaf8f1171cfc93dcca243d",
"package/src/style/aspectRatio.less": "5ab50ae065c4a21734f17a32f5838b940f97070083143dabe1070d45630a3aca",
"package/src/style/backdrop.less": "8530dcc3e390b7a1cd767463023aab2ca410478792dd5b4f00b24ae55967ed33",
"package/src/style/bottom.less": "447283e979e53e6c777dc8f513d0b42488ab98afb8f5f5bb8cb0d645df47a085",
"package/src/style/contextmenu.less": "3aca4d6f32e5fa7022b22bd2f7bc81d8b17224158a7de41ca9e6b8ed84837252",
"package/src/style/controls.less": "89d35e4154a82a99096df18bc01b1f7939a54b1823c12bd2c43e0ce67e91fa0c",
"package/src/style/danmuku.less": "e75aae6ff39b1d255d250486562e9db8324dada097552d62a0a85f2de7035caa",
"package/src/style/flip.less": "7b7be6602d1672c7d17a726051273c320eec83a925be509e2545df7a387123b7",
"package/src/style/fullscreen.less": "0ba5cddcd264a2750281a309916ab0f3d8b01131666e052a24bc0ec89e870e76",
"package/src/style/fullscreenWeb.less": "1e0bac3295e5269ac28888cdc9060f6720983792dead34bfad897e2d33f499bd",
"package/src/style/hideCursor.less": "fcf26ad3ca2ce28486594975a045304048bdd98996bc80ac74e36740fd7ef4e7",
"package/src/style/hint.less": "e29017145d831b23337b500b9ed5ff3706ce56f31dc4ac2720615c6ea3a9d97d",
"package/src/style/icon.less": "a75dcb23a859cb42fa50cadada36508ce752aed6ea03984a8f5947d8584d10b7",
"package/src/style/index.less": "1d9cecc59fe0d0b7f2d057c91998e3a2492ea52999369512ef355fc166781474",
"package/src/style/info.less": "ba577cbe605cd541d0171d4e0b2fe15333963da4bc040d466bfb347f9be79bcc",
"package/src/style/layers.less": "93791f5e52176a166835e1f4b3d24a07d305531f91647cc8aea75496ec72b8ab",
"package/src/style/loading.less": "7f211e95694e0d3aa64b6f8e25deb6f60c2c65303dff9df44b1acab6cbc30bcd",
"package/src/style/mask.less": "251ea4a6b4ca20de2baaa8b13b420a77180fb570ca1744a7bd757d646b5b3664",
"package/src/style/mini.less": "de25c47271e807fc311f33110e651ea0ee143e61b15ae92cdcbe4ea8d2e78683",
"package/src/style/mixins.less": "3bb2205bf2b2ff9c224010fc1a170f1e56614f6e710b222f2e8807747f772c04",
"package/src/style/mobile.less": "088a21666ebf5b631f2d15527c2a283890b25285d0d31ea5f60adfaf3689d936",
"package/src/style/notice.less": "98baf3481e7269bb8b4d399d561a15f6f5189e45f50225adf41aabb64d0e94d1",
"package/src/style/plugins.less": "97b4baef8a0493f152ae73ce1b988cab0d7eebbe4a6c119e944247d19bcfd2bc",
"package/src/style/poster.less": "939f33aa2a48806eb1da3bc4b49a8f9ab541ff2a53796260f475b2c7a98cba60",
"package/src/style/progress.less": "1440c2dee6edce1edf0dd41cb8efa03fd504d295e119af9c7735b1757db73a38",
"package/src/style/selector.less": "5320e35c670912a57534fdf4122aef566c9ca273e14b52af5d882c8cd4591f74",
"package/src/style/setting.less": "1951153c3fa2ae6541c0a046404db043a1287b80847a499c6386c49c3e929695",
"package/src/style/subtitle.less": "b26cdc6aa6e5a113a0197f08e895ce73f0557e54d0e4d1dc4cac03a2fd48b5c0",
"package/src/style/variables.less": "58f64242b0838815fc96083a698a44aea15ff876fd0a1154ba496171b4187e3c",
"package/src/style/video.less": "a2a7ca14711238c18acdfa7d094c5223f269618cbb884866a6cdc22af7579b8d",
"package/src/style/volume.less": "7593ef9f5e34713b30b5d690182c6510a0912dd659f3405f7f38242398fbdfcb",
"package/src/subtitle.js": "7847d732cbecd3fabb0683b69d22972d9c47b1b13a991fa6b46e2b95d3ba4a65",
"package/src/template.js": "6561ac281682a65f3423dffd232b56e14f10d88713743d6505e1fbe0cf5402a9",
"package/src/utils/compatibility.js": "079c4621b7856d2f34bfba27376048c47b538cfc3e07c9d019701bd05a8b62c8",
"package/src/utils/component.js": "1a96e1ce80fab7a2c88e0849bf8519edd2554e332a4d3461eb7de8d3c709d638",
"package/src/utils/dom.js": "6ec4e5bff93aa9a8203a8fafcc6fb0781f22f78bb38e85e230dd1d7c1c50077a",
"package/src/utils/emitter.js": "637c2b65c89a34ca3208335a892258540eefc49cb8f87f981c69496fe49efa89",
"package/src/utils/error.js": "3b395e07922fb3fcbb7de34e662ada1914b3499dac6f109e522c432bd705f3d1",
"package/src/utils/file.js": "c02139c54e569bf635f90d32b7ccb9d6cb8ba5ff126071e6c79b34a134b11cb2",
"package/src/utils/format.js": "318a9e844fdbb64168a1d076c45697e35b0f907103089bce94b414f132ab3e9c",
"package/src/utils/index.js": "585394c7bfda8e8548cfb92c73ae1e45cccc55c48d683ca9a48099debdf4b98e",
"package/src/utils/property.js": "48faa8d72daf7bea824146ecf9ccec0575fd32995d482cb94731d859b1f9a437",
"package/src/utils/subtitle.js": "4f5450fd6d4881d2499d2c4f54e8ddc39c5edb6d2bb2d6c6dd7555672bd28e5c",
"package/src/utils/time.js": "d471d1cbde1a108b908a083005a3af1e17a3df55b084cec1f1866368f1f3d07b",
"package/tsconfig.json": "bf1616499e177df22713d30f25dd255295c43d34310185403b2dfb1c4970c793",
"package/types/artplayer.d.ts": "ae6877ec208b09c9538e46b33eb80230690d7a3e04c69f14ea33a57557039143",
"package/types/component.d.ts": "7a4ea13e3f6400918190d2f34992b7de96e6145b4ebdf2030976594d5673f50d",
"package/types/config.d.ts": "3e2e3294802653fbab62f05d5d656411c657641d8f7a3ce64295eef44b37ef62",
"package/types/cssVar.d.ts": "a83429be37936c98850975c1a3a6896bb8a113a270b8cbe3994967f1d41458a3",
"package/types/events.d.ts": "f5b052edb9ef5fee846fe7aea9393e80df964226f1d4de21e6dfc0164662d0ce",
"package/types/i18n.d.ts": "75a61026bbc08cf29498700d1ed73b115734d9284085ab1ea0769d3d1a3c3d8b",
"package/types/icons.d.ts": "a4d2fa1a85755cc40d0ac9d0dadb7bedae1872b3306ba434f0fd817c0b2ac3b6",
"package/types/option.d.ts": "a336ee6381415fa7141edc1a1967db12e353b1cfad3af6f390a3c47f146faa3a",
"package/types/player.d.ts": "94dfcb837326954195cf38363ef8d8b909243549579c59fdde344cd8d8f1886f",
"package/types/quality.d.ts": "b07e6525dcadbbb6fcd7c5ccb5e24eca87d25b24b8a23b49891c032a479fe660",
"package/types/setting.d.ts": "fbf66bb3fd75e4d57052aafc41f752f8fca1c801ad502ff06ef11a6ab6b86200",
"package/types/subtitle.d.ts": "76d899e4f72aeafedfd8f063f9dcbe2ada9e367d0bb2dc6a01b9929d3ebbd58f",
"package/types/template.d.ts": "a6065449803fc0adca1b39a2588c01c4d82e4b2e3be73bb66f601d579aa2a583",
"package/types/utils.d.ts": "5cf2785edc48a462f28603b43f1176ee1f7bccc5be9d0824798cc9af32b5d45d"
},
"manifest": {
"license": "MIT",
"name": "artplayer",
"version": "5.1.6",
"main": "dist/artplayer.js",
"legacy": "dist/artplayer.legacy.js",
"types": "types/artplayer.d.ts",
"homepage": "https://artplayer.org",
"author": "Harvey Zack <laozhaochaguan@gmail.com>",
"browserslist": "last 1 Chrome version",
"description": "ArtPlayer.js is a modern and full featured HTML5 video player",
"repository": {
"type": "git",
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
},
"bugs": {
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
},
"keywords": [
"html5",
"video",
"player"
],
"dependencies": {
"option-validator": "^2.0.6"
}
}
}
}
@@ -0,0 +1,74 @@
# PKG-VTT-THUMB-05: browser combination checkpoint
Baseline: `4fa5c68be9d2d0d60d725c2a87b8d92a4dc8a85a`. Task05 remains doing;
this checkpoint does not claim physical-device or complete distribution acceptance.
## Inputs and actual coverage
The new 5.1.6 core snapshot verifies the registry SHA-512, archive SHA-256 and
197 archive members. The browser server verifies the actual main entry before
serving it. This is the source-associated core for usable VTT 1.0.1, not a newly
invented minimum-supported version. Existing frozen 5.1.7, 5.3.0 and 5.4.0 inputs
and the current candidate complete the five-core comparison. Npm 5.3.1 was
previously found absent; 5.3.0 is only an adjacent published stable comparison.
`vtt-thumbnail-combinations.spec.js` covers:
- Candidate plugin on all five cores: actual red/blue preview pixels from DOM
screenshots, real pointer positioning, Chapter progress coexistence, native
video play/pause, web and native fullscreen, source switching without refetch,
unchanged control identity and owned UI removal on destroy.
- Actual published 1.0.2/1.0.3/1.1.0 main bundles on candidate core, and 1.0.1
on 5.1.6: historical callable/default exports, previews, control identities,
source switching and a single VTT fetch. The historical compact-arrow input
requirement is explicit; ordinary-arrow parser failures remain separate tests.
- Android user-agent profiles with synthetic DOM touch payloads: the actual core
gesture handlers emit setBar and perform native media seeking, the preview
follows the drag and its real 500ms timer hides it. This is not trusted OS input
or physical Android/iOS evidence.
- Existing native fetch/abort, malformed input/recovery and lifecycle tests remain.
The current source build is the plugin input. This is not an installed tarball,
every old legacy bundle, a browser-device farm or the online editor. Those gates
remain task06/EX-03 and the relevant device/release tasks. No new dependencies,
runtime code, public types or shippable build artifacts change in this checkpoint.
## Findings and failed runs
VTT 1.0.1 registers `thumbnails`. Actual core 5.1.6 creates its built-in control
only when a thumbnail URL is configured, so the plugin can register normally.
Core 5.1.7 reserves the control unconditionally. The resulting duplicate-name
rejection reproduces on 5.1.7, 5.4.0 and candidate cores in all three engines.
The nine explicit failure assertions are historical evidence, not successful
old-plugin/new-core acceptance. Preserve the current reserved control; any
compatibility accommodation must account for its public identity and duplicate
registration behavior. The pairing is recorded as an open release-review issue.
The initial 27-case run had nine passes and eighteen failures. Fifteen failures
came from test-only setBar calls without the event required by newer core hover
handlers; the tests now use real mouse movement. Three exposed the 1.0.1 collision.
Legal and incompatible combinations now have distinct explicit assertions.
The expanded 69-case run passed. Adding native fullscreen then produced fourteen
passes and one Chromium candidate screenshot timeout. Trace showed actual
fullscreen ownership followed by a hidden preview at screenshot time; cleanup
also timed out after the interrupted screenshot. Mouse positioning now first
uses Playwright's stable/actionable progress hover, then computes the desired
position, and verifies visible preview/background before screenshot. The final
69-case run passes. This changes test interaction timing, not player code, and
does not prove a product fix for every prior timeout. Initial reports are retained;
no retry, skip, timeout increase or weaker pixel expectation was introduced.
## Verification and handoff
`../baselines/vtt-thumbnail-combinations.json` records exact browser versions,
input identities, passes/failures, screenshots/report fingerprints and Node/CI/lint
results. Nine passing assertions deliberately confirm historical incompatibility.
The task remains open for physical-device evidence, final candidate revalidation
and disposition of the old reserved-name pairing; controlled HTTP fixtures do
not establish external CDN or every sprite format's behavior.
The package architecture and environment/browser guides describe actual scope.
Revert this checkpoint as one unit to remove the new route, frozen core snapshot,
combination tests and evidence without reverting the earlier VTT implementation.
Local checkpoint commit only; no push or publication.
+1 -1
View File
@@ -57,7 +57,7 @@ Node10 是 TS 模块解析模式名,不代表支持 Node.js 10。现代 es2020
| artplayer-plugin-jassub / 1.1.0 | ASS、worker/WASM/font 加载、切源/销毁;短 ASS+明确来源字体 | 内嵌资源哈希已有;版本对应、跨源/worker 限制、实际渲染待 | PKG-JASSUB-01/02/05/06 |
| artplayer-plugin-multiple-subtitles / 1.2.0 | VTT 合并/排序/解析错误、URL 回收;双语言/空/坏 VTT | parser 来源头已观察;特有行为和浏览器字幕待 | PKG-MULTI-SUB-01/02/05/06 |
| artplayer-plugin-vast / 1.2.0 | Glomex/Google IMA、广告错误/恢复、重复初始化;供应商测试广告标签 | 依赖版本已记录;实际 IMA 网络/广告流程待,PR 用受控 adapter | PKG-VAST-01/02/05/06 |
| artplayer-plugin-vtt-thumbnail / 1.1.0 | WebVTT 时间和 sprite xywh、图片失败/跨源;本地 VTT+sprite | 五个实际发布归档和可控历史边界/故障已核对;原生图片、浏览器、核心组合仍待 05/06 | PKG-VTT-THUMB-01/02/05/06 |
| artplayer-plugin-vtt-thumbnail / 1.1.0 | WebVTT 时间和 sprite xywh、图片失败/跨源;本地 VTT+sprite | 05 检查点已有五核心桌面像素/Chapter/原生和网页全屏、切源及模拟触摸;1.0.1 控件重名历史失败和真机/分发仍开放,见 vtt-thumbnail-combinations.json | PKG-VTT-THUMB-01/02/05/06 |
| artplayer-proxy-canvas / 1.1.0 | video-like 属性/事件、Canvas 绘制、seek/销毁;MP4 | shim 与实际媒体顺序、跨源/移动待 | PKG-CANVAS-01/02/05/06 |
| artplayer-proxy-mediabunny / 1.2.0 | Mediabunny 1.56.1 当前解析;WebCodecs/AudioContext、HLS/轨道拓扑、AV 同步 | 库依赖不等于 codec 可用;准确 codec/profile、设备能力、长播放待 | PKG-MB-01/02/07/08/09/10 |
| artplayer-tool-iframe / 1.1.0 | 跨窗协议、ready/错误/销毁;同源与两个受控不同 origin 页面 | 消息/嵌套浏览器及沙箱权限待 | PKG-IFRAME-01/02/05/06 |
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 243 项,范围 22 个包及工作区/示例。
状态:todo 58 / doing 15 / blocked 0 / done 170 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 57 / doing 16 / blocked 0 / done 170 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -190,7 +190,7 @@
| PKG-VTT-THUMB-02 | artplayer-plugin-vtt-thumbnail<br>建立特有行为与错误测试 | PKG-VTT-THUMB-01, ENG-03, ENG-05 | VTT 解析、xywh、相对 URL、时间边界、请求失败和定位 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | M | done |
| PKG-VTT-THUMB-03 | artplayer-plugin-vtt-thumbnail<br>整理内部职责与资源 | PKG-VTT-THUMB-02, CORE-09, CORE-19 | 纯解析/区间查找与 DOM、请求/定时器生命周期分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | done |
| PKG-VTT-THUMB-04 | artplayer-plugin-vtt-thumbnail<br>迁移自有源码和公开类型 | PKG-VTT-THUMB-03, ENG-04, ENG-06, CORE-07 | cue/rect/result 和参数可选性保持兼容 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | M | done |
| PKG-VTT-THUMB-05 | artplayer-plugin-vtt-thumbnail<br>验证新旧核心和组合 | PKG-VTT-THUMB-04, CORE-22 | 鼠标和移动进度、全屏、切源、chapter 组合 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
| PKG-VTT-THUMB-05 | artplayer-plugin-vtt-thumbnail<br>验证新旧核心和组合 | PKG-VTT-THUMB-04, CORE-22 | 鼠标和移动进度、全屏、切源、chapter 组合 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | doing |
| PKG-VTT-THUMB-06 | artplayer-plugin-vtt-thumbnail<br>验证分发并同步文档 | PKG-VTT-THUMB-05, ENG-07 | vtt.thumbnail.js、VTT/图片资源解析和产物验证 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | M | todo |
## 5 包迁移:artplayer-plugin-hls-control
@@ -533,6 +533,7 @@
- PKG-VTT-THUMB-02: [记录](baselines/vtt-thumbnail-failures.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-02-failures.md)
- PKG-VTT-THUMB-03: [记录](changes/2026-09-13-PKG-VTT-THUMB-03-resources.md) [记录](baselines/vtt-thumbnail-resources.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-03-parser.md) [记录](baselines/vtt-thumbnail-parser.json)
- PKG-VTT-THUMB-04: [记录](changes/2026-09-13-PKG-VTT-THUMB-04-runtime-types.md) [记录](baselines/vtt-thumbnail-runtime-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-public-types.md) [记录](baselines/vtt-thumbnail-public-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-module-forms.md) [记录](baselines/vtt-thumbnail-module-forms.json) [记录](type-compatibility-policy.md) [记录](baselines/vtt-thumbnail-approved-types.json) [记录](changes/2026-09-13-PKG-VTT-THUMB-04-approved-types.md)
- PKG-VTT-THUMB-05: [记录](changes/2026-09-14-PKG-VTT-THUMB-05-combinations.md) [记录](baselines/vtt-thumbnail-combinations.json) [记录](baselines/vtt-thumbnail-core.json)
- PKG-HLS-01: [记录](baselines/hls-control-contract.md) [记录](baselines/hls-control-release.json) [记录](changes/2026-09-11-PKG-HLS-01-contract.md)
- PKG-HLS-02: [记录](hls-validation.md) [记录](baselines/hls-sdk.json) [记录](baselines/hls-validation.json) [记录](changes/2026-09-11-PKG-HLS-02-tests.md)
- PKG-HLS-03: [记录](changes/2026-09-12-PKG-HLS-03-modules.md) [记录](baselines/hls-modules-validation.json) [记录](hls-validation.md)
+15
View File
@@ -1,5 +1,20 @@
# 进度与证据
## VTT Thumbnail 五核心组合检查点
PKG-VTT-THUMB-05 进入 doing。冻结真实核心5.1.6的197成员,和已有5.1.7、
5.3.0、5.4.0及候选核心验证实际预览截图像素、Chapter、网页/原生全屏、
播放/暂停、切源不重抓VTT及销毁。移动分支为Android UA和合成DOM触摸事件,
不能当真机。最终三浏览器69项通过,其中9项确认1.0.1在5.1.7起的历史控件
重名拒绝;其余60项行为通过。1.0.1/5.1.6合法组合及较新旧插件/新核心另测。
初次漏传测试事件与Chromium全屏截图超时报告保留;后者通过稳定控件后定位
鼠标并显式检查预览可见改善测试,不宣称生产修复。252项VTT、50项CI和lint
通过(1既有warning)。见[检查点](changes/2026-09-14-PKG-VTT-THUMB-05-combinations.md)和[证据](baselines/vtt-thumbnail-combinations.json)。
生产源码/类型/分发及依赖未改,任务/历史重名风险保持开放,未完成真机或打包
验收。243项保持170 done、16 doing、57 todo。下一步MOD-02剩余工程脚本与
模板迁移可独立推进;VAST默认行为选择仍待用户答复。本地提交,无推送/发布。
## Auto Thumbnail 首次 seek 诊断检查点
+1
View File
@@ -260,3 +260,4 @@
| SITE-CODE-GROUP-01 | resolved / 已复现 | VitePress code-group random IDs make identical site inputs emit different output hashes | SITE-BUILD-01 |
| SITE-EDITOR-FAILURE-01 | resolved / 已复现 | Desktop editor evaluates raw TypeScript and cannot settle FileReader errors or boot with denied storage | SITE-03 |
| SITE-EDITOR-AMD-01 | resolved / 已复现 | Late Monaco language AMD initialization races with example dependency loading | SITE-03 |
| VTT-CORE-NAME-01 | open / 已复现 | Published VTT 1.0.1 control name conflicts with the core placeholder introduced in 5.1.7 | PKG-VTT-THUMB-05, REL-08 |
+19
View File
@@ -5873,6 +5873,25 @@
"test/browser/site-editor.spec.js"
],
"resolutionRationale": "Initial real WebKit failure retained; await JS/TS language modules before Run and example dependencies. Delayed-module regression passes on all three engines."
},
{
"id": "VTT-CORE-NAME-01",
"title": "Published VTT 1.0.1 control name conflicts with the core placeholder introduced in 5.1.7",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-VTT-THUMB-05",
"REL-08"
],
"evidence": [
"refactor/changes/2026-09-14-PKG-VTT-THUMB-05-combinations.md",
"refactor/baselines/vtt-thumbnail-combinations.json",
"refactor/baselines/vtt-thumbnail-core.json",
"test/browser/vtt-thumbnail-combinations.spec.js"
],
"compatibleResolution": "Preserve current vtt-thumbnail and reserved core control identities; distinguish the actual working 1.0.1/5.1.6 pair from the already failing 5.1.7/5.4.0/candidate pair. Decide the supported historical pairing/migration or a compatible accommodation during release review without hiding duplicate-control failures.",
"closureCriteria": "Historical working and failing browser pairs remain reproducible; any claimed accommodation preserves reserved-control ownership and duplicate-registration contracts, or an explicit reviewed historical support/migration boundary is recorded.",
"workspaceState": "Final three-engine suite passes nine assertions of this historical rejection, not nine successful compatibility cells. No production control behavior was changed."
}
]
}
+6 -2
View File
@@ -1963,11 +1963,15 @@
"PKG-VTT-THUMB-04",
"CORE-22"
],
"status": "todo",
"status": "doing",
"risk": "M",
"deliverable": "鼠标和移动进度、全屏、切源、chapter 组合",
"acceptance": "最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成",
"evidence": []
"evidence": [
"changes/2026-09-14-PKG-VTT-THUMB-05-combinations.md",
"baselines/vtt-thumbnail-combinations.json",
"baselines/vtt-thumbnail-core.json"
]
},
{
"id": "PKG-VTT-THUMB-06",
+11
View File
@@ -245,3 +245,14 @@ when diagnosing a timeout: the historical failure includes a single ~10-second
evaluate returning an already-recorded restart, not seven seconds of fast empty
reads. These observations do not expand the timeout or waive the open timing and
physical-device acceptance in PKG-CHAPTER-05.
VTT combination tests verify actual preview screenshot pixels, Chapter coexistence,
native/web fullscreen, source switching and cleanup across five recorded core
inputs. The 5.1.6 server route verifies its frozen npm archive/member fingerprints.
Historical 1.0.1 has a distinct valid 5.1.6 pair and explicit later-core name-conflict
tests; expected historical failures are not compatibility passes. Later 1.0.x
compiled bundles receive their documented compact-arrow fixture, while ordinary
syntax failures remain in the historical parser tests. Mobile cases use an Android
UA and synthetic DOM touches through the real core handlers, not trusted hardware
input. Fullscreen mouse placement first waits for the progress control to be stable;
the earlier hidden-preview screenshot timeout remains in the checkpoint evidence.
+6 -1
View File
@@ -79,6 +79,11 @@ const asrCoreMember = `package/${asrCore.manifest.main.replace(/^\.\//, '')}`
const asrCoreBytes = readMember(await ensureArchive(asrCore), asrCoreMember)
assert.equal(hash(asrCoreBytes), asrCore.files[asrCoreMember], 'Adjacent stable ASR core differs from frozen release')
add('/published-5.3.0/artplayer.js', asrCoreBytes, { kind: 'npm-release', version: asrCore.version, integrity: asrCore.integrity, member: asrCoreMember })
const vttCore = JSON.parse(fs.readFileSync(path.join(workspace, 'refactor/baselines/vtt-thumbnail-core.json'), 'utf8')).release
const vttCoreMember = `package/${vttCore.manifest.main.replace(/^\.\//, '')}`
const vttCoreBytes = readMember(await ensureArchive(vttCore), vttCoreMember)
assert.equal(hash(vttCoreBytes), vttCore.files[vttCoreMember], 'Historical VTT core differs from frozen archive')
add('/published-5.1.6/artplayer.js', vttCoreBytes, { kind: 'npm-release', version: vttCore.version, integrity: vttCore.integrity, member: vttCoreMember })
add('/test/audio-tone.m4a', fs.readFileSync(path.join(workspace, 'test/browser/media/audio-tone.m4a')), { kind: 'generated-media', file: 'test/browser/media/audio-tone.m4a' })
add('/test/thumbnail-pattern.mp4', fs.readFileSync(path.join(workspace, 'test/browser/media/thumbnail-pattern.mp4')), { kind: 'generated-media', file: 'test/browser/media/thumbnail-pattern.mp4' })
add('/test/auto-thumbnail-timeline.mp4', fs.readFileSync(path.join(workspace, 'test/browser/media/auto-thumbnail-timeline.mp4')), { kind: 'generated-media', file: 'test/browser/media/auto-thumbnail-timeline.mp4' })
@@ -165,7 +170,7 @@ const server = http.createServer((req, res) => {
if (url.pathname === '/test/player.html') {
const core = url.searchParams.get('core') || 'candidate'
const chapter = url.searchParams.get('chapter') || 'candidate'
assert(['candidate', 'published', 'published-4.5.5', 'published-4.5.9', 'published-5.1.7', 'published-5.3.0', 'published-5.3.1-beta.1'].includes(core) && ['candidate', 'published'].includes(chapter), 'Invalid test combination')
assert(['candidate', 'published', 'published-4.5.5', 'published-4.5.9', 'published-5.1.6', 'published-5.1.7', 'published-5.3.0', 'published-5.3.1-beta.1'].includes(core) && ['candidate', 'published'].includes(chapter), 'Invalid test combination')
const html = fs.readFileSync(path.join(workspace, 'test/browser/player.html'), 'utf8')
.replace('__CORE__', core)
.replace('__CHAPTER__', chapter)
@@ -0,0 +1,203 @@
import { PNG } from 'pngjs'
import { hash } from '../../refactor/scripts/releases.mjs'
import { acceptedVttText, vttThumbnailCandidate, vttThumbnailHistorical } from '../helpers/vtt-thumbnail.js'
import { expect, test } from './fixtures.js'
const candidate = await vttThumbnailCandidate()
const historical = (await vttThumbnailHistorical()).filter(item => /^published-.*-main$/.test(item.name))
const cores = ['published-5.1.6', 'published-5.1.7', 'published-5.3.0', 'published', 'candidate']
const cues = 'WEBVTT\n\n00:00.000 --> 00:04.000\nsprite.svg#xywh=0,0,80,45\n\n00:04.000 --> 00:08.000\nsprite.svg#xywh=80,0,80,45\n'
const sprite = '<svg xmlns="http://www.w3.org/2000/svg" width="160" height="45"><path fill="red" d="M0 0h80v45H0z"/><path fill="blue" d="M80 0h80v45H80z"/></svg>'
function centerPixel(bytes) {
const { width, height, data } = PNG.sync.read(bytes)
const index = (Math.floor(height / 2) * width + Math.floor(width / 2)) * 4
return [...data.subarray(index, index + 4)]
}
async function install(page, core, implementation, testInfo) {
let requests = 0
await page.route('**/test/vtt-combination/cues.vtt', (route) => {
requests++
return route.fulfill({ contentType: 'text/vtt', body: acceptedVttText(implementation, cues) })
})
await page.route('**/test/vtt-combination/sprite.svg', route => route.fulfill({ contentType: 'image/svg+xml', body: sprite }))
await page.goto(`/test/player.html?core=${core}`)
await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; ${implementation.code}; window.vttFactory = module.exports.default || module.exports; })();` })
await page.evaluate(async () => {
window.createPlayer('/test/pattern.mp4', true)
await window.art.plugins.add(window.vttFactory({ vtt: '/test/vtt-combination/cues.vtt' }))
window.vttControl = window.art.controls['vtt-thumbnail'] || window.art.controls.thumbnails
})
await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true)
await testInfo.attach('vtt-combination-inputs', {
contentType: 'application/json',
body: JSON.stringify({ core, implementation: implementation.name, sha256: hash(implementation.code), cueFormat: /^published-1\.0\./.test(implementation.name) ? 'historical compact arrow; ordinary-space failures retained separately' : 'standard spaced arrow', mobile: 'desktop unless test declares an emulated user agent; no physical-device inference' }),
})
return () => requests
}
async function hover(page, percentage) {
const progress = page.locator('.art-control-progress')
await progress.hover()
const bounds = await progress.boundingBox()
await page.mouse.move(bounds.x + bounds.width * percentage, bounds.y + bounds.height / 2)
}
for (const core of cores) {
test(`VTT candidate / ${core}: actual sprite pixels, chapter, native/web fullscreen and source switch`, async ({ page }, testInfo) => {
const requests = await install(page, core, candidate, testInfo)
try {
const preview = page.locator('.art-control-vtt-thumbnail')
const progress = page.locator('.art-control-progress')
const bounds = await progress.boundingBox()
await page.mouse.move(bounds.x + bounds.width * 0.25, bounds.y + bounds.height / 2)
await expect(preview).toHaveCSS('background-position', '0px 0px')
await expect(preview).toBeVisible()
const red = await preview.screenshot()
expect(centerPixel(red)).toEqual([255, 0, 0, 255])
await testInfo.attach('vtt-red-cell', { contentType: 'image/png', body: red })
await page.mouse.move(bounds.x + bounds.width * 0.75, bounds.y + bounds.height / 2)
await expect(preview).toHaveCSS('background-position', '-80px 0px')
const blue = await preview.screenshot()
expect(centerPixel(blue)).toEqual([0, 0, 255, 255])
await testInfo.attach('vtt-blue-cell', { contentType: 'image/png', body: blue })
await page.click('#play')
await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.1)
await page.click('#pause')
await page.evaluate(() => {
window.art.fullscreenWeb = true
})
await expect.poll(() => page.evaluate(() => window.art.fullscreenWeb)).toBe(true)
await hover(page, 0.25)
await expect(preview).toHaveCSS('background-position', '0px 0px')
expect(centerPixel(await preview.screenshot())).toEqual([255, 0, 0, 255])
await page.evaluate(async () => {
window.art.fullscreenWeb = false
await window.art.switchUrl('/test/pattern.mp4?second')
})
await hover(page, 0.75)
await expect(preview).toHaveCSS('background-position', '-80px 0px')
expect(await page.evaluate(() => window.vttControl === window.art.controls['vtt-thumbnail'])).toBe(true)
expect(requests()).toBe(1)
expect(await page.evaluate(() => Boolean(window.art.plugins.artplayerPluginChapter))).toBe(true)
await expect(page.locator('.art-chapter')).toHaveCount(1)
await page.evaluate(() => {
window.vttFullscreen = []
window.art.on('fullscreen', value => window.vttFullscreen.push(value))
document.querySelector('#play').onclick = () => {
window.art.fullscreen = true
}
})
expect(await page.evaluate(() => Boolean(document.fullscreenEnabled || document.webkitFullscreenEnabled))).toBe(true)
await page.locator('#play').click()
await expect.poll(() => page.evaluate(() => (document.fullscreenElement || document.webkitFullscreenElement) === window.art.template.$player)).toBe(true)
await hover(page, 0.75)
await expect(preview).toBeVisible()
await expect(preview).toHaveCSS('background-position', '-80px 0px')
expect(centerPixel(await preview.screenshot())).toEqual([0, 0, 255, 255])
expect(await page.evaluate(() => (document.fullscreenElement || document.webkitFullscreenElement).contains(window.vttControl))).toBe(true)
await page.evaluate(() => {
window.art.fullscreen = false
})
await expect.poll(() => page.evaluate(() => Boolean(document.fullscreenElement || document.webkitFullscreenElement))).toBe(false)
await expect.poll(() => page.evaluate(() => window.vttFullscreen)).toEqual([true, false])
await page.evaluate(() => window.art.destroy(false))
await expect(preview).toHaveCount(0)
}
finally {
await page.evaluate(() => {
if (!window.art.isDestroy)
window.art.destroy()
})
}
})
}
for (const implementation of historical) {
const core = implementation.profile === 'old-control' ? 'published-5.1.6' : 'candidate'
test(`VTT ${implementation.name} / ${core}: legal old calls preserve preview and control identity`, async ({ page }, testInfo) => {
const requests = await install(page, core, implementation, testInfo)
try {
const name = implementation.profile === 'old-control' ? 'thumbnails' : 'vtt-thumbnail'
const preview = page.locator(`.art-control-${name}`)
const bounds = await page.locator('.art-control-progress').boundingBox()
await page.mouse.move(bounds.x + bounds.width * 0.75, bounds.y + bounds.height / 2)
await expect(preview).toHaveCSS('background-position', '-80px 0px')
expect(centerPixel(await preview.screenshot())).toEqual([0, 0, 255, 255])
expect(await page.evaluate(name => window.art.controls[name] === window.vttControl, name)).toBe(true)
await page.evaluate(async () => {
await window.art.switchUrl('/test/pattern.mp4?old-plugin')
})
await hover(page, 0.25)
await expect(preview).toHaveCSS('background-position', '0px 0px')
expect(requests()).toBe(1)
}
finally { await page.evaluate(() => window.art.destroy()) }
})
}
for (const core of ['published-5.1.7', 'published', 'candidate']) {
test(`VTT 1.0.1 / ${core}: pre-existing reserved thumbnails name conflict is retained as historical evidence`, async ({ page }, testInfo) => {
const implementation = historical.find(item => item.version === '1.0.1')
await page.route('**/test/vtt-conflict.vtt', route => route.fulfill({ contentType: 'text/vtt', body: acceptedVttText(implementation, cues) }))
await page.goto(`/test/player.html?core=${core}`)
await page.addScriptTag({ content: `(() => { const module = { exports: {} }; const exports = module.exports; ${implementation.code}; window.vttFactory = module.exports.default || module.exports; })();` })
const state = await page.evaluate(async () => {
window.createPlayer('/test/pattern.mp4')
const original = window.art.controls.thumbnails
try {
await window.art.plugins.add(window.vttFactory({ vtt: '/test/vtt-conflict.vtt' }))
return { error: null }
}
catch (error) {
return { error: error.message, sameReservedControl: original === window.art.controls.thumbnails }
}
finally { window.art.destroy() }
})
expect(state.error).toContain('Can\'t add an existing [thumbnails] to the [control]')
expect(state.sameReservedControl).toBe(true)
await testInfo.attach('vtt-historical-conflict', { contentType: 'application/json', body: JSON.stringify({ core, plugin: implementation.name, sha256: hash(implementation.code), state, scope: 'Existing incompatibility, not successful old-plugin/new-core acceptance and not a newly introduced refactor regression' }) })
})
}
test.describe('VTT mobile event integration', () => {
test.use({ userAgent: 'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 Chrome/120.0.0.0 Mobile Safari/537.36', hasTouch: true })
for (const core of cores) {
test(`VTT candidate / ${core}: emulated mobile drag routes through core progress and releases hiding timer`, async ({ page }, testInfo) => {
await install(page, core, candidate, testInfo)
const sample = await page.evaluate(() => {
const art = window.art
const progress = art.template.$progress
const box = progress.getBoundingClientRect()
const events = []
art.on('setBar', (type, percentage, event) => {
if (event)
events.push({ type, percentage, nativeType: event.type })
})
function touch(type, percentage) {
const x = box.left + box.width * percentage
const y = box.top + box.height / 2
const point = { identifier: 1, target: progress, clientX: x, clientY: y, pageX: x + scrollX, pageY: y + scrollY }
const event = new Event(type, { bubbles: true, cancelable: true })
Object.defineProperties(event, { touches: { value: type === 'touchend' ? [] : [point] }, changedTouches: { value: [point] } })
progress.dispatchEvent(event)
}
touch('touchstart', 0.25)
touch('touchmove', 0.75)
touch('touchend', 0.75)
const control = art.controls['vtt-thumbnail']
return { mobile: window.Artplayer.utils.isMobile, events, position: control.style.backgroundPosition, display: control.style.display, time: art.currentTime, duration: art.duration }
})
expect(sample.mobile).toBe(true)
expect(sample.events.some(event => event.nativeType === 'touchmove' && event.type === 'played')).toBe(true)
expect(sample.display).toBe('flex')
expect(sample.position).toBe('-80px 0px')
expect(sample.time / sample.duration).toBeGreaterThan(0.5)
await expect(page.locator('.art-control-vtt-thumbnail')).toHaveCSS('display', 'none')
await page.evaluate(() => window.art.destroy(false))
await expect(page.locator('.art-control-vtt-thumbnail')).toHaveCount(0)
await testInfo.attach('vtt-mobile-event-integration', { contentType: 'application/json', body: JSON.stringify({ core, sample, scope: 'Android user agent and synthetic DOM touch payloads through actual core handlers; native media seek and real hide timer. Not trusted OS touch, real Android, or iOS Safari acceptance.' }) })
})
}
})